math - असम - दो चरो वाले रैखिक समीकरण युग्म




एक रेखीय समीकरण को हल करना (7)

NIST के टेम्पलेट न्यूमेरिकल टूलकिट में ऐसा करने के लिए उपकरण होते हैं।

अधिक विश्वसनीय तरीकों में से एक क्यूआर अपघटन का उपयोग करना है।

यहां एक रैपर का उदाहरण दिया गया है ताकि मैं अपने कोड में "गेटइनवर्स (ए, इनवा)" कह सकूं और यह उलटा को इनवा में डाल देगा।

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

Array2D को लाइब्रेरी में परिभाषित किया गया है।

मुझे प्रोग्राम सी, ऑब्जेक्टिव सी, या (यदि आवश्यक हो) सी ++ में रैखिक समीकरणों की एक प्रणाली को हल करने की आवश्यकता है।

यहाँ समीकरणों का एक उदाहरण दिया गया है:

-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

इस से, मुझे a , b , और tx लिए सर्वश्रेष्ठ सन्निकटन प्राप्त करना है।


आप इसे प्रोग्राम के साथ ठीक उसी तरह से हल कर सकते हैं जिस तरह से आप इसे हाथ से हल करते हैं (गुणा और घटाव के साथ, फिर परिणामों को वापस समीकरणों में खिलाते हैं)। यह सुंदर मानक माध्यमिक-स्कूल-स्तर का गणित है।

-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)

तो आप के साथ अंत:

a =   0.0785250
b =  -0.1806125
c = -41.6375875

यदि आप इन मानों को वापस A, B और C में प्लग करते हैं, तो आप पाएंगे कि वे सही हैं।

चाल एक साधारण 4x3 मैट्रिक्स का उपयोग करना है जो एक 3x2 मैट्रिक्स के बदले में कम हो जाती है, फिर एक 2x1 जो "a = n" है, एक वास्तविक संख्या है। एक बार जब आपके पास ऐसा हो जाता है, तो आप इसे अन्य मूल्य प्राप्त करने के लिए अगले मैट्रिक्स में खिलाते हैं, फिर अगले मैट्रिक्स में उन दो मूल्यों को जब तक आप अपने चर को हल नहीं करते।

बशर्ते आपके पास एन अलग समीकरण हैं, आप हमेशा एन चर के लिए हल कर सकते हैं। मैं स्पष्ट कहता हूं क्योंकि ये दोनों नहीं हैं:

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

वे एक ही समीकरण दो से गुणा कर रहे हैं ताकि आप उनसे एक समाधान प्राप्त नहीं कर सकते हैं - पहले दो से गुणा करें फिर आपको सही लेकिन बेकार बयान के साथ छोड़ देता है:

0 = 0 + 0

उदाहरण के अनुसार, यहां कुछ C कोड हैं जो आपके प्रश्न में आपके द्वारा रखे गए एक साथ समीकरणों को पूरा करते हैं। पहले कुछ आवश्यक प्रकार, चर, एक समीकरण को प्रिंट करने के लिए एक समर्थन फ़ंक्शन और 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;

इसके बाद, तीन समीकरणों में तीन अज्ञात के साथ दो समीकरणों में दो अज्ञात की कमी:

    // 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 ("");

अगला, दो समीकरणों की दो अज्ञात के साथ एक समीकरण के साथ एक अज्ञात में कमी:

    // 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 ("");

अब जब हमारे पास number1 = unknown * number2 का फॉर्मूला है, तो हम unknown <- number1 / number2 साथ unknown <- number1 / number2 मूल्य का काम कर सकते हैं। फिर, एक बार जब आप उस मूल्य का पता लगा लेते हैं, तो इसे दो अज्ञात के साथ समीकरणों में से एक में प्रतिस्थापित करें और दूसरे मूल्य पर काम करें। फिर उन दोनों (अब-ज्ञात) अज्ञात को मूल समीकरणों में से एक में स्थानापन्न करें और अब आपके पास तीनों अज्ञात के लिए मान हैं:

    // 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;
}

उस कोड का आउटपुट इस उत्तर में पहले की गणनाओं से मेल खाता है:

         >: -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)

क्या आप एक सॉफ्टवेयर पैकेज की तलाश कर रहे हैं जो काम करेगा या वास्तव में मैट्रिक्स ऑपरेशन कर रहा है और प्रत्येक चरण में ऐसा करेगा?

सबसे पहले, मेरे एक सहकर्मी ने Ocaml GLPK का उपयोग किया। यह GLPK लिए सिर्फ एक आवरण है, लेकिन यह चीजों को स्थापित करने के कई चरणों को हटा देता है। ऐसा लगता है कि आप C में GLPK के साथ रहना चाहते हैं, हालाँकि। उत्तरार्द्ध के लिए, एक पुराने लेख को बचाने के लिए स्वादिष्ट के लिए धन्यवाद, मैं एलपी थोड़ी देर के लिए वापस सीखता था, PDF । यदि आपको आगे स्थापित करने में विशिष्ट सहायता की आवश्यकता है, तो हमें बताएं और मुझे यकीन है, मुझे या किसी व्यक्ति को वापस भटकना और मदद करना होगा, लेकिन, मुझे लगता है कि यह यहां से काफी सीधा है। शुभ लाभ!


रन-टाइम दक्षता के संदर्भ में, अन्य लोगों ने I. से बेहतर उत्तर दिया है। यदि आपके पास हमेशा चर के समान समीकरण होंगे, तो मुझे क्रैमर का नियम पसंद है क्योंकि इसे लागू करना आसान है। एक मैट्रिक्स के निर्धारक की गणना करने के लिए एक फ़ंक्शन लिखें (या जो पहले से लिखा है, उसका उपयोग करें, मुझे यकीन है कि आप वहां से एक का पता लगा सकते हैं), और दो मैट्रिसेस के निर्धारकों को विभाजित कर सकते हैं।


व्यक्तिगत रूप से, मैं न्यूमेरिकल व्यंजनों के एल्गोरिदम के लिए आंशिक हूं। (मैं C ++ संस्करण का शौकीन हूं।)

यह पुस्तक आपको सिखाएगी कि एल्गोरिदम क्यों काम करता है, साथ ही आपको उन एल्गोरिदम के कुछ बहुत अच्छी तरह से डिबग किए गए कार्यान्वयन भी दिखाएंगे।

बेशक, आप बस आँख बंद करके इस्तेमाल कर सकते हैं (मैंने इसे बड़ी सफलता के साथ इस्तेमाल किया है), लेकिन मैं सबसे पहले एक गौसियन एलिमिनेशन एल्गोरिथ्म को हाथ से टाइप करूँगा, कम से कम उस तरह के काम का एक बेहोश विचार है जो इस एल्गोरिदम को बनाने में चला गया है। स्थिर।

बाद में, यदि आप अधिक दिलचस्प रैखिक बीजगणित कर रहे हैं, तो Octave के स्रोत कोड के चारों ओर देखने से बहुत सारे प्रश्नों का उत्तर मिलेगा।


Microsoft सॉल्वर फाउंडेशन पर एक नज़र डालें।

इसके साथ आप इस तरह कोड लिख सकते हैं:

  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); 

यहाँ उत्पादन है:
=== सॉल्वर फाउंडेशन सेवा रिपोर्ट ===
जीवनकाल: 04/20/2009 23:29:55
मॉडल का नाम: डिफ़ॉल्ट
अनुरोधित क्षमताएं: एल.पी.
हल समय (एमएस): 1027
कुल समय (एमएस): 1414
पूर्णता स्थिति को हल करें: इष्टतम
सॉल्वर चयनित: Microsoft.SolverFoundation.Solvers.SimplexSolver
निर्देशों:
Microsoft.SolverFoundation.Services.Directive
एल्गोरिथम: प्राइमल
अंकगणित: हाइब्रिड
मूल्य निर्धारण (सटीक): डिफ़ॉल्ट
मूल्य निर्धारण (डबल): SteepestEdge
आधार: सुस्त
धुरी गणना: 3
=== समाधान विवरण ===
लक्ष्य:

निर्णय:
a: 0.0785250000000004
b: -0.180612500000001
c: -41.6375875


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






linear-equation