2012-07-03 10 views
9

मेरे पास बाधाओं के साथ एक गैर-रैखिक अनुकूलन समस्या है। इसे सॉफ़्टवेयर ऐड-इन के साथ माइक्रोसॉफ्ट एक्सेल में हल किया जा सकता है, लेकिन मुझे सी # में दोहराने में परेशानी हो रही है।मैं सी # में माइक्रोसॉफ्ट एक्सेल की सॉल्वर कार्यक्षमता (जीआरजी नॉनलाइनर) का अनुकरण कैसे कर सकता हूं?

मेरी समस्या following spreadsheet में दिखाया गया है। मैं क्लासिक ए x = b समस्या को हल कर रहा हूं लेकिन चेतावनी के साथ कि x के सभी घटक गैर-नकारात्मक होना चाहिए। तो मानक रैखिक बीजगणित का उपयोग करने के बजाय मैं गैर-नकारात्मक बाधा के साथ सॉल्वर का उपयोग करता हूं, वर्ग अंतरों के योग को कम करता हूं, और उचित समाधान प्राप्त करता हूं। मैंने Microsoft Solver Foundation या Solver SDK का उपयोग करके इसे सी # में दोहराने की कोशिश की है। हालांकि मुझे उनके साथ कहीं भी नहीं मिल रहा है क्योंकि एमएसएफ के साथ मैं यह नहीं समझ सकता कि लक्ष्य को परिभाषित करने के लिए और सॉल्वर एसडीके के साथ मैं हमेशा "इष्टतम" स्थिति वापस लेता हूं और सभी 0 का समाधान जो निश्चित रूप से स्थानीय भी नहीं है न्यूनतम।

यहाँ सॉल्वर एसडीके के लिए मेरे कोड है:

static double[][] A = new double[][] { new double[] { 1, 0, 0, 0, 0 }, new double[] { 0.760652602, 1, 0, 0, 0 }, new double[] { 0.373419404, 0.760537565, 1, 0, 0 }, new double[] { 0.136996731, 0.373331934, 0.760422587, 1, 0 }, new double[] { 0.040625222, 0.136953801, 0.373244464, 0.76030755, 1 } }; 
static double[][] b = new double[][] { new double[] { 2017159 }, new double[] { 1609660 }, new double[] { 837732.8125 }, new double[] { 330977.3125 }, new double[] { 87528.38281 } }; 

static void Main(string[] args) 
{ 
    using(Problem problem = new Problem(Solver_Type.Minimize, 5, 0)) 
    { 
     problem.VarDecision.LowerBound.Array = new double[] { 0.0, 0.0, 0.0, 0.0, 0.0 }; 
     problem.VarDecision.UpperBound.Array = new double[] { Constants.PINF, Constants.PINF, Constants.PINF, Constants.PINF, Constants.PINF }; 

     problem.Evaluators[Eval_Type.Function].OnEvaluate += new EvaluateEventHandler(SumOfSquaredErrors); 

     problem.ProblemType = Problem_Type.OptNLP; 

     problem.Solver.Optimize(); 

     Optimize_Status status = problem.Solver.OptimizeStatus; 

     Console.WriteLine(status.ToString()); 
     foreach(double x in problem.VarDecision.FinalValue.Array) 
     { 
      Console.WriteLine(x); 
     } 
    } 
} 

static Engine_Action SumOfSquaredErrors(Evaluator evaluator) 
{ 
    double[][] x = new double[evaluator.Problem.Variables[0].Value.Array.Length][]; 
    for(int i = 0; i < x.Length; i++) 
    { 
     x[i] = new double[1] { evaluator.Problem.Variables[0].Value.Array[i] }; 
    } 

    double[][] b_calculated = MatrixMultiply(A, x); 

    double sum_sq = 0.0; 
    for(int i = 0; i < b_calculated.Length; i++) 
    { 
     sum_sq += Math.Pow(b_calculated[i][0] - b[i][0], 2); 
    } 
    evaluator.Problem.FcnObjective.Value[0] = sum_sq; 

    return Engine_Action.Continue; 
} 

static double[][] MatrixMultiply(double[][] left, double[][] right) 
{ 
    if(left[0].Length != right.Length) 
    { 
     throw new ArgumentException(); 
    } 

    double[][] sum = new double[left.Length][]; 
    for(int i = sum.GetLowerBound(0); i <= sum.GetUpperBound(0); i++) 
    { 
     sum[i] = new double[right[i].Length]; 
    } 

    for(int i = 0; i < sum.Length; i++) 
    { 
     for(int j = 0; j < sum[0].Length; j++) 
     { 
      for(int k = 0; k < right.Length; k++) 
      { 
       sum[i][j] += left[i][k] * right[k][j]; 
      } 
     } 
    } 

    return sum; 
} 

मैं क्योंकि मुझे नहीं लगता कि लक्ष्य समारोह एक पंक्ति में लिखा जा सकता है माइक्रोसॉफ्ट सॉल्वर फाउंडेशन के लिए किसी भी कोड नहीं है और यह 'नहीं करता है सॉलवर एसडीके जैसे प्रतिनिधियों की अनुमति नहीं है।

+0

तो हमें अपना कोड दिखाने के बारे में कैसे?यदि आप सभी 0 वापस प्राप्त करते हैं तो आप शायद कुछ गलत कर रहे हैं। –

+0

वहां आप जाते हैं। पहले यह किया होगा लेकिन मुझे एक त्वरित और गंदे मैट्रिक्स गुणात्मक कार्य लिखना पड़ा क्योंकि मैं मालिकाना 'मैट्रिक्स' वर्ग का उपयोग कर रहा हूं। –

+0

@FistOfFury नीचे स्वीकार किए जाते हैं जवाब देखें माइक्रोसॉफ्ट solver नींव कोड – FistOfFury

उत्तर

2

एक वैकल्पिक एक एल.पी. समस्या के रूप में यह तैयार करने के लिए किया जाएगा:

एक्स

विषय को कुल्हाड़ी में तत्वों की राशि को कम से कम> = ख

यह काफी सरल होना चाहिए एलपी नमूने में से एक के आधार पर सॉल्वर फाउंडेशन का उपयोग करने के लिए तैयार करना।

अद्यतन जुलाई 5

ऊपर दृष्टिकोण भी बहुत जटिल है, लेकिन हो सकता है इस सीमावर्ती सॉल्वर एपीआई के कारण है। माइक्रोसॉफ्ट सॉल्वर फाउंडेशन, और चुकता मतभेद की राशि को कम करने का उपयोग करना, निम्नलिखित कार्यक्रम:

f = 254184688.179922 
x[0] = 2017027.31820845 
x[1] = 76226.6063397686 
x[2] = 26007.3375581303 
x[3] = 1.00650383558278E-07 
x[4] = 4.18546775823669E-09 
:

private static void Main(string[] args) 
{ 
    var solver = SolverContext.GetContext(); 
    var model = solver.CreateModel(); 

    var A = new[,] 
     { 
      { 1, 0, 0, 0, 0 }, 
      { 0.760652602, 1, 0, 0, 0 }, 
      { 0.373419404, 0.760537565, 1, 0, 0 }, 
      { 0.136996731, 0.373331934, 0.760422587, 1, 0 }, 
      { 0.040625222, 0.136953801, 0.373244464, 0.76030755, 1 } 
     }; 
    var b = new[] { 2017159, 1609660, 837732.8125, 330977.3125, 87528.38281 }; 

    var n = A.GetLength(1); 
    var x = new Decision[n]; 
    for (var i = 0; i < n; ++i) 
     model.AddDecision(x[i] = new Decision(Domain.RealNonnegative, null)); 

    // START NLP SECTION 
    var m = A.GetLength(0); 
    Term goal = 0.0; 
    for (var j = 0; j < m; ++j) 
    { 
     Term Ax = 0.0; 
     for (var i = 0; i < n; ++i) Ax += A[j, i] * x[i]; 
     goal += Model.Power(Ax - b[j], 2.0); 
    } 
    model.AddGoal(null, GoalKind.Minimize, goal); 
    // END NLP SECTION 

    var solution = solver.Solve(); 
    Console.WriteLine("f = {0}", solution.Goals.First().ToDouble()); 
    for (var i = 0; i < n; ++i) Console.WriteLine("x[{0}] = {1}", i, x[i].GetDouble()); 
} 

निम्नलिखित समाधान है, जो जुड़ा हुआ एक्सेल शीट से समाधान के साथ लाइन में होना चाहिए उत्पन्न करता है

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

पूर्णता के लिए, बजाय एल.पी. समस्या तैयार करने के लिए, स्टार्ट NLP खंड और अंत NLP खंड के बीच कोड निम्न कोड के साथ आदान-प्रदान:

var m = A.GetLength(0); 
    var constraints = new Term[m]; 
    for (var j = 0; j < m; ++j) 
    { 
     Term Ax = 0.0; 
     for (var i = 0; i < n; ++i) Ax += A[j, i] * x[i]; 
     model.AddConstraint(null, constraints[j] = Model.GreaterEqual(Ax, b[j])); 
    } 
    model.AddGoal(null, GoalKind.Minimize, Model.Sum(x)); 

जो उत्पादन निम्नलिखित (नोट निकलेगा कि उद्देश्य के मामले दो मामलों में अलग हैं, इसलिए f में बड़े अंतर):

f = 2125502.27815564 
x[0] = 2017159 
x[1] = 75302.7580022821 
x[2] = 27215.9247379241 
x[3] = 5824.5954154355 
x[4] = 0 
+0

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

+0

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

+0

आप सही हैं, 1-मानदंड आपके फॉर्मूलेशन के साथ बेहतर है जबकि 2-मानदंड मूल फॉर्मूलेशन के साथ बेहतर है। यदि आपका फॉर्मूलेशन सॉल्वर फाउंडेशन के साथ किया जा सकता है तो मुझे लगता है कि यह एक अच्छा समाधान होगा। –

संबंधित मुद्दे