math असम एक रैखिक समीकरण हल करना




दो चरो वाले रैखिक समीकरण युग्म (8)

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

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

-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 लिए सबसे अच्छा अनुमान प्राप्त करना चाहता हूं।


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


क्रैमर का नियम और गॉसियन उन्मूलन दो अच्छे, सामान्य उद्देश्य वाले एल्गोरिदम हैं ( साथ ही साथ समीर रैखिक समीकरण ) भी देखें। यदि आप कोड की तलाश में हैं, तो GiNaC , Maxima , और SymbolicC++ (निश्चित रूप से आपकी लाइसेंसिंग आवश्यकताओं के आधार पर)।

संपादित करें: मुझे पता है कि आप सी भूमि में काम कर रहे हैं, लेकिन मुझे SymPy (पायथन में एक कंप्यूटर बीजगणित प्रणाली) के लिए भी एक अच्छा शब्द SymPy । आप इसके एल्गोरिदम से बहुत कुछ सीख सकते हैं (यदि आप थोड़ा पाइथन पढ़ सकते हैं)। इसके अलावा, यह नए बीएसडी लाइसेंस के तहत है, जबकि अधिकांश मुफ्त गणित पैकेज जीपीएल हैं।


एनआईएसटी से टेम्पलेट न्यूमेरिकल टूलकिट में ऐसा करने के लिए टूल हैं।

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

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

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

पुस्तकालय में Array2D परिभाषित किया गया है।


आपके प्रश्न के शब्द से, ऐसा लगता है कि आपके पास अज्ञात से अधिक समीकरण हैं और आप विसंगतियों को कम करना चाहते हैं। यह आम तौर पर रैखिक प्रतिगमन के साथ किया जाता है, जो विसंगतियों के वर्गों के योग को कम करता है। डेटा के आकार के आधार पर, आप इसे स्प्रेडशीट में या सांख्यिकीय पैकेज में कर सकते हैं। आर एक उच्च गुणवत्ता वाला, मुफ्त पैकेज है जो कई अन्य चीजों के बीच रैखिक प्रतिगमन करता है। रैखिक प्रतिगमन (और बहुत सारे गॉचा) के लिए बहुत कुछ है, लेकिन सरल मामलों के लिए यह सरल है। यहां आपके डेटा का उपयोग करके एक आर उदाहरण है। ध्यान दें कि "टीएक्स" आपके मॉडल में अवरोध है।

> 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  

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

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

  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.Services.Directive
एल्गोरिदम: प्रारंभिक
अंकगणित: हाइब्रिड
मूल्य निर्धारण (सटीक): डिफ़ॉल्ट
मूल्य निर्धारण (डबल): स्टीस्टेस्ट एज
आधार: ढीला
पिवोट गणना: 3
=== समाधान विवरण ===
लक्ष्य:

निर्णय:
ए: 0.0785250000000004
बी: -0.180612500000001
सी: -41.6375875


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

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

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

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


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

-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

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

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

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

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

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

0 = 0 + 0

उदाहरण के तौर पर, यहां कुछ सी कोड है जो आपके प्रश्न में एक साथ समीकरण समीकरणों को काम करता है। पहले कुछ आवश्यक प्रकार, चर, एक समीकरण मुद्रण के लिए एक समर्थन समारोह, और 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 । फिर, एक बार जब आप उस मूल्य को समझ लेंगे, तो इसे दो अज्ञातों के साथ समीकरणों में से एक में बदलें और दूसरे मान को कार्य करें। फिर उन दोनों (अब-ज्ञात) अज्ञात को मूल समीकरणों में से एक में प्रतिस्थापित करें और अब आपके पास सभी तीन अज्ञातों के मान हैं:

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

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

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