1

ソルバーファンデーションは初めてですが、目標関数の指定方法がわかりません。ソルバーを使用して解決しようとしている問題は、ゴール関数に基づいて2Dサーフェス上の最適なポイントを見つけることです。入力データとして、私はこの表面に3つのポイントがあり、音波がソース(最適なポイント)からそれらの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();

このコードは機能しますが、LocalOptimalソリューションとして{0.0}を返しますが、optimalは{2,2}です(チェックしたところ、GoalFunctionは{2,2}に対して0を返し、{0,0}に対してはるかに高い値を返します。おそらく{0、 0}は、決定がDomain.Realである場合の開始点です。

Solution.GetNext()は何も変更しません。


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

ドメインを制限すると、返されるソリューションは{1.9999999984154413,1.9999999990963979}なので、正しいです。

しかし、なぜソルバーは完全な実領域で起動しないのですか?まだわからない

多分誰かがいつか答えるでしょう...私は願っています、しかし私は以下の答えを正しいとマークしています。

4

1 に答える 1

1

私自身はMSFの専門家ではありませんが、私が知る限り、あなたのmodel.AddGoal()発言は正しくありません。ドキュメントによると、3番目の引数はTermである必要があります。TermにはdoubleからTermへの暗黙のキャスト演算子があるため、model.AddGoal()ステートメントで発生するのGoalFunctionは1回だけ呼び出されることです(最初は決定が初期化されないため、例外がスローされます)。

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);

うまくいけば、これはあなたの目標関数を定式化する方向にあなたを導くことができます。

于 2012-05-25T09:37:45.077 に答える