编程语言
首页 > 编程语言> > c# – 将地理分布表示为线性概率约束?

c# – 将地理分布表示为线性概率约束?

作者:互联网

我现在正在学习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)中的一个,它们会进一步扩展.

有人可以提供一些指导吗?提前谢谢了.

解决方法:

问题比我最初想的要复杂一些.就像我上面提到的,你需要计算色散.但是,地理点标准差的计算并不简单.这是一个MathWorks的解释.

似乎如果您的点不跨越大的地理区域,您可以通过计算2维的标准差来近似分散.否则,您将必须编写类似于MatLab,stdm中提供的函数.

更新

我花了一段时间,但我想我已经解决了这个问题.我必须说整套解算器程序很复杂.我在您提供的示例上测试了以下代码,它正确地选择了0,3和4.代码更改如下.

以下部分计算从位置i到位置j的距离,其中i和j是所提供目标集的元素.数据绑定到参数,以便稍后在目标中查询.

var dist = from l1 in locations 
          from l2 in locations 
          select new {ID1 = l1.LocationID, ID2 = l2.LocationID, dist = GetDistance(l1.Latitude, l1.Longitude, l2.Latitude, l2.Longitude)};

Parameter distance = new Parameter(Domain.RealNonnegative, "Location", items, items);
distance.SetBinding(dist, "dist", "ID1", "ID2");
model.AddParameter(distance);

最终目标实际上由两部分组成.第一个目标是最大化分数,第二个目标是最大化位置的分散.在这种情况下,我已将色散抽象为所选位置之间的总距离.我得到了一个例外,“模型有多个目标”,当我添加2个目标时,我必须将它们组合成一个目标,如下所示.

double maxDist = (from distances in dist select distances.dist).Max();
Term goal1 = Model.Sum(Model.ForEach(items, item => take[item] * scoreParam[item]));
Term goal2 = Model.Sum(Model.ForEach(items, i => Model.ForEach(items, j => take[i] * take[j] * distance[i, j])));
model.AddGoal("Dispersion", GoalKind.Maximize, Model.Sum(Model.Sum(goal1, maxDist), goal2));

GetDistance()使用System.Device.Location.GeoCoordinate计算2个坐标之间的距离;事实证明有一个C#实现.我将纬度和经度类型更改为两倍以避免类型转换.在使用大型案例之前,此代码需要更新.

public static double GetDistance(double lat1, double long1, double lat2, double long2)
{
    GeoCoordinate geo1 = new GeoCoordinate(lat1, long1);
    GeoCoordinate geo2 = new GeoCoordinate(lat2, long2);
    return geo1.GetDistanceTo(geo2);
}

标签:c,linear-programming,ms-solver-foundation,lpsolve
来源: https://codeday.me/bug/20190630/1332864.html