mathnet / mathnet-numerics

Math.NET Numerics
http://numerics.mathdotnet.com
MIT License
3.49k stars 897 forks source link

A question about curve fitting using Fit #969

Closed seabluescn closed 1 year ago

seabluescn commented 1 year ago

I need to fit a curve to a bunch of data, and I know that the theoretical function of the curve is y=aSin(bx+c) The implementation code is attached。Everything seems to work fine after the program runs and solves the problem. However, the third parameter about Curve is very difficult to understand. My function is three variables, and the parameters that need to be brought in here should be only three. The method signature is as follows: Func<double,double,double,double,double> actually the method needed here is: Func<double,double,double,double,double,double> For this reason my function method is defined as follows: double MyFunction1(double s, double a, double b, double c, double x) where the first parameter double s is not used at all, just to match the definition requirements. My question is: What is the purpose of having an extra input parameter here for the function method definition requirement than the actual variable?

CODE: public class CurvePageViewModel {
private double s = 0;

    private void Invalidate()
    {
        int Count = 200;
        double[] SampleX = new double[Count];
        double[] SampleY = new double[Count];

  //LoadData
  //......

 //Request a solution
        var result = Fit.Curve(
             SampleX,
             SampleY,
             (a, b, c, x) => MyFunction1(s, a, b, c, x),
             initialGuess0: 1,
             initialGuess1: 1,
             initialGuess2: 1,
             maxIterations: 10000000);

        var Result_P0 = result.P0;
        var Result_P1 = result.P1;
        var Result_P2 = result.P2;
    }

    //y=a*Sin(b*x+c)
    private static double MyFunction1(double s, double a, double b, double c, double x)
    {
        double y= a * Math.Sin(b * x + c);
        return y;
    }
}
jkalias commented 1 year ago

Hi,

I think you are misusing the API here. If you define your function as

private static double MyFunction1(double a, double b, double c, double x)

you can use it directly like this

       var result = Fit.Curve(
             SampleX,
             SampleY,
             MyFunction1,
             initialGuess0: 1,
             initialGuess1: 1,
             initialGuess2: 1,
             maxIterations: 10000000);

        var Result_P0 = result.P0;
        var Result_P1 = result.P1;
        var Result_P2 = result.P2;

That should solve your problem, right?

seabluescn commented 1 year ago

Indeed! I made a low-level mistake, thanks for the correction.

cdrnet commented 1 year ago

or a bit shorter:

var (a, b, c) = Fit.Curve(
     SampleX,
     SampleY,
     (pa, pb, pc, x) => pa * Math.Sin(pb * x + pc),
     initialGuess0: 1,
     initialGuess1: 1,
     initialGuess2: 1,
     maxIterations: 10000000);