使用求解器在2D区域上查找最佳点

时间:2012-05-25 08:54:02

标签: c# ms-solver-foundation

这是我第一次使用Solver Foundation,我不明白如何指定目标函数。我试图用Solver解决的问题是在基于目标函数的2D表面上找到最佳点。作为输入数据,我在这个表面上有3个点,声波需要从源(最佳点)到这三个点的时间之间的差异。这个时间差会导致距离差异。

这是我的代码:

var solver = SolverContext.GetContext();
var model = solver.CreateModel();

decisionX = new Decision( Domain.Real, "X" );
decisionY = new Decision( Domain.Real, "Y" );

model.AddDecision( decisionX );
model.AddDecision( decisionY );

model.AddGoal( "Goal", GoalKind.Minimize, GoalFunction() );

var solution = solver.Solve();
Console.WriteLine("X " + decisionX.GetDouble());
Console.WriteLine("Y " + decisionY.GetDouble());

GoalFunction()定义如下:

double GoalFunction() {
    Location X = new Location( decisionX.ToDouble(), decisionY.ToDouble() );
    var rA = A.Location.Distance( X );
    var rB = B.Location.Distance( X );
    var rC = C.Location.Distance( X );

    rA = (Distance)( rA - dsA );
    rB = (Distance)( rB - dsA );
    rC = (Distance)( rC - dsA );

    return ( rA * rA + rB * rB + rC * rC ) / 3;
}

上面的代码抛出异常(decisionX.ToDouble()),因为此时决策没有初始化。

有人可以帮我改写吗?


我已将GoalFunction重写为all-Model.methods-calls。

var solver = SolverContext.GetContext();
var model = solver.CreateModel();

decisionX = new Decision( Domain.Real, "X" );
decisionY = new Decision( Domain.Real, "Y" );

model.AddDecision( decisionX );
model.AddDecision( decisionY );

var rA = Model.Difference(
    Model.Sqrt(
        Model.Sum(
            Model.Power( Model.Difference( decisionX, A.Location.X ), 2 ),
            Model.Power( Model.Difference( decisionY, A.Location.Y ), 2 )
        )
    ),
    dsA.Value
);
var rB = Model.Difference(
    Model.Sqrt(
        Model.Sum(
            Model.Power( Model.Difference( decisionX, B.Location.X ), 2 ),
            Model.Power( Model.Difference( decisionY, B.Location.Y ), 2 )
        )
    ),
    dsB.Value
);
var rC = Model.Difference(
    Model.Sqrt(
        Model.Sum(
            Model.Power( Model.Difference( decisionX, C.Location.X ), 2 ),
            Model.Power( Model.Difference( decisionY, C.Location.Y ), 2 )
        )
    ),
    dsC.Value
);
var miner = Model.Min( rA, rB, rC );
rA = Model.Difference( rA, miner );
rB = Model.Difference( rB, miner );
rC = Model.Difference( rC, miner );
var goal = Model.Sum(
    Model.Power( rA, 2 ),
    Model.Power( rB, 2 ),
    Model.Power( rC, 2 )
);
model.AddGoal( "Goal", GoalKind.Minimize, goal );

var solution = solver.Solve();
var q = solution.Quality;
double x = decisionX.GetDouble();
double y = decisionY.GetDouble();

solution.GetNext();
x = decisionX.GetDouble();
y = decisionY.GetDouble();

此代码有效,但返回{0.0}作为LocalOptimal解决方案,而最佳值为{2,2}(我检查过,GoalFunction为{2,2}返回0,为{0,0}返回更高的值。可能当决策是Domain.Real时,{0,0}是起点。

Solution.GetNext()什么都不做。


decisionX = new Decision( Domain.RealRange( -10, 10 ), "X" );
decisionY = new Decision( Domain.RealRange( -10, 10 ), "Y" );

如果我限制域名,则返回的解决方案是{1.9999999984154413,1.9999999990963979},所以这是正确的。

但为什么解算器无法启动完整的真实域名?仍然不知道

也许有人会在某一天回答......我希望,但我将下面的答案标记为正确。

1 个答案:

答案 0 :(得分:1)

我自己并不是MSF的专家,但据我所知,你的model.AddGoal()陈述是不正确的。根据{{​​3}},第三个参数应该是documentation Term 具有从 double Term 的隐式强制转换运算符,因此model.AddGoal()语句中唯一发生的是{{1被调用一次(并抛出异常,因为决定最初没有初始化)。

在MSF样本中,有一些如何创建目标的例子。

<强>更新

基于这些样本,我创建了一个简单的目标(Rosenbrock香蕉函数),并将此目标纳入GoalFunction调用,如下所示:

AddGoal

希望这可以引导您制定目标函数。