Numerisk programmering i C# part 1: Løsning af ligningssystemer

Tags:    c#
<< < 123 > >>
Skrevet af Bruger #4522 @ 22.10.2007

Crouts Faktorisering


Nu skal vi kigge på den sidste metode vi vil implementere til at løse et ligningssystem, og det er Crouts faktorisering.

De to andre metoder vi har kigget på har den ulempe, at vi ændrer b vektoren og A matricen samtidig, hvilket betyder at hvis vi vil løse et system med samme A matrix, men med forskellige b vektorer - en situation der sandsynligvis vil opstå ganske tit - skal vi enten starte forfra med reduktionen af vores A matrix eller på en eller anden måde gemme en historie over modifikationerne ved b vektoren.

I Crouts faktorisering manipulerer vi A matricen og b vektoren uafhængigt af hindanden. Vi kan derfor bruge samme A matrix sammen med flere forskellige b vektorer uden at skulle starte forfra. Denne fleksibilitet gør denne metode til nok den mest benyttede ved løsning af ligningssystemer.

Følgende ligning viser hvordan vi omdanner det oprindelige system til til et nyt system hvor A matricen er omdannet til produktet af en øvre og nedre triangulær matrix (henholdsvis U og L):

Ax = LUx = b

L og U er henholdsvis (i dette eksempel er de fra et 4x4 system; l_ij er elementet fra L matricen på i. række og j. kolonne - ligeså med u_ij for U matricens vedkommende. Desværre ligner bogstavet lille L (l) ettallet (1) ret meget, men det skulle være klart hvad der er hvad):

Fold kodeboks ind/udKode 


Indgangene i L og U udregnes kolonne for kolonne efter følgende to ligninger (a_ij er elementet i række i og kolonne j fra A matricen):




Vi overskriver A matricen (via vores a variabel) med de to triangulære matricer, og sparer derfor lidt plads på den konto. Den nye A matrix er derfor (igen bruger jeg for eksemplets skyld et 4x4 system):

Fold kodeboks ind/udKode 


Med ovenstående A' matrix, løser vi følgende ligning:

Ly = b

y findes ved brug af substitution:



Når vi har fundet y, finder vi løsningsvektoren ved at løse:

Ux = y

Igen bruger vi substitution:



Vi har nu nok information til at kunne implementere Crouts løsningen i C# kode. Her er koden:

Fold kodeboks ind/udKode 


Bemærk at Crouts metoden bruger sin egen "indbyggede" pivoting, hvorfor der ikke gøres brug af vores Pivot() ovenfor.

Test af EquationSolver


Til at teste EquationSolver benyttes to ligningssystemer:

Ligningssystem 1:
Fold kodeboks ind/udKode 


Ligningssystem 2:
Fold kodeboks ind/udKode 


Bemærk venligst at element A[0,0] = 0 i begge eksempler, hvilket som vi nævnte under Pivoting-sektionen medfører at vores system bliver ustabilt under vores løsningsmetoder, hvorfor vi netop gør brug af pivoting.

Løsningen til testsystemerne er:

Fold kodeboks ind/udKode 


Følgende fil, EquationSolverTest.cs, indeholder unit tests for ovenstående to eksempler:

Fold kodeboks ind/udKode 


Ovenstående unit tests viser at vores ligningsløser fungerer rigtig godt! For at være helt sikker skal man selvfølgelig kører implementationen igennem mange flere tests for at sikre at koden holder i alle tilfælde, inkl. grænsetilfælde osv.

Bemærk at vi arbejder med double's hvilket vil sige at vi skal bruge en tolerance parameter ved testen som angiver hvor meget resultatværdien må afvige fra den forventede værdi. Jeg har anvendt en meget lille toleranceværdi (0.000000000005) som tit vil være påkrævet ved videnskabelige udregninger. Til finans/business og andre formål kan en toleranceværdi på f.eks. 0.0005 tit vær god nok.

Så! Nu er vi færdig. I denne artikel kiggede vi på hvordan vi i C#/.NET kunne implementere de mest almindelige løsningsmetoder for løsning af ligningssystemer. Jeg håber det har været ligeså interessant at læse som det har været at skrive.



<< < 123 > >>

Hvad synes du om denne artikel? Giv din mening til kende ved at stemme via pilene til venstre og/eller lægge en kommentar herunder.

Del også gerne artiklen med dine Facebook venner:  

Kommentarer (3)

User
Bruger #12679 @ 24.10.07 18:24
Yderst interessant artikel! Flere af den slags :) 5 herfra!
User
Bruger #3491 @ 02.11.07 01:20
Det er fedt med nogle mere avancerede artikler her på Udvikleren, jeg kunne dog ikke helt følge med i Crouts Faktorisering, måske pga. det sene tidspunkt.

Det er lidt uheldigt at det eksempel på et ligningssystem du angiver:
x² + y² = 1
2x+ 4y = 0
Ikke er lineært (pga. x² og y²) og derved ikke kan repræsenteres af en matrix og altså ikke løses vha. disse fremgangsmåder.

Du burde også læse om C#'s rektangulære arrays, en af C#'s fordele i forhold til Java. Der er en rigtig god illustration her http://decenturl.com/books.google/rectangular-vs-jagged og her er der en god gennemgang af fordele ulemper ved de 2 måder http://msdn.microsoft.com/msdnmag/issues/04/03/ScientificC/#S10
User
Bruger #4522 @ 02.11.07 09:40
Hej Martin,

Tak for dine kommentarer.

Jeg bemærkede slet ikke at mit eksempel på et ligningssytem ikke var lineært, hvilket ikke er særlig smart. Tak fordi du gjorde mig opmærksom på det - det vil jeg få ændret.

Og tak for linksene på C#s rektangulære arrays, dem vil jeg læse.
Du skal være logget ind for at skrive en kommentar.
t