Jump to content
nullschritt

Problem Storing Arrays Inside Arrays

Recommended Posts

Thanks czardas, currently it is limited for integer range only.  :whistle:

I wanted to show the calculation of the invers matrix. The fraction problem isn't solved for sure.

Edited by UEZ

Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

I wouldn't give up on it altogether. Sometimes taking a step back gives you more perspective. In all honesty I'm reasonably happy with the UDF, but not quite as happy as I originally wanted to be.

Regarding division by zero. You can do it as much as you like using _Fraction() so long as you do not try and access the non-existent array afterwards. That's where the interpreter throws an error. The same applies with numbers: after division by zero infinity is returned (or rather a representation of infinity) and AutoIt does not throw an error. Of course it's wrong to divide by zero in both cases and I have no intentions of overriding the current behaviour. All the checks you need are already provided.

 

So all I have to do then is make it return the invalid fraction instead of an error, the

Here a fast hack for a 2x2 matrix:

;a fast hack version by UEZ
#include <Array.au3>
#include <EditConstants.au3>
#include <StaticConstants.au3>
#include <WindowsConstants.au3>
#include <GUIConstantsEx.au3>

Global $hGUI = GUICreate("2x2 Matrix Invers", 500, 306, -1, -1)
Global $iLabel = GUICtrlCreateLabel("2x2 Matrix Invers", 40, 20, 400, 40, $SS_CENTER)
GUICtrlSetFont(-1, 20, 400, 0, "Arial", 5)
Global $hLabel2 = GUICtrlCreateLabel("Matrix A", 80, 90, 100, 28, $SS_CENTER)
GUICtrlSetFont(-1, 20, 400, 0, "Times New Roman", 5)
Global $iInput_A = GUICtrlCreateInput("4.25", 80, 130, 40, 30)
Global $iInput_B = GUICtrlCreateInput("7/2", 130, 130, 40, 30)
Global $iInput_C = GUICtrlCreateInput("3", 80, 165, 40, 30)
Global $iInput_D = GUICtrlCreateInput("2", 130, 165, 40, 30)
Global $hLabel3 = GUICtrlCreateLabel("Matrix A'", 280, 90, 100, 28, $SS_CENTER)
GUICtrlSetFont(-1, 20, 400, 0, "Times New Roman", 5)
Global $iInput_Ai = GUICtrlCreateInput("", 280, 130, 60, 30, $ES_READONLY)
Global $iInput_Bi = GUICtrlCreateInput("", 350, 130, 60, 30, $ES_READONLY)
Global $iInput_Ci = GUICtrlCreateInput("", 280, 165, 60, 30, $ES_READONLY)
Global $iInput_Di = GUICtrlCreateInput("", 350, 165, 60, 30, $ES_READONLY)
Global $iButton = GUICtrlCreateButton("Calculate", 280, 230, 90, 60)
GUISetState()

While 1
    Switch GUIGetMsg()
        Case $GUI_EVENT_CLOSE
            GUIDelete()
            Exit
        Case $iButton
            Calc_InversMatrix()
    EndSwitch
WEnd

Func Calc_InversMatrix()
    Local $aMatrix[2][2] = [[Execute(GUICtrlRead($iInput_A)), Execute(GUICtrlRead($iInput_b))],[Execute(GUICtrlRead($iInput_C)), Execute(GUICtrlRead($iInput_D))]]
    If Not $aMatrix[1][0] And Not $aMatrix[1][1] Then Return SetError(1, 0, 0) ; -> determinant is zero, therefore inverse matrix doesn't exist
    Local $fDetA = 1 / ($aMatrix[0][0] * $aMatrix[1][1] - $aMatrix[1][0] * $aMatrix[0][1])
    GUICtrlSetData($iInput_Ai, Float2Frac(Number($fDetA * $aMatrix[1][1])))
    GUICtrlSetData($iInput_Bi, Float2Frac(Number($fDetA * -$aMatrix[0][1])))
    GUICtrlSetData($iInput_Ci, Float2Frac(Number($fDetA * -$aMatrix[1][0])))
    GUICtrlSetData($iInput_Di, Float2Frac(Number($fDetA * $aMatrix[0][0])))
EndFunc

Func Float2Frac($fFloat) ;coded by UEZ
    If Not IsNumber($fFloat) Then Return SetError(1, 0, 0)
    Local Const $iDec = StringLen(StringRegExpReplace($fFloat, "\d+\.(\d*)", "\1"))
    Local Const $iZaehler = $fFloat * 10^$iDec
    Local Const $iNenner = 10^$iDec
    Local Const $iGGT = ggT($iZaehler, $iNenner)
    ConsoleWrite($fFloat & " -> " & $iZaehler / $iGGT & " / "  & $iNenner / $iGGT & @CRLF)
    Return $iZaehler / $iGGT & " / "  & $iNenner / $iGGT
EndFunc

Func ggT($a, $b) ;coded by UEZ 2012
    If Not IsInt($a) Then Return SetError(1, 0, 0)
    If Not IsInt($b) Then Return SetError(2, 0, 0)
    If $a = $b Then Return Abs($a)
    If Not $a And $b Then Return Abs($a)
    If $a And Not $b Then Return Abs($b)
    If ($a And $b = 1) Or ($a = 1 And $b) Then Return 1
    Local $iMod
    Do
        $iMod = Mod($a, $b)
        If Not $iMod Then ExitLoop
        $a = $b
        $b = $iMod
    Until False
    Return $b
EndFunc

That looks fantastically streamlined but I don't understand a bit of it. What would I need to change to make it work with 8x8 arrays?

Share this post


Link to post
Share on other sites

So all I have to do then is make it return the invalid fraction instead of an error, the

 

You may get further forward, but I imagine the calculations producing infinity are not needed. The code appears to loop through an array, find an empty string, convert it to a number, divide by this number and then you want to override the error which occurs - at least I think that is what's happening. This is not a good approach. The whole thing needs rewriting from the very beginning.

Edited by czardas

Share this post


Link to post
Share on other sites

That looks fantastically streamlined but I don't understand a bit of it. What would I need to change to make it work with 8x8 arrays?

First, you need to understand the math behind. Have a look here (Cramer's rule): http://en.wikipedia.org/wiki/Cramer%27s_rule or at Wiki: http://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

I believe it would first be very useful to precisely describe the goal and the algorithm you want to implement, demonstrate its correctness, then only work out a toy example with solid grounds (i.e. BigNum even if it's slow as hell).

From this point you'd know if it's worth going further and creating an interface layer to a suitable library. BTW, isn't >Eigen good for you?


This wonderful site allows debugging and testing regular expressions (many flavors available). An absolute must have in your bookmarks.
Another excellent RegExp tutorial. Don't forget downloading your copy of up-to-date pcretest.exe and pcregrep.exe here
RegExp tutorial: enough to get started
PCRE v8.33 regexp documentation latest available release and currently implemented in AutoIt beta.

SQLitespeed is another feature-rich premier SQLite manager (includes import/export). Well worth a try.
SQLite Expert (freeware Personal Edition or payware Pro version) is a very useful SQLite database manager.
An excellent eBook covering almost every aspect of SQLite3: a must-read for anyone doing serious work.
SQL tutorial (covers "generic" SQL, but most of it applies to SQLite as well)
A work-in-progress SQLite3 tutorial. Don't miss other LxyzTHW pages!
SQLite official website with full documentation (may be newer than the SQLite library that comes standard with AutoIt)

Share this post


Link to post
Share on other sites

You may get further forward, but I imagine the calculations producing infinity are not needed. The code appears to loop through an array, find an empty string, convert it to a number, divide by this number and then you want to override the error which occurs - at least I think that is what's happening. This is not a good approach. The whole thing needs rewriting from the very beginning.

 

You're right, like I said, the values will NEVER be calculated, they are mere placeholders for re-arranging data. It will never actually try to divide the placeholders.

Share this post


Link to post
Share on other sites

First, you need to understand the math behind. Have a look here (Cramer's rule): http://en.wikipedia.org/wiki/Cramer%27s_rule or at Wiki: http://en.wikipedia.org/wiki/Invertible_matrix#Analytic_solution

I'll take a look at this and see what I can make of it. Thanks.

Edit: Have been looking over this and I'm having some trouble understanding. I'm very bad at learning from reading, but from looking at your code to extend to it to work with a bigger array I would just have to do the following, right?

Local $fDetA = 1 / ($aMatrix[0][0] * $aMatrix[1][1] * $aMatrix[0][2] * $aMatrix[1][2] - $aMatrix[1][0] * $aMatrix[0][1]$aMatrix[0][2] * $aMatrix[0][2]) ;etc etc for each element.

Is this right?

Edited by nullschritt

Share this post


Link to post
Share on other sites

I believe it would first be very useful to precisely describe the goal and the algorithm you want to implement, demonstrate its correctness, then only work out a toy example with solid grounds (i.e. BigNum even if it's slow as hell).

From this point you'd know if it's worth going further and creating an interface layer to a suitable library. BTW, isn't >Eigen good for you?

Never saw that library before, I'll look into seeing if it returns more accurate results.

Edit: When I tested all the example scripts on my computer they all stopped responding and had to be killed D:

Edited by nullschritt

Share this post


Link to post
Share on other sites

I'll take a look at this and see what I can make of it. Thanks.

Edit: Have been looking over this and I'm having some trouble understanding. I'm very bad at learning from reading, but from looking at your code to extend to it to work with a bigger array I would just have to do the following, right?

Local $fDetA = 1 / ($aMatrix[0][0] * $aMatrix[1][1] * $aMatrix[0][2] * $aMatrix[1][2] - $aMatrix[1][0] * $aMatrix[0][1]$aMatrix[0][2] * $aMatrix[0][2]) ;etc etc for each element.

Is this right?

 

Just checkout the example for a 3x3 matrix:

 

Inversion of 3×3 matrices[edit]

A computationally efficient 3x3 matrix inversion is given by

ae4b131d68af9eb132ee40d05bc13292.png

(where the scalar A is not to be confused with the matrix A). If the determinant is non-zero, the matrix is invertible, with the elements of the intermediary matrix on the right side above given by

bddd8fa7c35f9286e37802e8e40fdbd8.png

The determinant of A can be computed by applying the rule of Sarrus as follows:

682ff37dce63390b0d70c294aac53521.png

 

As you can see it isn't that simple what you did to get the determinant of the matrix.


Please don't send me any personal message and ask for support! I will not reply!

Selection of finest graphical examples at Codepen.io

The own fart smells best!
Her 'sikim hıyar' diyene bir avuç tuz alıp koşma!
¯\_(ツ)_/¯  ٩(●̮̮̃•̃)۶ ٩(-̮̮̃-̃)۶ૐ

Share this post


Link to post
Share on other sites

Gosh I haven't learned about the process behind matrix inversion since highschool, this is really hurting my brain, but maybe if I stare at it long enough I'll get it. Now I'm feeling stupid. Maybe I should have paid more attention in class.

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now

×
×
  • Create New...