制約のある非線形最適化の問題があります。Excel Solver (GRG) で解決しましたが、C# に変換しようとするMicrosoft Solver Foundation
とsolution.Quality = SolverQuality.Unknown
.
問題はこれです: 私はいくつかの決定をしており、それらのすべてに制約 (上限と下限) を制限しています。そして、他の 2 つの制約 (これは問題のある制約です):
- 決定の合計は 1 (100%) である必要があります
(MMULT(TRANSPOSE(Decision-Array),MMULT(Tabel-with-values,Decision-Array)))^0.5
別の値と等しい必要があります
目標はsum(Decision * value)
。Microsoft Solver Foundation によって次のように記述します。
SolverContext solverData = SolverContext.GetContext();
context.ClearModel();
model = context.CreateModel();
for (i=0 ; i< decisionCount; i++)
{
var decision = new Decision(SolverDomain.RealNonnegative, "decisions_" + i);
model.AddDecision(decision);
model.AddConstraint("limits_of_" + i, downConstraint(i) <= decision <= upConstraint(i));
}
var fdecision = new Decision(SolverDomain.RealNonnegative, "formula");
//mymatrix is double[,]
model.AddConstraint("f_constraint_1", fdecision == matMult(transpose(model.Decisions.ToList()),
matMult(matrix(mymatrix), transpose(model.Decisions.ToList()))[0, 0]);
//myAalue is double = givvenValue^2
solverData.model.AddConstraint("f_constraint_2", fdecision == myAalue);
var udecision = new Decision(SolverDomain.RealNonnegative, "upto100");
model.AddConstraint("upto1_constraint_1", udecision == UpTo100Precent(model.Decisions.ToList()));
model.AddConstraint("upto1_constraint_2", udecision == 1);
solverData.model.AddGoal("goal", GoalKind.Maximize, CalcGoal(model.Decisions.ToList()));
model.AddDecision(udecision);
model.AddDecision(fdecision);
Solution solution = context.Solve(new HybridLocalSearchDirective() { TimeLimit = 60000 });
//add here I get solution.Quality == SolverQuality.Unknown
上記のコードで使用する関数は次のとおりです。
private 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;
}
private 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;
}
private 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;
}
private Term UpTo100Precent(List<Decision> decisions)
{
Term to100 = 0;
foreach (var decision in decisions)
{
to100 += decision;
}
return to100;
}
private Term CalcGoal(List<Decision> decisions)
{
Term x = 0;
//A is double[]
for (i = 0; i < decisions.Count ; i++)
{
x += decisions[i] * A[1]
}
return x;
}
誰かが解決策を持っていますか?