Jump to content

System of linear equations resolver


oMBRa
 Share

Recommended Posts

this program uses the Gauss-Jordan eliminations algorithm to solve a system of equations.

How to use:

1)for each unknown quantity there must be an equation

2)put in the right upper edit the number of equations

3)put in the grid of boxes the coefficients of the unknow quantity

4)put in the right column the known term

5)each coefficient of the same unknown quantity must be aligned in the same column

example:

2y + 1z = 5 ------------------> 0 2 1 |5

1x + 3y + 2z = 3 -----------> 1 3 2 |3

2z + 1y + 1z = 6 -----------> 2 1 1 |6

in the first equation there isnt the 'x' so we put 0

here is the code:

CODE

#include <GUIConstants.au3>

#include <EditConstants.au3>

#include <WindowsConstants.au3>

#include <StaticConstants.au3>

#include <Array.au3>

Global $nColumns[4] ; Columns's number

Global $nRows[4] ; Row's number

Global $nInput[4][4] ; Edits

Global $nIGraphics[4][4] ; Edit's Graphics

Global $nResults[4] ; Result's label

Global $nResName[4] ; Result's name

Global $nKnowTerm[4] ; Know terms

Global $nHMany ; How many equations

Global $sButton ; Button

Global $z = 0

$Gui = GUICreate('System of Linear Equations Resolver', 480, 480, -1, -1)

GUISetBkColor(0xFFFFFF)

GUISetFont(12, 400, 2, "Arial")

$sButton = GUICtrlCreateButton('Solve System', 80, 410, 120, 30)

GUICtrlCreateLabel('N. Equations', 365, 40, 80, 40, BitOR($ES_CENTER, $SS_CENTERIMAGE)) ; N. Equations

GUICtrlSetFont(-1, 10) ;

$nHMany = GUICtrlCreateEdit('4', 376, 91, 60, 20, $ES_CENTER, $WS_EX_TRANSPARENT)

For $i = 0 To 3

$nResName[$i] = GUICtrlCreateLabel('x'&$i+1, 80 + 61*$i, 40, 60, 40, BitOR($ES_CENTER, $SS_CENTERIMAGE))

$nResults[$i] = GUICtrlCreateLabel('', 81 + 61*$i, 81, 60, 40, BitOR($ES_CENTER, $SS_CENTERIMAGE))

Next

GUICtrlCreateGraphic(82, 82, 245, 42, $GUI_DISABLE) ;

GUICtrlSetBkColor(-1, 0x808080) ;

GUICtrlCreateGraphic(80, 80, 245, 42, $GUI_DISABLE) ; Result's graphics

GUICtrlSetBkColor(-1, 0xCCCCCC) ;

GUICtrlSetColor(-1, 0x000000) ;

GUICtrlCreateGraphic(377, 82, 62, 42, $GUI_DISABLE) ;

GUICtrlSetBkColor(-1, 0x808080) ;

GUICtrlCreateGraphic(375, 80, 62, 42, $GUI_DISABLE) ; nHMany's graphics

GUICtrlSetBkColor(-1, 0xFFFFFF) ;

GUICtrlSetColor(-1, 0x000000) ;

For $i = 0 To 3

$nColumns[$i] = GUICtrlCreateLabel($i+1, 80 + 61*$i, 180, 60, 40, BitOR($ES_CENTER, $SS_CENTERIMAGE))

$nRows[$i] = GUICtrlCreateLabel($i+1, 20, 220 + 41*$i, 60, 40, BitOR($ES_CENTER, $SS_CENTERIMAGE))

Next

GUICtrlCreateLabel('Know Term', 365, 179, 80, 40, BitOR($ES_CENTER, $SS_CENTERIMAGE)) ; Know Term

GUICtrlSetFont(-1, 10) ;

GUICtrlCreateGraphic(82, 222, 243, 163, $GUI_DISABLE) ; Grey Graphic (edits)

GUICtrlSetBkColor(-1, 0x808080) ;

GUICtrlCreateGraphic(377, 222, 62, 163, $GUI_DISABLE) ; Grey Graphic (know term)

GUICtrlSetBkColor(-1, 0x808080) ;

For $i = 0 To 3

For $j = 0 To 3

$nInput[$i][$j] = GUICtrlCreateEdit('', 82 + 60*$j, 230 + 40*$i+1, 59, 20, $ES_CENTER, $WS_EX_TRANSPARENT)

$nIGraphics[$i][$j] = GUICtrlCreateGraphic(80 + 60*$j+1, 220 + 40*$i+1, 61, 41, $GUI_DISABLE) ;

GUICtrlSetBkColor(-1, 0xFFFFFF) ; Edit's Graphics

GUICtrlSetColor(-1, 0xCCCCCC) ;

Next

$nKnowTerm[$i] = GUICtrlCreateEdit('', 376, 231 + 40*$i+1, 60, 20, $ES_CENTER, $WS_EX_TRANSPARENT)

GUICtrlCreateGraphic(375, 220 + 40*$i+1, 62, 41, $GUI_DISABLE) ;

GUICtrlSetBkColor(-1, 0xFFFFFF) ; Know term's Graphics

GUICtrlSetColor(-1, 0xCCCCCC) ;

Next

GUICtrlCreateGraphic(375, 220, 62, 163, $GUI_DISABLE) ; Know term's

GUICtrlSetColor(-1, 0x000000) ; Black Frame

GUICtrlCreateGraphic(80, 220, 243, 163, $GUI_DISABLE) ; Edit's

GUICtrlSetColor(-1, 0x000000) ; Black Frame

GUIRegisterMsg($WM_COMMAND, "WM_COMMAND")

GUISetState()

While 1

$nMsg = GUIGetMsg()

If $nMsg = $GUI_EVENT_CLOSE Then

Exit

EndIf

If $nMsg = $sButton Then

_BuildMatrix(GUICtrlRead($nHMany))

EndIf

WEnd

Func _BuildMatrix($nEq)

Local $Matrix[$nEq][$nEq + 1], $sMatrix

For $i = 0 To $nEq - 1

For $j = 0 To $nEq - 1

$Matrix[$i][$j] = GUICtrlRead($nInput[$i][$j])

If $j = $nEq - 1 Then

$Matrix[$i][$j + 1] = GUICtrlRead($nKnowTerm[$i])

EndIf

Next

Next

_OrderMatrix($Matrix)

$sMatrix = _SolveMatrix($Matrix)

For $i = 0 To 3

If $i < UBound($sMatrix) Then

GUICtrlSetData($nResults[$i], Round($sMatrix[$i], 2))

Else

GUICtrlSetData($nResults[$i], '-')

EndIf

Next

EndFunc ;==>_BuildMatrix

Func _OrderMatrix(ByRef $oMatrix)

Local $hModule[3] = [0, 0, -1]

Local $nRows = UBound($oMatrix)

Local $K = 0, $nSwap

For $i = 0 To $nRows - 1

If $oMatrix[$i][$K] = 0 Then

If $oMatrix[Mod($i + 1, $nRows)][$K] <> 0 Then

_SwapRows($oMatrix, $i, Mod($i + 1, $nRows))

Else

$nSwap = _CheckRow($oMatrix, $K)

_SwapRows($oMatrix, $i, $nSwap)

EndIf

EndIf

$K += 1

Next

EndFunc ;==>_OrderMatrix

Func _CheckRow($oMatrix, $tK)

$nRows = UBound($oMatrix)

For $i = 0 To $nRows - 1

If $oMatrix[Mod($i + $tK, $nRows)][$tK] <> 0 Then

Return $i

EndIf

Next

EndFunc ;==>_CheckRow

Func _SwapRows(ByRef $oMatrix, $Row1, $Row2)

Local $nColumns = UBound($oMatrix, 2) - 1

For $i = 0 To $nColumns

_ArraySwap($oMatrix[$Row1][$i], $oMatrix[$Row2][$i])

Next

EndFunc ;==>_SwapRows

Func WM_COMMAND($hWnd, $Msg, $wParam, $lParam)

Local $IDFrom, $iCode, $K

$IDFrom = BitAND($wParam, 0xFFFF)

$iCode = BitShift($wParam, 16)

If $iCode = 768 And $IDFrom = $nHMany Then

$K = GUICtrlRead($nHMany)

If $K > 1 And $K < 5 Then

For $i = 0 To 3

For $j = 0 To 3

If $j > $K-1 Or $i > $K-1 Then

_ChangeBkEdits($i, $j, 0xC0C0C0, 0)

Else

_ChangeBkEdits($i, $j, 0xFFFFFF, 1)

EndIf

Next

Next

EndIf

EndIf

If $iCode = 768 And $IDFrom <> $sButton Then

If StringRegExp(GUICtrlRead($IDFrom), '[^-0-9.]') Then

GUICtrlSetData($IDFrom, StringRegExpReplace(GUICtrlRead($IDFrom), '[^-0-9.]', ''))

EndIf

EndIf

Return $GUI_RUNDEFMSG

EndFunc

Func _ChangeBkEdits($Row, $Column, $Color, $State)

Local $nState[2] = [$GUI_DISABLE, $GUI_ENABLE]

If BitAND(GUICtrlGetState($nInput[$Row][$Column]), $nState[$State]) = 0 Then

GUICtrlSetState($nInput[$Row][$Column], $nState[$State])

GUICtrlSetBkColor($nInput[$Row][$Column], $Color)

GUICtrlSetBkColor($nIGraphics[$Row][$Column], $Color)

EndIf

EndFunc

Func _SolveMatrix(ByRef $oMatrix)

Local $nRows = UBound($oMatrix) - 1

Local $nColumns = UBound($oMatrix, 2) - 1

Local $K, $mResults[$nRows + 1]

For $x = 0 To $nRows

$tDivisor = $oMatrix[$K][$K]

For $j = 0 To $nColumns

If $tDivisor = 0 Or $tDivisor = 1 Then ExitLoop

$oMatrix[$K][$j] /= $tDivisor

Next

For $i = 0 To $nRows

$Multi = $oMatrix[$i][$K]

For $j = 0 To $nColumns

If $i = $K Then ContinueLoop 2

$oMatrix[$i][$j] = $oMatrix[$i][$j] - $oMatrix[$K][$j] * $Multi

Next

Next

$K += 1

Next

For $i = 0 To UBound($oMatrix) - 1

$mResults[$i] = $oMatrix[$i][$nColumns]

Next

Return $mResults

EndFunc ;==>_SolveMatrix

P.S is my first script in the example forum :) Enjoy Edited by oMBRa
Link to comment
Share on other sites

it's great but you can't solve all equations with this method, for example:

3x3 matrix:

x+4y+7z = 138

2x+5y+8z = 171

3x+6y+9z = 204

as a result, you'll get:

x = 0, y = 0, z = 0

and the right solution is:

x = 10, y = 11, z = 12

anyway, your method works for non-singular matrices, but can u find a way to calculate it for singular matrices (determinant|matrix|=0)? :)

You might also consider this: http://www.maths.surrey.ac.uk/explore/emma...es/option1.html (bottom of the page) for non-singular matrices (it's a bit more simplified method for calculating matrix of this type)

Good luck :party:

Edited by sandin
Link to comment
Share on other sites

it's great but you can't solve all equations with this method, for example:

3x3 matrix:

x+4y+7z = 138

2x+5y+8z = 171

3x+6y+9z = 204

as a result, you'll get:

x = 0, y = 0, z = 0

and the right solution is:

x = 10, y = 11, z = 12

anyway, your method works for non-singular matrices, but can u find a way to calculate it for singular matrices (determinant|matrix|=0)? :)

You might also consider this: http://www.maths.surrey.ac.uk/explore/emma...es/option1.html (bottom of the page) for non-singular matrices (it's a bit more simplified method for calculating matrix of this type)

Good luck :party:

thx for the great reply, I will try to solve singular matrices too
Link to comment
Share on other sites

thx for the great reply, I will try to solve singular matrices too

If you have this

#include <Array.au3>

Local $a, $b[4][5] = [["","","","",""],["", 1,4,7,138],["", 2,5,8,171],["", 3,6,9,204]]
$a = _SolveLinearSystem ($b)
_ArrayDisplay($a)

; #FUNCTION# =============================================================
; Name...........: _SolveLinearSystem

at the top of clarinetmeister's Gaussian_elimination_function from

http://www.autoitscript.com/forum/index.ph...st&p=659609

then Authenticity's solution is returned.

I imagine you have found out Cramer's rule will not work because the determinant of the 3x3 matrix from sandin's equations is zero.

Link to comment
Share on other sites

I imagine you have found out Cramer's rule will not work because the determinant of the 3x3 matrix from sandin's equations is zero.

yes, I noticed.

I will try to add gaussian elimination to solve singular matrix, thx for the reply

Link to comment
Share on other sites

great results, I'm glad u've added the "-" and "," support, very useful application you made :)

it would be great if you could add support for like AxA matrix (not only 4x4 max), and add the support for at least 4-5 extra numbers (5 just isn't enough, especially when you use "-" in front of the numbers).

smth like this:

#include <GUIConstantsEx.au3>
#include <WindowsConstants.au3>

Global $last_matr = 4

While 1
    _ispocetka()
WEnd

func _ispocetka()
    Local $velicina_matrice = _matrica_get_count()
    if $velicina_matrice <> 0 AND $velicina_matrice <> 1 then _prikazi_matricu($velicina_matrice)
EndFunc

func _matrica_get_count()
    Local $return_val
    Local $iform_x = GUICreate("Matrix dimensions", 200, 60)
    Local $iInput_x = GUICtrlCreateInput($last_matr, 120, 3, 70, 20, 0x2000)
    GUICtrlSetLimit(-1, 99, 1)
    GUICtrlCreateUpdown(-1)
    GUICtrlSetLimit(-1, 2, 1)
    GUICtrlCreateLabel("Input matrix dimension", 10, 7, 105, 17)
    Local $ok_button = GUICtrlCreateButton("OK", 10, 30, 85, 20)
    Local $canc_button = GUICtrlCreateButton("Cancel", 105, 30, 85, 20)
    GUISetState(@SW_SHOW, $iform_x)
    While 1
        Local $iMsg = GUIGetMsg()
        Switch $iMsg
            case $GUI_EVENT_CLOSE, $canc_button
                Exit
            case $ok_button, $iInput_x
                $return_val = GUICtrlRead($iInput_x)
                GUIDelete($iform_x)
                ExitLoop
        EndSwitch
    WEnd
    $last_matr = $return_val
    Return $return_val
EndFunc

func _prikazi_matricu($velicina_matrice)
    Local $x_coord = 10, $y_coord = 10
    Local $Form1 = GUICreate("Matrix", $velicina_matrice*69+200, $velicina_matrice*16+50)
    Dim $inputs[$velicina_matrice+1][$velicina_matrice+1]
    for $i = 1 to $velicina_matrice
        for $j = 1 to $velicina_matrice
            $inputs[$i][$j] = GUICtrlCreateInput("", $x_coord, $y_coord, 70, 17)
            $y_coord += 16
        Next
        $y_coord = 10
        $x_coord += 69
    Next
    dim $mnozioci[$velicina_matrice+1]
    $y_coord = 10
    GUICtrlCreateLabel("x", $velicina_matrice*69+30-19, ($velicina_matrice*16)/2, 19, 20, 0x0001)
    GUICtrlSetFont(-1, 16, 800)
    for $i = 1 to $velicina_matrice
        $mnozioci[$i] = GUICtrlCreateInput("", $velicina_matrice*69+30, $y_coord, 70, 17)
        $y_coord += 16
    Next
    GUICtrlCreateLabel("=", $velicina_matrice*69+100, ($velicina_matrice*16)/2, 19, 20, 0x0001)
    GUICtrlSetFont(-1, 16, 800)
    dim $resenja[$velicina_matrice+1]
    $y_coord = 10
    for $i = 1 to $velicina_matrice
        $resenja[$i] = GUICtrlCreateInput("", $velicina_matrice*69+100+20, $y_coord, 70, 17)
        $y_coord += 16
    Next
    Local $racunaj_button = GUICtrlCreateButton("Calculate", 10, $velicina_matrice*16+20, 60, 20)
    Local $novo_button = GUICtrlCreateButton("New matrix", 80, $velicina_matrice*16+20, 100, 20)
    Local $izlaz_button = GUICtrlCreateButton("Exit", $velicina_matrice*69+130, $velicina_matrice*16+20, 60, 20)
    GUISetState(@SW_SHOW, $Form1)

    While 1
        Local $nMsg = GUIGetMsg()
        Switch $nMsg
            Case $GUI_EVENT_CLOSE, $izlaz_button
                Exit
            case $novo_button
                GUIDelete($Form1)
                ExitLoop
            case $racunaj_button
                for $j = 1 to $velicina_matrice
                    Local $rezultat = 0
                    for $i = 1 to $velicina_matrice
                        $rezultat += GUICtrlRead($inputs[$i][$j])*GUICtrlRead($mnozioci[$i])
                    Next
                    GUICtrlSetData($resenja[$j], $rezultat)
                Next
        EndSwitch
    WEnd
EndFunc

it's just basic matrix multiplication (reverse of the thing you made, when you have the X, Y, Z, etc..., but you have no solution).

Edited by sandin
Link to comment
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
 Share

  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...