我可以使用 Accord.Net 进行并发 cobyla 优化吗?
Can I do concurrent cobyla optimizations using Accord.Net?
下面的代码是我正在使用的圆估计器的最小工作示例。它使用 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;
}
}
我建议将 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 时,您可以 'capture' 外部作用域中的变量。在内部,它被转换为一个对象,所有捕获的变量都作为 class.
中的字段
下面的代码是我正在使用的圆估计器的最小工作示例。它使用 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;
}
}
我建议将 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 时,您可以 'capture' 外部作用域中的变量。在内部,它被转换为一个对象,所有捕获的变量都作为 class.
中的字段