我有一个带有约束的非线性优化问题。它可以在 Microsoft Excel 中使用 Solver 加载项解决,但我无法在 C# 中复制它。
我安装了 Microsoft Solver Foundation dll
这是我改编代码的示例:http: //msdn.microsoft.com/en-us/library/gg261758 (v=vs.93).aspx?cs-save-lang=1&cs-lang=csharp#代码片段 3
基本上,在我的代码中,我有 2 个参数,称为 RHO 和 NU。我需要获得最小化平方和的最佳值。我只有 1 个 RHO 值和 1 个 NU 值,所以我知道将 RHO[s] 和 NU[s] 放在我的代码中是错误的,但是当我用 RHO 和 NU 替换它们时,我得到了错误。
另一个问题是,在示例中,代码查找一个名为“燃料”的“目标”类型的最佳变量。就我而言,我有 2 个变量需要优化。
显然,程序在最后一行中断,它说:“没有解决方案可以传播”。
任何人都知道如何更正我的代码?任何帮助表示赞赏!
这是我的代码:
class Segment
{
public double Strike { get; set; }
public double VolImp { get; set; }
public double _Rho_ { get; set; }
public double _Nu_ { get; set; }
public double _Alpha_ { get; set; }
}
Segment[] segmentData = new Segment[] {
new Segment { Strike = 5, VolImp = 53.2608},
new Segment { Strike = 10, VolImp = 48.3773},
new Segment { Strike = 20, VolImp = 43.8949},
new Segment { Strike = 30, VolImp = 40.9367},
new Segment { Strike = 40, VolImp = 38.891},
new Segment { Strike = 50, VolImp = 37.417},
new Segment { Strike = 60, VolImp = 36.2838},
new Segment { Strike = 70, VolImp = 35.3713},
new Segment { Strike = 80, VolImp = 34.6192},
new Segment { Strike = 90, VolImp = 33.9774},
new Segment { Strike = 100, VolImp = 33.4359},
new Segment { Strike = 110, VolImp = 32.9747},
new Segment { Strike = 120, VolImp = 32.5635},
new Segment { Strike = 130, VolImp = 32.2025},
new Segment { Strike = 140, VolImp = 31.8917},
new Segment { Strike = 150, VolImp = 31.6209},
new Segment { Strike = 160, VolImp = 31.3702},
new Segment { Strike = 170, VolImp = 31.1596},
new Segment { Strike = 180, VolImp = 30.9591},
};
SolverContext context = SolverContext.GetContext();
Model model = context.CreateModel();
// Parameters
Set segments = new Set(Domain.Integer, "segments");
Parameter RHO = new Parameter(Domain.Real, "RHO", segments);
RHO.SetBinding(segmentData, "_Rho_", "Strike");
Parameter NU = new Parameter(Domain.RealNonnegative, "NU", segments);
NU.SetBinding(segmentData, "_Nu_", "Strike");
Parameter ALPHA = new Parameter(Domain.RealNonnegative, "ALPHA", segments);
ALPHA.SetBinding(segmentData, "_Alpha_", "Strike");
Parameter MyStrike = new Parameter(Domain.RealNonnegative, "MyStrike", segments);
MyStrike.SetBinding(segmentData, "Strike", "Strike");
Parameter MyImpVol = new Parameter(Domain.RealNonnegative, "MyImpVol", segments);
MyImpVol.SetBinding(segmentData, "VolImp", "Strike");
model.AddParameters(RHO, NU, ALPHA, MyStrike, MyImpVol);
//Constraints
model.AddConstraint("rho_bound", Model.ForEach(segments, s => (-1 <= RHO[s] <= 1))) ;
model.AddConstraint("nu_bound", Model.ForEach(segments, s => (0 <= NU[s]) )) ;
model.AddConstraint("alpha_bound", Model.ForEach(segments, s => (0 < ALPHA[s]))) ;
double Forward = 100 ;
//Goal
Goal Mygoal = model.AddGoal("Mygoal", GoalKind.Minimize, Model.Sum(Model.ForEach(segments, s => Model.Power((MyImpVol[s] - (ALPHA[s] * (NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])) * (Model.Log((Model.Sqrt(1 - 2 * RHO[s] * (NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])) + Model.Power((NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])), 2)) + (NU[s] / ALPHA[s] * Model.Log(Forward / MyStrike[s])) - RHO[s]) / (1 - RHO[s]))) * (1 + (0.25 * RHO[s] * NU[s] * ALPHA[s] + (2 - 3 * RHO[s] * RHO[s]) / 24 * NU[s] * NU[s]) * 6.46407))), 2)))) ;
//solve
context.Solve();
context.PropagateDecisions();