C# 使用解算器在二维区域上寻找最佳点 这是我第一次和Sover基金会合作,我不知道如何指定目标函数。我试图用解算器解决的问题是基于目标函数在二维曲面上找到最佳点。作为输入数据,我在这个表面上有3个点,声波从声源(最佳点)到这三个点的时间差。这个时间差导致距离差

C# 使用解算器在二维区域上寻找最佳点 这是我第一次和Sover基金会合作,我不知道如何指定目标函数。我试图用解算器解决的问题是基于目标函数在二维曲面上找到最佳点。作为输入数据,我在这个表面上有3个点,声波从声源(最佳点)到这三个点的时间差。这个时间差导致距离差,c#,ms-solver-foundation,C#,Ms Solver Foundation,这是我的代码: 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.Ad

这是我的代码:

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}作为局部最优解,而最优解是{2,2}(我检查过了,GoalFunction为{2,2}返回0,为{0,0}返回更高的值。当决策是Domain.Real时,{0,0}可能是起点

GetNext()不会更改任何内容


如果我限制域,返回的解决方案是{1.99999984154413,1.9999990963979},因此它是正确的

但是为什么解算器不能在完整的实域中开始呢?还是不知道


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

我自己也不是MSF专家,但就我所能告诉您的
model.AddGoal()
语句不正确。根据示例,第三个参数应该是a.Term,它有一个从double到Term的隐式强制转换运算符,因此在
model.AddGoal()
语句中发生的唯一事情是调用一次
GoalFunction
(并引发异常,因为最初没有初始化决策)

在MSF示例中,有一些关于如何创建目标的示例

更新

基于这些示例,我创建了一个简单的目标(Rosenbrock香蕉函数),并将此目标合并到
AddGoal
调用中,如下所示:

    var goal = Model.Sum(Model.Power(1.0 - decisionX, 2.0),
                         Model.Product(100.0, Model.Power(decisionY - Model.Power(decisionX, 2.0), 2.0)));
    model.AddGoal( "Goal", GoalKind.Minimize, goal);

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

我自己不是MSF方面的专家,但就我所能告诉您的
模型。AddGoal()
语句不正确。根据示例,第三个参数应该是a.Term,它有一个从double到Term的隐式强制转换运算符,因此在
model.AddGoal()
语句中发生的唯一事情是调用一次
GoalFunction
(并引发异常,因为最初没有初始化决策)

在MSF示例中,有一些关于如何创建目标的示例

更新

基于这些示例,我创建了一个简单的目标(Rosenbrock香蕉函数),并将此目标合并到
AddGoal
调用中,如下所示:

    var goal = Model.Sum(Model.Power(1.0 - decisionX, 2.0),
                         Model.Product(100.0, Model.Power(decisionY - Model.Power(decisionX, 2.0), 2.0)));
    model.AddGoal( "Goal", GoalKind.Minimize, goal);

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

我已经看过这个示例,但我不确定是否可以在一个表达式中关闭此函数……无论如何,我会尝试。我已经用一种我希望有效的方法更新了我的答案。没有保证,但我会立即尝试:-)这将导致相同的异常-决策未初始化。我已经将我的函数转换为Model.Method()调用,所以最后我得到了一个术语,但在求解之后我得到了无穷大;)所以有些东西还是不对劲是的,我自己试过了,得出了同样的结论,很抱歉把你引向了错误的方向。但希望您最终能够摆脱
Model.Method()
调用中的无穷大。好的,对我来说,这里的答案是重写Model.Method调用,所以我将您的答案标记为最佳答案。。。这是唯一的答案,谢谢。不幸的是,我仍然无法得到最佳答案-{0,0}而不是最佳答案{2,2}。我看过这个例子,但我不确定是否可以在一个表达式中关闭这个函数。。。无论如何,我会努力的。我已经用一种我希望有效的方法更新了我的答案。没有保证,但我会马上亲自尝试:-)这会导致相同的异常-决策未初始化。我已经将我的函数转换为Model.Method()调用,所以最后我得到了一个术语,但在求解之后我得到了无穷大;)所以有些东西还是不对劲是的,我自己试过了,得出了同样的结论,很抱歉把你引向了错误的方向。但希望您最终能够摆脱
Model.Method()
调用中的无穷大。好的,对我来说,这里的答案是重写Model.Method调用,所以我将您的答案标记为最佳答案。。。这是唯一的答案,谢谢。不幸的是,我仍然无法得到最佳答案-{0,0}而不是最佳答案{2,2}。距离是标量还是向量类型?您确定在创建模型时定义了A、B和C吗?在
GoalFunction
中,您使用dsA减去rA、rB和rC,而在重写的代码中,您分别使用dsA、dsB和dsC进行减去。这仅仅是一个输入错误吗?我现在应用了GoalFunction,因为您已经重写了它,但是替换了a.Location.X,…,dsA。。。使用编译时双常量。当我执行时,我得到了一个合理的答案。如果尚未这样做,请确保在定义rA、rB和rC之前定义了A、B、C、dsA、dsB和dsC。距离是标量类型还是向量类型?您确定在创建模型时定义了A、B和C吗?在
GoalFunction
中,您使用dsA减去rA、rB和rC,而在重写的代码中,您分别使用dsA、dsB和dsC进行减去。这仅仅是一个输入错误吗?我现在应用了GoalFunction,因为您已经重写了它,但是替换了a.Location.X,…,dsA。。。使用编译时双常量。当我执行时,我得到了一个合理的答案。如果您尚未这样做,请确保在定义rA、rB和rC之前定义了A、B、C、dsA、dsB和dsC。