Megoldása lineáris egyenlet

szavazat
35

Azt kell, hogy programozottan megoldani egy lineáris egyenletrendszer C, Objective C, vagy (ha szükséges) a C ++.

Íme egy példa az egyenletek:

-44.3940 = a * 50.0 + b * 37.0 + tx
-45.3049 = a * 43.0 + b * 39.0 + tx
-44.9594 = a * 52.0 + b * 41.0 + tx

Ebből szeretnék, hogy a legjobb közelítés a, bés tx.

A kérdést 03/08/2008 19:14
a forrás felhasználó
Más nyelveken...                            


10 válasz

szavazat
3

Keres egy szoftvercsomagot, majd nem a munka, illetve a ténylegesen csinál a mátrix műveletek és az ilyen, és nem minden lépés?

Az első, egy munkatársat az enyém csak használt ocaml GLPK . Ez csak egy wrapper a GLPK , de eltávolítja a sok lépéseit beállítási dolgokat. Úgy tűnik, hogy mész, hogy ragaszkodni a GLPK, C, mégis. Az utóbbi, hála finom mentésére egy régi cikket Tanultam LP kicsit vissza, PDF . Ha egyedi beállításával kapcsolatos segítségért tovább, tudassa velünk, és biztos vagyok benne, én vagy valaki fog vándorolni vissza, és segít, de azt hiszem, ez elég egyenesen előre innen. Sok szerencsét!

Válaszolt 03/08/2008 19:27
a forrás felhasználó

szavazat
17

Cramer-szabály és minánsok két jó, általános célú algoritmusok (lásd még szimultán lineáris egyenletek ). Ha keres kódot, nézd meg GiNaC , Maxima , és SymbolicC ++ (attól függően, hogy az engedélyezési követelmények, természetesen).

EDIT: Tudom, hogy dolgozik C földet, de azt is, hogy egy pár jó szót az SymPy (a számítógépes algebrai rendszer Python). Meg lehet tanulni sokat algoritmusait (ha tud olvasni egy kicsit a python). Továbbá, ez az új BSD licenc, míg a legtöbb ingyenes matematikai csomagok GPL.

Válaszolt 03/08/2008 19:37
a forrás felhasználó

szavazat
7

Egy 3x3 lineáris egyenletrendszer azt hiszem, rendben lesz beindítani a saját algoritmusok.

Előfordulhat azonban, hogy nem kell aggódnia, a pontosság, osztás nullával, vagy nagyon kis számban, és mit kell tenni, végtelen sok megoldás. A véleményem az, hogy menjen el egy szabványos numerikus lineáris algebra csomag, mint LAPACK .

Válaszolt 08/08/2008 18:59
a forrás felhasználó

szavazat
1

Személy szerint én vagyok részrehajló az algoritmusok a numerikus receptek . (Én szeretem a C ++ kiadás.)

Ez a könyv megtanítja, hogy miért az algoritmusok dolgoznak, valamint bemutatjuk, néhány szép lyukú hibamentesített megvalósítások azok algoritmusok.

Persze, akkor is csak vakon használni CLAPACK (Én is használtam nagy sikerrel), de én először kézzel írja minánsok algoritmus legalább egy halvány ötlet a fajta munka, hogy ment bele, hogy ezek az algoritmusok stabil.

Később, ha csinálsz, sokkal érdekesebb a lineáris algebra, körülnézett a forráskódját Octave válaszolni fog egy csomó kérdést.

Válaszolt 25/08/2008 19:22
a forrás felhasználó

szavazat
3

Template Toolkit Numerikus NIST eszközöket kínálnak az csinálja.

Az egyik megbízható módja az, hogy egy QR bomlástermékek .

Íme egy példa egy wrapper, hogy tudok hívni „GetInverse (A, INVA)” az én kódot, és akkor tegye az inverz be INVA.

void GetInverse(const Array2D<double>& A, Array2D<double>& invA)
   {
   QR<double> qr(A);  
   invA = qr.solve(I); 
   }

Array2D definiáljuk a könyvtárban.

Válaszolt 25/08/2008 19:53
a forrás felhasználó

szavazat
2

A megfogalmazás a kérdés, úgy tűnik, mintha több egyenletek, mint ismeretlenek, és szeretné, hogy minimalizálja a következetlenségeket. Ez általában úgy történik a lineáris regresszió, amely minimalizálja a négyzetének összege a következetlenségek. Méretétől függően az adatok, akkor ezt a táblázatot vagy egy statisztikai csomagot. R egy magas színvonalú, ingyenes programcsomag, lineáris regresszió között sok más dolog. Van egy csomó a lineáris regresszió (és sok megvagy-k), de ez egyértelmű, hogy nem az egyszerű eseteket. Íme egy R példa segítségével az adatokat. Megjegyezzük, hogy a „TX” a lehallgatott a modellben.

> y <- c(-44.394, -45.3049, -44.9594)
> a <- c(50.0, 43.0, 52.0)
> b <- c(37.0, 39.0, 41.0)
> regression = lm(y ~ a + b)
> regression

Call:
lm(formula = y ~ a + b)

Coefficients:
(Intercept)            a            b  
  -41.63759      0.07852     -0.18061  
Válaszolt 17/09/2008 15:22
a forrás felhasználó

szavazat
2

Ami a futásidejű hatékonyság, mások válaszol jobb, mint az I. Ha mindig ugyanaz lesz a száma egyenletek változók, szeretem Cramer szabály mivel ez könnyen megvalósítható. Csak írj egy függvény kiszámítására meghatározója a mátrix (vagy az egyik, ami már meg van írva, biztos vagyok benne, megtalálja az egyik ott), és elosztjuk a meghatározó két mátrix.

Válaszolt 19/09/2008 04:36
a forrás felhasználó

szavazat
15

Meg lehet oldani ezt a programot pontosan ugyanúgy megoldani kézzel (szorzás és kivonás, majd etetés eredmények vissza egyenletek). Ez elég általános középiskolai szintű matematika.

-44.3940 = 50a + 37b + c (A)
-45.3049 = 43a + 39b + c (B)
-44.9594 = 52a + 41b + c (C)

(A-B): 0.9109 =  7a -  2b (D)
(B-C): 0.3455 = -9a -  2b (E)

(D-E): 1.2564 = 16a (F)

(F/16):  a = 0.078525 (G)

Feed G into D:
       0.9109 = 7a - 2b
    => 0.9109 = 0.549675 - 2b (substitute a)
    => 0.361225 = -2b (subtract 0.549675 from both sides)
    => -0.1806125 = b (divide both sides by -2) (H)

Feed H/G into A:
       -44.3940 = 50a + 37b + c
    => -44.3940 = 3.92625 - 6.6826625 + c (substitute a/b)
    => -41.6375875 = c (subtract 3.92625 - 6.6826625 from both sides)

Tehát ha a végén:

a =   0.0785250
b =  -0.1806125
c = -41.6375875

Ha csatlakoztatja ezeket az értékeket vissza az A, B és C, megtalálod, hogy azok megfelelőek.

A trükk az, hogy egy egyszerű 4x3-as mátrix, amely csökkenti viszont egy 3x2 mátrix, akkor egy 2x1 amely „a = n”, ahol n tényleges száma. Ha megvan, hogy adsz meg a következő mátrix fel, hogy más értéket, akkor a két érték a következő mátrix-ig már megoldódott minden változóra.

Feltéve, ha van N különböző egyenleteket, akkor mindig megoldja az N változó. Azt mondják, különálló, mert a kettő nem:

 7a + 2b =  50
14a + 4b = 100

Ezek az azonos egyenletet szorozni kettővel, így nem tud megoldást tőlük - megszorozzuk az első két kivonjuk hagyja a valódi, de haszontalan nyilatkozata:

0 = 0 + 0

Példaként, itt van néhány C kód, amely kidolgozza az egyenletrendszer, hogy te helyezni a kérdésre. Először néhány szükséges típusok, változók, a támogatási funkció kinyomtatására az egyenletet, és a kezdeti main:

#include <stdio.h>

typedef struct { double r, a, b, c; } tEquation;
tEquation equ1[] = {
    { -44.3940,  50, 37, 1 },      // -44.3940 = 50a + 37b + c (A)
    { -45.3049,  43, 39, 1 },      // -45.3049 = 43a + 39b + c (B)
    { -44.9594,  52, 41, 1 },      // -44.9594 = 52a + 41b + c (C)
};
tEquation equ2[2], equ3[1];

static void dumpEqu (char *desc, tEquation *e, char *post) {
    printf ("%10s: %12.8lf = %12.8lfa + %12.8lfb + %12.8lfc (%s)\n",
        desc, e->r, e->a, e->b, e->c, post);
}

int main (void) {
    double a, b, c;

Ezután a csökkenés a három egyenlet három ismeretlenes egyenlet két, két ismeretlenes

    // First step, populate equ2 based on removing c from equ.

    dumpEqu (">", &(equ1[0]), "A");
    dumpEqu (">", &(equ1[1]), "B");
    dumpEqu (">", &(equ1[2]), "C");
    puts ("");

    // A - B
    equ2[0].r = equ1[0].r * equ1[1].c - equ1[1].r * equ1[0].c;
    equ2[0].a = equ1[0].a * equ1[1].c - equ1[1].a * equ1[0].c;
    equ2[0].b = equ1[0].b * equ1[1].c - equ1[1].b * equ1[0].c;
    equ2[0].c = 0;

    // B - C
    equ2[1].r = equ1[1].r * equ1[2].c - equ1[2].r * equ1[1].c;
    equ2[1].a = equ1[1].a * equ1[2].c - equ1[2].a * equ1[1].c;
    equ2[1].b = equ1[1].b * equ1[2].c - equ1[2].b * equ1[1].c;
    equ2[1].c = 0;

    dumpEqu ("A-B", &(equ2[0]), "D");
    dumpEqu ("B-C", &(equ2[1]), "E");
    puts ("");

Ezután a csökkenés a két egyenlet két ismeretlennel egy egyenlet egy ismeretlen:

    // Next step, populate equ3 based on removing b from equ2.

    // D - E
    equ3[0].r = equ2[0].r * equ2[1].b - equ2[1].r * equ2[0].b;
    equ3[0].a = equ2[0].a * equ2[1].b - equ2[1].a * equ2[0].b;
    equ3[0].b = 0;
    equ3[0].c = 0;

    dumpEqu ("D-E", &(equ3[0]), "F");
    puts ("");

Most, hogy van egy formula típusú number1 = unknown * number2, akkor egyszerűen dolgoznak ki az ismeretlen értéket unknown <- number1 / number2. Aztán, ha rájöttek, hogy érték el, helyettesíti azt az egyik egyenlet két ismeretlennel, és dolgozzanak ki a második érték. Ezután helyettesítse mindkét (jelenleg ismert) ismeretlent az egyik az eredeti egyenletek és most már az értékeket mind a három ismeretlenes

    // Finally, substitute values back into equations.

    a = equ3[0].r / equ3[0].a;
    printf ("From (F    ), a = %12.8lf (G)\n", a);

    b = (equ2[0].r - equ2[0].a * a) / equ2[0].b;
    printf ("From (D,G  ), b = %12.8lf (H)\n", b);

    c = (equ1[0].r - equ1[0].a * a - equ1[0].b * b) / equ1[0].c;
    printf ("From (A,G,H), c = %12.8lf (I)\n", c);

    return 0;
}

A kimenet a kód megegyezik a korábbi számításokat ez a válasz:

         >: -44.39400000 =  50.00000000a +  37.00000000b +   1.00000000c (A)
         >: -45.30490000 =  43.00000000a +  39.00000000b +   1.00000000c (B)
         >: -44.95940000 =  52.00000000a +  41.00000000b +   1.00000000c (C)

       A-B:   0.91090000 =   7.00000000a +  -2.00000000b +   0.00000000c (D)
       B-C:  -0.34550000 =  -9.00000000a +  -2.00000000b +   0.00000000c (E)

       D-E:  -2.51280000 = -32.00000000a +   0.00000000b +   0.00000000c (F)

From (F    ), a =   0.07852500 (G)
From (D,G  ), b =  -0.18061250 (H)
From (A,G,H), c = -41.63758750 (I)
Válaszolt 26/02/2009 11:59
a forrás felhasználó

szavazat
6

Vessen egy pillantást a Microsoft Solver Alapítvány .

Vele meg tudná írni a kódot, mint ez:

  SolverContext context = SolverContext.GetContext();
  Model model = context.CreateModel();

  Decision a = new Decision(Domain.Real, "a");
  Decision b = new Decision(Domain.Real, "b");
  Decision c = new Decision(Domain.Real, "c");
  model.AddDecisions(a,b,c);
  model.AddConstraint("eqA", -44.3940 == 50*a + 37*b + c);
  model.AddConstraint("eqB", -45.3049 == 43*a + 39*b + c);
  model.AddConstraint("eqC", -44.9594 == 52*a + 41*b + c);
  Solution solution = context.Solve();
  string results = solution.GetReport().ToString();
  Console.WriteLine(results); 

Itt látható a kimenet:
=== Solver Foundation Service Report ===
Datetime: 2009/04/20 23:29:55
Modell neve: Alapértelmezett
képességek kért: LP
megoldásához idő (ms): 1027
Total Time (ms): 1414
megoldásához Befejezés Állapot: Optimális
Solver Kiválasztott: Microsoft.SolverFoundation.Solvers.SimplexSolver
irányelvek:
Microsoft.SolverFoundation.Services.Directive
algoritmus: Primal
számtani: hibrid
árak (pontos): alapértelmezett
árak (dupla): SteepestEdge
Bázis: Slack
Pivot száma: 3
== = Megoldás Részletek ===
Gólok:

döntések:
a: ,0785250000000004
b: -,180612500000001
c: -41,6375875

Válaszolt 21/04/2009 04:33
a forrás felhasználó

szavazat
1
function x = LinSolve(A,y)
%
% Recursive Solution of Linear System Ax=y
% matlab equivalent: x = A\y 
% x = n x 1
% A = n x n
% y = n x 1
% Uses stack space extensively. Not efficient.
% C allows recursion, so convert it into C. 
% ----------------------------------------------
n=length(y);
x=zeros(n,1);
if(n>1)
    x(1:n-1,1) = LinSolve( A(1:n-1,1:n-1) - (A(1:n-1,n)*A(n,1:n-1))./A(n,n) , ...
                           y(1:n-1,1) - A(1:n-1,n).*(y(n,1)/A(n,n))); 
    x(n,1) = (y(n,1) - A(n,1:n-1)*x(1:n-1,1))./A(n,n); 
else
    x = y(1,1) / A(1,1);
end
Válaszolt 30/12/2014 15:24
a forrás felhasználó

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more