Page 1 of 1

matrices multiplication

Posted: Sun Oct 11, 2020 11:53 am
by Antonio Linares

Code: Select all

function Main()

   ? MatrixMult( { { 1, 2 }, { 3, 4 } },;
                 { { 11, 12 }, { 13, 14 } } )
          
return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aRowMatrix1, aRowMatrix2, nValRowMatrix1
   local aResult := Array( nRowsMatrix1, nColsMatrix2  ), nSum
   
   aMatrix2 = ArrTranspose( aMatrix2, .F. )
   
   for each aRowMatrix1 in aMatrix1
      for each aRowMatrix2 in aMatrix2
        nSum = 0
        for each nValRowMatrix1 in aRowMatrix1
          ? nValRowMatrix1, aRowMatrix2[ nValRowMatrix1:__enumIndex ]
          nSum += nValRowMatrix1 * aRowMatrix2[ nValRowMatrix1:__enumIndex ]
        next
        aResult[ aRowMatrix1:__enumIndex, aRowMatrix2:__enumIndex ] = nSum
      next        
   next      

return aResult

function ArrTranspose( aArray, lSquare )

   local nRows, nCols, nRow, nCol, nWidth
   local aNew

   // DEFAULT lSquare := .f.

   nRows          := Len( aArray )
   if lSquare
      nCols       := Len( aArray[ 1 ] )
   else
      nCols       := 1
      for nRow := 1 to nRows
         if ValType( aArray[ nRow ] ) == 'A'
            nCols    := Max( nCols, Len( aArray[ nRow ] ) )
         endif
      next
   endif

   aNew           := Array( nCols, nRows )
   for nRow := 1 to nRows
      if ValType( aArray[ nRow ] ) == 'A'
         nWidth  := Len( aArray[ nRow ] )
         for nCol := 1 to nWidth
            aNew[ nCol, nRow ]   := aArray[ nRow, nCol ]
         next
      else
         aNew[ 1, nRow ]      := aArray[ nRow ]
      endif
   next

return aNew

   
   
 
1 11
2 13
1 12
2 14
3 11
4 13
3 12
4 14
{{37, 40}, {85, 92}}

Re: matrices multiplication

Posted: Mon Oct 12, 2020 10:14 am
by Antonio Linares
Image

Re: matrices multiplication

Posted: Mon Oct 12, 2020 10:27 am
by AntoninoP
Nice, now some home work: :wink:
Image

I tryed:

Code: Select all

function Main()
   LOCAL a := { { 1, 2, 3 }, { 4, 5, 6 } }
   LOCAL b := { { 11, 12 }, { 13, 14 }, { 15, 16 } }
   ? hb_ValToExp(MatrixMult( a,b ))
   ? hb_ValToExp(MatrixMult( b,a ))

return nil
and the result is
Image

Re: matrices multiplication

Posted: Mon Oct 12, 2020 10:54 am
by AntoninoP
The fix is pretty simple, you swapped row and col creating the result, here the correct creation:

Code: Select all

function MatrixMult( aMatrix1, aMatrix2 )

   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aRowMatrix1, aRowMatrix2, nValRowMatrix1
   local aResult := Array( nRowsMatrix1, nColsMatrix2  ), nSum
in the original was

Code: Select all

 local aResult := Array( nColsMatrix1, nRowsMatrix2 )

Re: matrices multiplication

Posted: Mon Oct 12, 2020 11:46 am
by Antonio Linares
Dear Antonino,

Fixed in my original post

many thanks!

Mr. Rao has managed to implement an enhanced version that does not need the ArrTranspose() call.
It will be included in the next FWH build:

Code: Select all

function MatrixMult( matrix1, matrix2 )

   local MatrixA, MatrixB, i, j, nRow, nCol, nRows, nCols, nSize, result, dot_product
   local cType

   // Check for scalar multiplication
   cType    := ValType( matrix1 ) + ValType( matrix2 )
   if cType != "AA"
      if cType == "NN"
         return matrix1 * matrix2
      elseif cType == "NA" .or. cType == "AN"
         if cType == "NA"
            i        := matrix1
            MatrixA  := matrix2
         else
            i        := matrix2
            MatrixA  := matrix1
         endif
         if !HB_ISARRAY( MatrixA[ 1 ] ); MatrixA := { MatrixA }; endif
         nSize       := Len( MatrixA[ 1 ] )
         for nRow := 1 to Len( MatrixA )
            for nCol := 1 to nSize
               MatrixA[ nRow, nCol ] *= i
            next
         next
         return MatrixA
      else
         ? "Invalid params"
         return nil
      endif
   endif

   if Empty( matrix1 ) .or. Empty( matrix2 )
      ? "Empty matrix"
      return nil
   endif

   // Check for single-dim arrays
   if !( HB_ISARRAY( matrix1[ 1 ] ) ); matrix1 := { matrix1 }; endif
   if !( HB_ISARRAY( matrix2[ 1 ] ) ); AEval( matrix2, { |x,i| matrix2[ i ] := { x } } ); endif

   MatrixA  := matrix1
   MatrixB  := matrix2

   // Actual Matrix Multiplication
   result   := Array( nRows := Len( MatrixA ), nCols := Len( MatrixB[ 1 ] ) )

   for nRow := 1 to nRows
      for nCol := 1 to nCols
         dot_product    := 0
         TRY
            AEval( MatrixA[ nRow ], { |n,i| dot_product += n * MatrixB[ i, nCol ] } )
         CATCH
         END
         result[ nRow, nCol ] := dot_product
      next
   next

return result
 

Re: matrices multiplication

Posted: Mon Oct 12, 2020 11:50 am
by nageswaragunupudi
All the new matrix functions are still under testing and may still need some fixes.

Re: matrices multiplication

Posted: Mon Oct 12, 2020 3:13 pm
by cnavarro
With ArrTranspose

Code: Select all


function Main()

   // [ 2, 2 ] x [ 2, 2 ] = [ 2, 2 ]
   local aMatriz1 := { { 1, 2 }, { 3, 4 } }
   local aMatriz2 := { { 11, 12 }, { 13, 14 } }

   // [ 1, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 2, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 }, { 1, 0, -1 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 1, 3 ] x [ 3, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4, 2 }, { 5, 0 }, { 6, 0 } }

   // [ 1, 2 ] x [ 2, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, 5 } }
   //local aMatriz2 := { { 1, 2 }, { -2, 0 } }

   // [ 2, 2 ] x [ 2, 3 ] = [ 2, 3 ]
   //local aMatriz1 := { { 1, 2 }, { -2, 0 } }
   //local aMatriz2 := { { 1, 0, 2 }, { 0, 2, 0 } }

   // [ 1, 2 ] x [ 2, 1 ] = [ 1, 1 ]
   //local aMatriz1 := { { 1, -1 } }
   //local aMatriz2 := { { 5 }, { 5 } }

   // [ 3, 2 ] x [ 2, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, 2 }, { 0, -1 }, { 0, 1 } }
   //local aMatriz2 := { { 0, 3, 0 }, { 3, 0, 3 } }

   // [ 3, 3 ] x [ 3, 1 ] = [ 3, 1 ]
   //local aMatriz1 := { { 1, 0, 2 }, { 0, 2, 0 }, { 0, 1, 3 } }
   //local aMatriz2 := { { 5 }, { -1 }, { 0 } }

   // [ 3, 3 ] x [ 3, 2 ] = [ 3, 2 ]
   //local aMatriz1 := { { 1, 2, 3 }, { 0, 1, 0 }, { 3, 2, 1 } }
   //local aMatriz2 := { { 1, -1 }, { 0, 2 }, { -2, 0 } }

   // [ 3, 3 ] x [ 3, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, -1, 1 }, { 2, 2, 3 }, { -2, -3, -1 } }
   //local aMatriz2 := { { 1, 0, 4 }, { 0, 2, 5 }, { 1, 3, 0 } }


   // [ 2, 3 ] x [ 3, 2 ] = [ 2, 2 ]
   //local aMatriz1 := { { 1, 2, 6 }, { 3, 4, 9 } }
   //local aMatriz2 := { { 11, 12 }, { 13, 14 }, { 6, 9 } }

   if Len( aMatriz1[ 1 ] ) = Len( aMatriz2 )
      MatrixMult( aMatriz1, aMatriz2 )
   else
      ? "Only multiply matrix if number columns first matrix equal to number rows second matrix"
   endif
         
return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local x
   local y
   local z
   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix1 := Len( aMatrix1[ 1 ] )
   local nRowsMatrix2 := Len( aMatrix2 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aResult := Array( nRowsMatrix1, nColsMatrix2  )
   local nSum    := 0
   local nVal    := 0
   local nIter   := 0
   local aRowMatrix1
   local aRowMatrix2
   local nValRowMatrix1

   // Show Matrix1, Matrix2   
   ?
   For x = 1 to Len( aMatrix1 )
      ?? "[ " 
      For y = 1 to Len( aMatrix1[ x ] )
         ?? aMatrix1[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x
   ?
   For x = 1 to Len( aMatrix2 )
      ?? "[ " 
      For y = 1 to Len( aMatrix2[ x ] )
         ?? aMatrix2[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

   aMatrix2 = ArrTranspose( aMatrix2, .F. )
   ? "Transpose Matrix2"
   ?
   For x = 1 to Len( aMatrix2 )
      ?? "[ " 
      For y = 1 to Len( aMatrix2[ x ] )
         ?? aMatrix2[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

   // Multiply matrix

   For x = 1 to Len( aMatrix1 )
      nSum   := 0
      aRowMatrix1 := aMatrix1[ x ]
      For y = 1 to nColsMatrix2 
          aRowMatrix2 := aMatrix2[ y ]
          nSum   := 0
          For z = 1 to Len( aRowMatrix2 )
             nVal := aRowMatrix1[ z ] * aRowMatrix2[ z ]
             nSum += nVal
          Next z
          aResult[ x ][ y ] := nSum
      Next y
   Next x

   // Show Result
   ? "Result"
   ?
   For x = 1 to Len( aResult )
      ?? "[ " 
      For y = 1 to Len( aResult[ x ] )
         ?? aResult[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

return aResult

function ArrTranspose( aArray, lSquare )

   local nRows, nCols, nRow, nCol, nWidth
   local aNew

   // DEFAULT lSquare := .f.

   nRows          := Len( aArray )
   if lSquare
      nCols       := Len( aArray[ 1 ] )
   else
      nCols       := 1
      for nRow := 1 to nRows
         if ValType( aArray[ nRow ] ) == 'A'
            nCols    := Max( nCols, Len( aArray[ nRow ] ) )
         endif
      next
   endif

   aNew           := Array( nCols, nRows )
   for nRow := 1 to nRows
      if ValType( aArray[ nRow ] ) == 'A'
         nWidth  := Len( aArray[ nRow ] )
         for nCol := 1 to nWidth
            aNew[ nCol, nRow ]   := aArray[ nRow, nCol ]
         next
      else
         aNew[ 1, nRow ]      := aArray[ nRow ]
      endif
   next

return aNew

 

Re: matrices multiplication

Posted: Mon Oct 12, 2020 8:24 pm
by cnavarro
Without ArrTranspose

Code: Select all


function Main()

   // [ 2, 2 ] x [ 2, 2 ] = [ 2, 2 ]
   local aMatriz1 := { { 1, 2 }, { 3, 4 } }
   local aMatriz2 := { { 11, 12 }, { 13, 14 } }

   // [ 1, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 2, 3 ] x [ 3, 1 ] = [ 2, 1 ]
   //local aMatriz1 := { { 1, -2, 3 }, { 1, 0, -1 } }
   //local aMatriz2 := { { 4 }, { 5 }, { 6 } }

   // [ 1, 3 ] x [ 3, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, -2, 3 } }
   //local aMatriz2 := { { 4, 2 }, { 5, 0 }, { 6, 0 } }

   // [ 1, 2 ] x [ 2, 2 ] = [ 1, 2 ]
   //local aMatriz1 := { { 1, 5 } }
   //local aMatriz2 := { { 1, 2 }, { -2, 0 } }

   // [ 2, 2 ] x [ 2, 3 ] = [ 2, 3 ]
   //local aMatriz1 := { { 1, 2 }, { -2, 0 } }
   //local aMatriz2 := { { 1, 0, 2 }, { 0, 2, 0 } }

   // [ 1, 2 ] x [ 2, 1 ] = [ 1, 1 ]
   //local aMatriz1 := { { 1, -1 } }
   //local aMatriz2 := { { 5 }, { 5 } }

   // [ 3, 2 ] x [ 2, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, 2 }, { 0, -1 }, { 0, 1 } }
   //local aMatriz2 := { { 0, 3, 0 }, { 3, 0, 3 } }

   // [ 3, 3 ] x [ 3, 1 ] = [ 3, 1 ]
   //local aMatriz1 := { { 1, 0, 2 }, { 0, 2, 0 }, { 0, 1, 3 } }
   //local aMatriz2 := { { 5 }, { -1 }, { 0 } }

   // [ 3, 3 ] x [ 3, 2 ] = [ 3, 2 ]
   //local aMatriz1 := { { 1, 2, 3 }, { 0, 1, 0 }, { 3, 2, 1 } }
   //local aMatriz2 := { { 1, -1 }, { 0, 2 }, { -2, 0 } }

   // [ 3, 3 ] x [ 3, 3 ] = [ 3, 3 ]
   //local aMatriz1 := { { 1, -1, 1 }, { 2, 2, 3 }, { -2, -3, -1 } }
   //local aMatriz2 := { { 1, 0, 4 }, { 0, 2, 5 }, { 1, 3, 0 } }


   // [ 2, 3 ] x [ 3, 2 ] = [ 2, 2 ]
   //local aMatriz1 := { { 1, 2, 6 }, { 3, 4, 9 } }
   //local aMatriz2 := { { 11, 12 }, { 13, 14 }, { 6, 9 } }

   if Len( aMatriz1[ 1 ] ) = Len( aMatriz2 )
      MatrixMult( aMatriz1, aMatriz2 )
   else
      ? "Only multiply matrix if number columns first matrix equal to number rows second matrix"
   endif
         
return nil

function ShowMatrix( aMatrix )

   local x
   local y

   ?
   For x = 1 to Len( aMatrix )
      ?? "[ " 
      For y = 1 to Len( aMatrix[ x ] )
         ?? aMatrix[ x ][ y ]
         ??  "   "
      Next y
      ?? " ]" 
      ? 
   Next x

Return nil


function MatrixMult( aMatrix1, aMatrix2 )

   local x
   local y
   local z
   local nRowsMatrix1 := Len( aMatrix1 )
   local nColsMatrix1 := Len( aMatrix1[ 1 ] )
   local nRowsMatrix2 := Len( aMatrix2 )
   local nColsMatrix2 := Len( aMatrix2[ 1 ] )
   local aResult := Array( nRowsMatrix1, nColsMatrix2  )
   local nSum    := 0
   local nVal0   := 0
   local nVal1   := 0
   local nIter   := 0

   ShowMatrix( aMatrix1 )
   ShowMatrix( aMatrix2 )

   For x = 1 to Len( aMatrix1 )
      For y = 1 to nColsMatrix2
         nSum   := 0
         For z = 1 to nRowsMatrix2
            nVal0  := aMatrix1[ x ][ z ]
            nVal1 := nVal0 * aMatrix2[ z ][ y ]
            nSum  += nVal1
         Next z
         aResult[ x ][ y ] := nSum
      Next y
   Next x

   ? "Resultado"
   ShowMatrix( aResult )

return aResult


 

Re: matrices multiplication

Posted: Tue Oct 13, 2020 7:36 am
by Antonio Linares
Shortest version ? :-)

Code: Select all

function Main()

   ? MatrixMult( { { 1, 2 }, { 3, 4 } },;
                 { { 11, 12 }, { 13, 14 } } )

return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local aRowMatrix1, nColMatrix2, nRowMatrix2
   local aResult := Array( Len( aMatrix1 ), Len( aMatrix2[ 1 ] ) )

   for each aRowMatrix1 in aMatrix1
      for nColMatrix2 = 1 to Len( aMatrix2[ 1 ] )
         nSum = 0
         for nRowMatrix2 = 1 to Len( aMatrix2 )
            nSum += aRowMatrix1[ nRowMatrix2 ] * aMatrix2[ nRowMatrix2 ][ nColMatrix2 ]
         next 
         aResult[ aRowMatrix1:__enumIndex ][ nColMatrix2 ] := nSum
      next 
   next    
   
return aResult  
{{37, 40}, {85, 92}}

Re: matrices multiplication

Posted: Tue Oct 13, 2020 8:22 am
by Antonio Linares
Shortest version based on Mr. Rao version:

Code: Select all

function Main()

   ? MatrixMult( { { 1, 2 }, { 3, 4 } },;
                 { { 11, 12 }, { 13, 14 } } )

return nil

function MatrixMult( aMatrix1, aMatrix2 )

   local aRowMatrix1, nSum, nCols := Len( aMatrix2[ 1 ] )
   local aResult := Array( Len( aMatrix1 ), nCols )

   for each aRowMatrix1 in aMatrix1
      for nCol := 1 to nCols
         nSum = 0
         AEval( aRowMatrix1, { |n,i| nSum += n * aMatrix2[ i, nCol ] } )
         aResult[ aRowMatrix1:__enumIndex, nCol ] = nSum
      next
   next

return aResult
 
{{37, 40}, {85, 92}}
{ { 1*11 + 2*13, 1*12 + 2*14 }, { 3*11 + 4*13, 3*12 + 4*14 }}

Re: matrices multiplication

Posted: Tue Oct 13, 2020 5:58 pm
by Silvio.Falconi
I am very intrigued, I did not understand what you are trying to do, I want to participate too if it comes to things to eat (cakes, sweets, ..) even if I have to go on a diet I know !!!

Re: matrices multiplication

Posted: Tue Oct 13, 2020 6:09 pm
by Antonio Linares

Re: matrices multiplication

Posted: Tue Oct 13, 2020 6:54 pm
by Silvio.Falconi
Dear antonio

I know that Python

it is a multi-paradigm language, which supports both procedural programming (which makes use of functions) and object-oriented programming (including features such as single and multiple inheritance, but Harbor also supports these two things. and then I don't understand what is needed to convert programs made on python to harbour that is, I do not see the need, if you have something else in mind that I do not know I raise my hands
a colleague of mine ( school) builds programs with python but uses additional tools for graphics and more (TkInter which also includes the graphical interface management system, which is what you see when you use the program. Other tools to mention are PYQt and wxPython.), he use pyton to create games (PyGame, PyKyra and the 3D rendering engines)

There are things that Python can't do well, or at all.

For example it is not a low-level language and therefore not good for creating components such as drivers.

It is not suitable for creating cross-platform executables and it is not even the ideal choice if the code must be as fast as possible.

Historically it has been mainly used for scripting and automation elements in fact my colleague uses it with Arduino

Re: matrices multiplication

Posted: Tue Oct 13, 2020 9:21 pm
by Antonio Linares
Dear Silvio,

My interest in porting those 9 lines from Python to Harbour is in building a small and simple neural network to be used from Harbour and mainly for learning purposes :-)