matrices multiplication

Post Reply
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

matrices multiplication

Post 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}}
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: matrices multiplication

Post by Antonio Linares »

Image
regards, saludos

Antonio Linares
www.fivetechsoft.com
AntoninoP
Posts: 347
Joined: Tue Feb 10, 2015 9:48 am
Location: Albenga, Italy
Contact:

Re: matrices multiplication

Post 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
AntoninoP
Posts: 347
Joined: Tue Feb 10, 2015 9:48 am
Location: Albenga, Italy
Contact:

Re: matrices multiplication

Post 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 )
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: matrices multiplication

Post 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
 
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
nageswaragunupudi
Posts: 8017
Joined: Sun Nov 19, 2006 5:22 am
Location: India
Contact:

Re: matrices multiplication

Post by nageswaragunupudi »

All the new matrix functions are still under testing and may still need some fixes.
Regards

G. N. Rao.
Hyderabad, India
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: matrices multiplication

Post 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

 
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
User avatar
cnavarro
Posts: 5792
Joined: Wed Feb 15, 2012 8:25 pm
Location: España

Re: matrices multiplication

Post 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


 
C. Navarro
Hay dos tipos de personas: las que te hacen perder el tiempo y las que te hacen perder la noción del tiempo
Si alguien te dice que algo no se puede hacer, recuerda que esta hablando de sus limitaciones, no de las tuyas.
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: matrices multiplication

Post 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}}
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: matrices multiplication

Post 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 }}
regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Silvio.Falconi
Posts: 4956
Joined: Thu Oct 18, 2012 7:17 pm

Re: matrices multiplication

Post 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 !!!
I use : FiveWin for Harbour August 2020 (Revision) - Harbour 3.2.0dev (r1712141320) - Bcc7.30 - xMate ver. 1.15.3 - PellesC
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: matrices multiplication

Post by Antonio Linares »

regards, saludos

Antonio Linares
www.fivetechsoft.com
User avatar
Silvio.Falconi
Posts: 4956
Joined: Thu Oct 18, 2012 7:17 pm

Re: matrices multiplication

Post 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
I use : FiveWin for Harbour August 2020 (Revision) - Harbour 3.2.0dev (r1712141320) - Bcc7.30 - xMate ver. 1.15.3 - PellesC
User avatar
Antonio Linares
Site Admin
Posts: 37481
Joined: Thu Oct 06, 2005 5:47 pm
Location: Spain
Contact:

Re: matrices multiplication

Post 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 :-)
regards, saludos

Antonio Linares
www.fivetechsoft.com
Post Reply