【问题标题】:Can I do concurrent cobyla optimizations using Accord.Net?我可以使用 Accord.Net 进行并发 cobyla 优化吗?
【发布时间】:2021-04-29 03:46:28
【问题描述】:

下面的代码是我正在使用的圆估计器的最小工作示例。它使用 Accord.Net 的 cobyla 优化器。 localize 方法的输入是一组点。使用优化器找到中心位置并返回。 (我的真实代码有点复杂,但我忽略了最不相关的东西)

代码运行良好,但我遇到的问题是 static 字段(我的真实代码中有更多字段)。当我同时优化多个问题时,static 字段会出现问题,因为优化器可能会读取用于另一个线程的值。

问题是如何使这段代码适用于并发代码?我可以抛弃静态并仍然在Func<double[], double> 中获得积分吗?还有其他方法可以规避静态的并发问题吗?

    internal class CircleLocalizer
    {
        private static (double, double)[] points; // I dislike these statics!
        private double[] prior = { 0, 0 };

        Func<double[], double> objective = x =>
        {
            var distancesToCenter = CircleLocalizer.points.Select(p => Distance.Euclidean(new[] { p.Item1, p.Item2 }, new[] { x[0], x[1] }));
            var averageDistance = distancesToCenter.Average();
            return distancesToCenter.Select(d => Math.Pow(d - averageDistance, 2)).Sum();
        };

        public double[] Localize((double, double) points)
        {
            CircleLocalizer.points = points;

            Cobyla cobyla = new Cobyla(2, objective);
            cobyla.Minimize(Prior);

            return cobyla.Solution;
        }
    }

【问题讨论】:

  • 不使用静态选项吗?
  • 我很乐意,但我不知道如何将points 变量传递给objective 函数,因为它必须是cobyla 优化器的Func&lt;double[], double&gt;。如果我将它们添加到 double[] 参数 cobyla 将开始优化它们,这是不正确的
  • Cobyla 是一种无衍生方法。使用不同的算法可能会获得更好的性能。

标签: c# optimization concurrency accord.net


【解决方案1】:

我建议将objective 重写为以点为参数的常规方法:

double Objective(double[] x, (double, double)[] points){
     var distancesToCenter = points.Select(p => Distance.Euclidean(new[] { p.Item1, p.Item2 }, new[] { x[0], x[1] }));
     var averageDistance = distancesToCenter.Average();
     return distancesToCenter.Select(d => Math.Pow(d - averageDistance, 2)).Sum();
}

然后这样称呼它

new Cobyla(2, x => Objective(x, points)); 

当您编写lambda function 时,您可以在外部范围内“捕获”变量。在内部,这被转换为一个对象,其中所有捕获的变量都作为类中的字段。

【讨论】:

  • Cobyla 不接受这样的点参数。但!这确实允许我使this.points 非静态!这解决了我的问题。我现在用new Cobyla(2, x =&gt; Objective(x)); 调用它,非常感谢。我会接受您的回答,并邀请您通过省略目标中的点并使用 this.points 来稍微改变它。非常感谢您的帮助!
  • @Goosebumps 我不确定你的意思。 Cobyla 的签名是Cobyla(Int32, Func&lt;Double[], Double&gt;)。假设点是(double, double)[],使用 lambda 捕获 points 应该没问题。在您的示例中,它是(double, double),但我认为这是一个错字。但是,如果您更愿意将其保留为应该也可以正常工作的字段。
  • 我的错。它确实有效!不知道第一次出了什么问题,一定是其他错误...
猜你喜欢
  • 2019-06-25
  • 1970-01-01
  • 1970-01-01
  • 2016-10-22
  • 2022-01-16
  • 1970-01-01
  • 1970-01-01
  • 2016-04-29
  • 1970-01-01
相关资源
最近更新 更多