2012-05-25 36 views
1

這是我第一次與Solver Foundation合作,我不明白如何指定目標函數。我試圖用Solver解決的問題是基於目標函數在2D表面上找到最佳點。作爲輸入數據,我在這個表面上有3點,聲波需要從源(最佳點)到這三點之間的時間差。這個時間差異導致距離差異。使用Solver找到2D區域上的最佳點

這裏是我的代碼:

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}(I檢查,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}所以我t是正確的。

但爲什麼求解器不能啓動全真實域?仍然不知道

也許有人會回答某一天...我希望,但我在下面的答案是正確的。

+0

是距離標量還是矢量類型?您是否肯定在創建模型時定義了A,B和C?在'GoalFunction'中,您用_dsA_減去_rA_,_rB_和_rC_,而在您重寫的代碼中,分別用_dsA_,_dsB_和_dsC_進行減法。這只是一個錯字嗎? –

+0

我已經應用了_GoalFunction_,因爲您已經重寫了它,但用編譯時雙常量替換了A.Location.X,...,dsA ...。當我執行時,我會得到一個合理的答案。如果您尚未這樣做,請確保在定義rA,rB和rC之前定義了A,B,C,dsA,dsB和dsC。 –

回答

1

我不是MSF專家,但是據我所知可以告訴你的model.AddGoal()聲明是不正確的。根據documentation第三個參數應該是Term期限具有期限隱式轉換操作符,這樣發生在你model.AddGoal()聲明的唯一的事情就是GoalFunction被調用一次(並拋出異常,因爲決定不是在第一次初始化)。

在MSF樣本中,有一些如何創建目標的例子。

UPDATE

基於這些樣品我創建了一個簡單的目標(的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); 

希望這會導致你在制定你的目標函數的方向。

+0

我見過這個例子,但我不知道如果我可以在一個表達式內關閉這個函數...無論如何,我會嘗試。 –

+0

我已經用我希望能夠工作的方法更新了我的答案。沒有保證,但我馬上試一試:-) –

+0

這會導致相同的例外情況 - 決策不會被初始化。我把我的函數變成了Model.Method()調用,所以我最終得到了Term,但是解決後我得到了Infinities;)所以有些東西仍然是錯誤的 –