I was using Math.Numerics in C# for my coding purposes but now I am learning Alglib since it has cross platform universal implementations. I am moving my Non-Linear curve fitting for the assumed equation and with sample generated data and upon successful i can fit my own data.
Curve Equation is : y = a * cos(b * x + c) + d * sin(e * x + f)
and C# code is :
Code:
class Program
{
public static int Main(string[] args)
{
/*string fileName = @"C:\Dropbox\Dropbox\Trade\AVLTreeC#\TestFiles\exchange.csv";
GetRawDataXY(fileName);*/
double[] coeffs=InitalizeSampleData(1000);
System.Console.WriteLine("Curve original Coeffs are : {0}", alglib.ap.format(coeffs, 10));
Random randNum = new Random();
// Random randInt = new Random();
double[] c = Enumerable.Repeat(0, 5 + 1)
.Select(i => randNum.NextDouble() + 1).ToArray();
double epsf = 0;
double epsx = 0.000001;
int maxits = 0;
int info;
alglib.lsfitstate state;
alglib.lsfitreport rep;
//
// Fitting without weights
//
alglib.lsfitcreatefgh(Curve.Xdata, Curve.Ydata, c, out state);
alglib.lsfitsetcond(state, epsf, epsx, maxits);
alglib.lsfitfit(state, ModelValue, ModelGradient, ModelHessian, null, null);
alglib.lsfitresults(state, out info, out c, out rep);
System.Console.WriteLine("{0}", info); // EXPECTED: 2
System.Console.WriteLine("Curve Generated coeffs without weights are : {0}", alglib.ap.format(c, 10)); // EXPECTED: [1.5]
System.Console.ReadLine();
return 0;
}
private static double[] InitalizeSampleData(int sampleSize)
{
int count = 0;
Random randNum = new Random();
// Random randInt = new Random();
double[] coeffs = Enumerable.Repeat(0, 5 + 1)
.Select(j => randNum.NextDouble() + 1).ToArray();
Curve.Xdata = new double[sampleSize, 1];
Curve.Ydata = new double[sampleSize];
for (int i=0;i<sampleSize;i++)
{
Curve.Xdata[count, 0] = Convert.ToDouble(i+1);
double[] xData =new double[1] { Curve.Xdata[count,0] };
ModelValue(coeffs, xData, ref Curve.Ydata[count], null);
count++;
}
return coeffs;
}
protected static void ModelValue(double[] parameters, double[] x, ref double func, object obj)
{
func = parameters[0] * Math.Cos(parameters[1] * x[0] + parameters[2]) + parameters[3] * Math.Sin(parameters[4] * x[0] + parameters[5]);
}
protected static void ModelGradient(double[] parameters, double[] x, ref double func, double[] gradient, object obj)
{
ModelValue(parameters, x, ref func, obj);
gradient[0] = Math.Cos(parameters[1] * x[0] + parameters[2]);
gradient[1] = -parameters[0] * Math.Sin(parameters[1] * x[0] + parameters[2]) * x[0];
gradient[2] = -parameters[0] * Math.Sin(parameters[1] * x[0] + parameters[2]);
gradient[3] = Math.Sin(parameters[4] * x[0] + parameters[5]);
gradient[4] = parameters[3] * Math.Cos(parameters[4] * x[0] + parameters[5]) * x[0];
gradient[5] = parameters[3] * Math.Cos(parameters[4] * x[0] + parameters[5]);
}
protected static void ModelHessian(double[] c, double[] x, ref double func, double[] grad, double[,] hess, object obj)
{
ModelValue(c, x, ref func, obj);
ModelGradient(c, x, ref func, grad, obj);
Hessian(x[0], c, ref hess);
}
private static void Hessian(double x, double[] parameters, ref double[,] hess)
{
hess[0, 0] = 0; //d2/du2
hess[1, 0] = -Math.Sin(parameters[1] * x + parameters[2]) * x; //d2/dvdu
hess[2, 0] = -Math.Sin(parameters[1] * x + parameters[2]); //d2/dwdu
hess[3, 0] = 0;//d2/dxdu
hess[4, 0] = 0;//d2/dydu
hess[5, 0] = 0;//d2/dydz
hess[0, 1] = -Math.Sin(parameters[1] * x + parameters[2]);//d2/dudv
hess[1, 1] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]) * x * x; //d2/dv2
hess[2, 1] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]) * x; //d2/dwdv
hess[3, 1] = 0;//d2/dxdv
hess[4, 1] = 0;//d2/dydv
hess[5, 1] = 0;////d2/dzdv
hess[0, 2] = -Math.Sin(parameters[1] * x + parameters[2]) * x;//d2/dudw
hess[1, 2] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]) * x; //d2/dvdw
hess[2, 2] = -parameters[0] * Math.Cos(parameters[1] * x + parameters[2]); //d2/dw2
hess[3, 2] = 0;//d2/dxdw
hess[4, 2] = 0;//d2/dydw
hess[5, 2] = 0;////d2/dzdw
hess[0, 3] = 0;//d2/dudx
hess[1, 3] = 0; //d2/dvdx
hess[2, 3] = 0; //d2/dwdx
hess[3, 3] = 0; //d2/dx2
hess[4, 3] = Math.Cos(parameters[4] * x + parameters[5]) * x;//d2/dydx
hess[5, 3] = Math.Cos(parameters[4] * x + parameters[5]); ////d2/dzdx
hess[0, 4] = 0;//d2/dudy
hess[1, 4] = 0; //d2/dvdy
hess[2, 4] = 0; //d2/dwdy
hess[3, 4] = Math.Cos(parameters[4] * x + parameters[5]) * x; //d2/dxdy
hess[4, 4] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]) * x * x;//d2/dy2
hess[5, 4] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]) * x; ////d2/dzdy
hess[0, 5] = 0;//d2/dudz
hess[1, 5] = 0; //d2/dvdz
hess[2, 5] = 0; //d2/dwdz
hess[3, 5] = Math.Cos(parameters[4] * x + parameters[5]); //d2/dxdz
hess[4, 5] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]) * x;//d2/dydz
hess[5, 5] = -parameters[3] * Math.Sin(parameters[4] * x + parameters[5]); ////d2/dz2
}
public static void GetRawDataXY(string filename)
{
int count = 0;
var lines = File.ReadAllLines(filename);
Curve.Xdata = new double[lines.Count(),1];
Curve.Ydata = new double[lines.Count()];
foreach (var line in lines)
{
var elements = line.Split(';');
Curve.Xdata[count,0] = Convert.ToDouble(elements[0]);
Curve.Ydata[count] = Convert.ToDouble(elements[1]);
count++;
}
}
public class Curve
{
/*Global Variables*/
public static double[,] Xdata;
public static double[] Ydata;
}
}
Ofcourse I am getting some values for Coeffs. But I wonder whether this approach is correct. I suspect on function alglib.lsfitfit algorithm. I have hard in understanding what it does. I just followed documentation. Does it minimize on R2 basis? I want my curve fitting to stop fitting when it reached below criteria:
NewCalcR2-oldCalcR2 is <= Given delta value or
Magnitude of(OldCoffVector-NewCoeffVector) <=GivenDeltaValue or IterationCount reached maximum
Ofcourse I know this by looking at Info value. I need to make sure if this is correct.
Output from Console:
As you see from ouput, original and generated coeff no way near to the value. I want the generated coeffs to be as approximate equal to that. How could i achieve that?