Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
189 views
in Technique[技术] by (71.8m points)

c# - Can I do concurrent cobyla optimizations using Accord.Net?

The code below is a minimal working example of a circle estimator i'm using. It usses Accord.Net's cobyla optimizer. The input for the localize method is a set of points. The center location is found using the optimizer and returned. (My real code is a bit more complicated but I left out most less relevant stuff)

The code is working fine but the issue I have is with the static fields (I have more of them in my real code). When I optimize multiple problems concurrently the static field will give problems because the optimizer might read values intended for another thread.

The question is how do I make this code work for concurrent code? Can I ditch the statics and still get the points inside the Func<double[], double>? Are there other ways to circumvent the concurrency problems with the statics?

    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;
        }
    }
question from:https://stackoverflow.com/questions/65883055/can-i-do-concurrent-cobyla-optimizations-using-accord-net

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I would suggest rewriting objective to a regular method that takes the points as a parameter:

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();
}

and call it like

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

When you are writing a lambda function you can 'capture' variables in the outer scope. Internally this is converted to an object with all the captured variables as fields in the class.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...