我现在正在学习 Solver Foundation。我实际上正在为我的项目插入 lpsolve,但我认为我的问题是如何最好地表示我的约束的一般问题。
我认为,我有一个相当典型的背包或包装问题。我有一组位置,每个位置都有一个“分数”。我想选择满足目标“分数”的最少位置数。
(实际上,它比这要复杂一些——每个位置都有许多不同的属性,我经常会针对多个属性进行定位)。
到目前为止,一切都很好。但是,我有一个额外的限制 - 我想最大化我选择的位置的地理分布。我如何表示该约束?
这是我现在拥有的基本示例:
static void Main(string[] args)
{
var locations = new List<LocationWithScore>()
{
new LocationWithScore() { LocationID = 0, Latitude = 43.644274M, Longitude = -79.478703M, Score = 20 },
new LocationWithScore() { LocationID = 1, Latitude = 43.644709M, Longitude = -79.476814M, Score = 20 },
new LocationWithScore() { LocationID = 2, Latitude = 43.643063M, Longitude = -79.477458M, Score = 20 },
new LocationWithScore() { LocationID = 3, Latitude = 43.650516M, Longitude = -79.469562M, Score = 20 },
new LocationWithScore() { LocationID = 4, Latitude = 43.642659M, Longitude = -79.463124M, Score = 20 }
};
SolverContext sContext = SolverContext.GetContext();
sContext.ClearModel();
Model model = sContext.CreateModel();
model.Name = "LocationWithScore";
Set items = new Set(Domain.Any, "candidates");
Decision take = new Decision(Domain.Boolean, "candidate", items);
model.AddDecision(take);
Parameter scoreParam = new Parameter(Domain.RealNonnegative, "score", items);
scoreParam.SetBinding(locations, "Score", "LocationID");
model.AddParameters(scoreParam);
model.AddConstraint("scoreConstraint", Model.Sum(Model.ForEach(items, item => scoreParam[item] * take[item])) >= 60);
model.AddGoal("locationGoal", GoalKind.Minimize, Model.Sum(Model.ForEach(items, item => take[item])));
var solution = sContext.Solve(new LpSolveDirective());
var report = solution.GetReport();
Console.WriteLine(report.ToString());
Console.WriteLine("Done");
Console.ReadKey();
}
internal class LocationWithScore
{
public int LocationID { get; set; }
public decimal Latitude { get; set; }
public decimal Longitude { get; set; }
public double Score { get; set; }
}
这将只选择前三个位置,这给了我 60 的目标,但是这三个位置非常接近地聚集在一起。我更希望它选择前三个(ID 0 - 2)和后两个(ID 3 和 4)中的一个,它们分布得更远。
有人可以在这里提供一些指导吗?提前谢谢了。