2012-09-28 3 views
2

행렬 곱셈과 관련된 문제를 최적화하기 위해 Microsoft Solver Foundation을 사용하려고합니다. Excel의 솔버를 사용하여이 작업을 수행 할 수 있지만 C#으로 통합하려고하는데 문제가 있습니다. 여기에 예제와 함께 설명입니다행렬 곱셈을 사용하여 MS Solver Foundation 사용

당신이 (3 × 3)을 말해봐 매트릭스 Y는 다음과 같이 정의 :

Double[][] y = 
{ 
    new Double[] { 5, 1, 0 }, 
    new Double[] { 1, 9, 1 }, 
    new Double[] { 0, 1, 9 }, 
}; 

내가 (× 3) 매트릭스를 찾으려면 X 같은 것을 : x * y * x' 최소화되어 있습니다. 또한, X 값이 1로 합산되어야하며 X 값 하나도 없을 여기

미만 0은 지금까지이 코드이다

SolverContext context = SolverContext.GetContext();    // Get context environment 
Model model = context.CreateModel();       // Create a new model 

Decision d1 = new Decision(Domain.RealNonnegative, "d1");  // First item in "x" vector (must be >= 0) 
Decision d2 = new Decision(Domain.RealNonnegative, "d2");  // Second item in "x" vector (must be >= 0) 
Decision d3 = new Decision(Domain.RealNonnegative, "d3");  // Third item in "x" vector (must be >= 0) 
model.AddDecisions(d1, d2, d3);         // Add these to the model (this is where the outputs will be stored) 

model.AddConstraints("limits",         // Add constraints 
    0 <= d1 <= 1,            // Each item must be between 0 and 1 
    0 <= d2 <= 1, 
    0 <= d3 <= 1, 
    d1 + d2 + d3 == 1);           // All items must add up to 1 

부분이 I

model.AddGoal("min", GoalKind.Minimize, /* What goes here? */); 

이 부분은 일반적으로 (예 : d1 * d2 + d3)을 방정식을 포함하는 것이지만, 매트릭스 multiplica이 :에 붙어있어 당신은 당신이 최소화하려면 무엇을 말할 때입니다 그것은 간단하지 않습니다.

내가 곱셈을 수행하고 double을 반환하지만 AddGoal()Term 객체를 기대하고 또한 내가 Decision 개체에 대한 연산을 수행해야하는 기능을 만들 수 있습니다.

또는이 곱셈을 거대한 string 표현식으로 배제 할 수 있습니다 (이미 완료 했음).하지만 이렇게하지 않아도됩니다. (이 문자열은 다음과 같습니다 : "d1 * 5 + d2 * 1 + d3 * 0 ...")

아이디어가 있으십니까? 감사합니다. .

PS (엑셀)에 따르면 정답은 :

d1 = 0.503497 
d2 = 0.216783 
d3 = 0.27972 

참고 : 용액은 다음 예상 용액을 수득 "결정"

+0

왜이 것이 다운 되었습니까? – Eric

+1

MSF에서 out-of-the-box에 벡터 또는 매트릭스 지원이 없다고 생각합니다. 올바르게 메모하면'AddGoal'에'Term' 객체를 입력해야합니다. 문제를 확대하고 싶다면'Term' 객체를위한 간단한 벡터 - 행렬 프레임 워크를 만드는 것이 좋습니다. 'Term' 클래스는 관련 산술 연산자를 지원하며,'Model' 클래스에서 정적 메소드로 많은 수학 함수를 찾을 수 있으므로 이러한 프레임 워크를 작성하는 것이 합리적으로 쉬운 작업이어야합니다. –

+0

BTW, 'x'는 무엇을 나타 냅니까? 바꾸어 놓다? 역? –

답변

1

n 번호를 갖도록 확장 여야

using System; 
using Microsoft.SolverFoundation.Services; 

namespace akMSFStackOverflow 
{ 
    class Program 
    { 
     static void Main(string[] args) 
     { 
      Double[,] y = 
      { 
       { 5, 1, 0 }, 
       { 1, 9, 1 }, 
       { 0, 1, 9 }, 
      }; 

      Term goal; 
      Term[,] tx; 
      Term[,] ty; 

      SolverContext context = SolverContext.GetContext();    // Get context environment 
      Model model = context.CreateModel();       // Create a new model 

      Decision d1 = new Decision(Domain.RealNonnegative, "d1");  // First item in "x" vector (must be >= 0) 
      Decision d2 = new Decision(Domain.RealNonnegative, "d2");  // Second item in "x" vector (must be >= 0) 
      Decision d3 = new Decision(Domain.RealNonnegative, "d3");  // Third item in "x" vector (must be >= 0) 
      model.AddDecisions(d1, d2, d3);         // Add these to the model (this is where the outputs will be stored) 

      model.AddConstraints("limits",         // Add constraints 
       0 <= d1 <= 1,            // Each item must be between 0 and 1 
       0 <= d2 <= 1, 
       0 <= d3 <= 1, 
       d1 + d2 + d3 == 1);           // All items must add up to 1 

      ty = matrix(y); 
      tx = new Term[,] { { d1, d2, d3 } }; 

      goal = matMult(matMult(tx, ty), transpose(tx))[0, 0]; 

      model.AddGoal("goal", GoalKind.Minimize, goal); 

      // Specifying the IPM solver, as we have a quadratic goal 
      Solution solution = context.Solve(new InteriorPointMethodDirective()); 


      Report report = solution.GetReport(); 
      Console.WriteLine("x {{{0}, {1}, {2}}}", d1, d2, d3); 
      Console.Write("{0}", report); 

     } 


     static Term[,] matrix(Double[,] m) 
     { 
      int rows = m.GetLength(0); 
      int cols = m.GetLength(1); 
      Term[,] r = new Term[rows, cols]; 

      for (int row = 0; row < rows; row++) 
       for (int col = 0; col < cols; col++) 
        r[row, col] = m[row, col]; 

      return r; 
     } 

     static Term[,] matMult(Term[,] a, Term[,] b) 
     { 
      int rows = a.GetLength(0); 
      int cols = b.GetLength(1); 
      Term[,] r = new Term[rows, cols]; 

      for (int row = 0; row < rows; row++) 
       for (int col = 0; col < cols; col++) 
       { 
        r[row,col] = 0; 
        for (int k = 0; k < a.GetLength(1); k++) 
        { 
         r[row, col] += a[row, k] * b[k, col]; 
        } 
       } 

      return r; 
     } 

     static Term[,] transpose(Term[,] m) 
     { 
      int rows = m.GetLength(0); 
      int cols = m.GetLength(1); 
      Term[,] r = new Term[cols, rows]; 

      for (int row = 0; row < rows; row++) 
       for (int col = 0; col < cols; col++) 
       { 
        r[col, row] = m[row, col]; 
       } 

      return r; 
     } 
    } 
}