Exemple #1
0
 public static NVector operator *(double a, NVector B)
 {
     NVector C = new NVector(B);
     for (int i = 0; i < B._n; i++)
         C._vector[i] *= a;
     return C;
 }
Exemple #2
0
 public NVector(NVector A)
 {
     _vector = new double[A._n];
     _n = A._n;
     for (int i = 0; i < A._n; i++)
         _vector[i] = A._vector[i];
 }
Exemple #3
0
 public static NVector operator *(NVector A, NVector B)
 {
     if (A._n != B._n) throw new Exception("NVector operator *: incompatable vector size");
     NVector C = new NVector(A);
     for (int i = 0; i < A._n; i++)
         C._vector[i] *= B._vector[i];
     return C;
 }
 public LevenbergMarquardt(Function func, JFunc Jfunc, NVector p_min, NVector p_max, NVector dp, double[] eps, UpdateType updateType)
 {
     this.func = func;
     this.Jfunc = Jfunc;
     n = p_min.N;
     this.p_min = p_min;
     if (p_max.N != n) throw new Exception("LevenbergMarquardt: size mismatch p_max");
     this.p_max = p_max;
     if (Jfunc == null)
     {
         if (dp.N != n) throw new Exception("LevenbergMarquardt: size mismatch dp");
         this.dp = dp;
     }
     MaxIter = 50 * n;
     this.eps = eps;
     this.updateType = updateType;
 }
Exemple #5
0
 private static bool fitSignal(double[] d, int start, int dataLength,
     ref double A, ref double B, ref double C, ref double a, ref double b, ref double tOffset)
 {
     NVector t = new NVector(dataLength);
     for (int t0 = 0; t0 < dataLength; t0++) t[t0] = (double)t0 / SR;
     NVector y = new NVector(dataLength);
     for (int i = 0; i < dataLength; i++)
         y[i] = d[start + i];
     NVector p = LM.Calculate(new NVector(new double[] { A, B, C, a, b, tOffset }), t, y);
     A = p[0];
     B = p[1];
     C = p[2];
     a = p[3];
     b = p[4];
     tOffset = p[5];
     return LM.Result > 0;
 }
Exemple #6
0
 public NVector Abs()
 {
     NVector A = new NVector(this);
     for (int i = 0; i < _n; i++)
         A._vector[i] = Math.Abs(_vector[i]);
     return A;
 }
Exemple #7
0
 public static NVector Uniform(double c, int dim)
 {
     NVector A = new NVector(dim);
     for (int i = 0; i < dim; i++)
         A._vector[i] = c;
     return A;
 }
Exemple #8
0
 public static NVector operator /(NVector A, double b)
 {
     NVector C = new NVector(A);
     for (int i = 0; i < A._n; i++)
         C._vector[i] /= b;
     return C;
 }
Exemple #9
0
 static NMMatrix Jfunc(NVector t, NVector p)
 {
     double eat;
     double ebt;
     NMMatrix J = new NMMatrix(t.N, p.N);
     for (int i = 0; i < t.N; i++)
     {
         double t0 = t[i] - p[5];
         if (t0 < 0D)
             J[i, 2] = 1D;
         else
         {
             eat = Math.Exp(-p[3] * t0);
             ebt = Math.Exp(-p[4] * t0);
             J[i, 0] = ebt * (1D - eat);
             J[i, 1] = 1D - ebt;
             J[i, 2] = ebt;
             J[i, 3] = p[0] * t0 * eat * ebt;
             J[i, 4] = -ebt * t0 * (p[0] * (1D - eat) + p[2] - p[1]);
             J[i, 5] = ebt * (p[0] * (p[4] * (1D - eat) - p[3] * eat) + (p[2] - p[1]) * p[4]);
         }
     }
     return J;
 }
Exemple #10
0
 public double Dot(NVector A)
 {
     if (A._n != _n) throw new Exception("NVector.Dot: incompatable sizes");
     double c = 0D;
     for (int i = 0; i < A._n; i++)
         c += A._vector[i] * _vector[i];
     return c;
 }
 private NMMatrix Jacobian(NVector p, NVector y)
 {
     NVector ps = new NVector(p); //save a copy
     NMMatrix J = new NMMatrix(m, n); //creating a new J from scratch
     double del_p;
     for (int j = 0; j < n; j++)
     {
         del_p = Math.Max(dp[j] * Math.Abs(p[j]), dp[j]);
         p[j] = ps[j] + del_p;
         NVector y1 = func(t, p);
         if (dp[j] != 0D) //forward or backward difference
             J.ReplaceColumn(j, (y1 - y) / del_p);
         else //central difference
         {
             p[j] = ps[j] - del_p;
             J.ReplaceColumn(j, (y1 - func(t, p)) / (2D * del_p));
         }
         p[j] = ps[j]; //restore this value
     }
     return J;
 }
 private NMMatrix Broyden(NVector p_old, NVector y_old, NMMatrix J, NVector p, NVector y)
 {
     NVector h = p - p_old;
     J = J + (y - y_old - J * h).Cross(h) / h.Dot(h);
     return J;
 }
        public NVector Calculate(NVector par_initial, NVector t, NVector y_dat)
        {
            _result = 0;
            m = t.N;
            if (par_initial.N != n) throw new Exception("LevenbergMarquardt.Calculate: size mismatch parms");
            this.p = par_initial;
            this.t = t;
            if (y_dat.N != m) throw new Exception("LevenbergMarquardt.Calculate: size mismatch t-y");
            this.y_dat = y_dat;

            //            weight_sq = (m - n + 1) / y_dat.Dot(y_dat);
            DOF = (double)(m - n + 1);

            //initalize Jacobian and related matrices
            y_hat = func(t, p);
            y_old = y_hat;
            if (Jfunc == null)
                J = Jacobian(p, y_hat);
            else
                J = Jfunc(t, p);
            NVector delta_y = y_dat - y_hat;
            X2 = delta_y.Dot(delta_y);
            JtJ = J.Transpose() * J;
            Jtdy = J.Transpose() * delta_y;

            iteration = 0;

            if (Jtdy.Abs().Max() < eps[0])
            {
                _result = 1;
                return p; //Good guess!!!
            }
            if (updateType == UpdateType.Marquardt)
                lambda = 0.01D;
            else
                lambda = 0.01D * JtJ.Diag().Max();

            bool stop = false;

            /************************** Begin Main loop ***********************/
            // y_hat = vector of y estimates for current value of parameters
            // y_try = vector of y estimates for current trial value of parameters
            // y_dat = given dependent values (fixed)
            // y_old = vector of y estimates for previous value of parameters (used in Broyden estimate of J)
            // t = given independent values (fixed)
            // p = current accepted estimate of parameters
            // h = last calculated (trial) increment for the parameters
            // p_try = current trial value for the parameters
            // p_old = previous accepted value of parameters (used in Broyden estimate of J)
            // X2 = chi^2 of last accepted estimate
            // X2_try = chi^2 of current trial estimate
            // J = current estimate of Jacobian at p

            while (!stop)
            {
                iteration++;

                NVector h;
                if (updateType == UpdateType.Marquardt)
                    h = Jtdy / (JtJ + lambda * JtJ.Diag().Diag());
                else
                    h = Jtdy / (JtJ + lambda * NMMatrix.I(n));

                NVector p_try = (p + h).Max(p_min).Min(p_max);

                NVector y_try = func(t, p_try);
                delta_y = y_dat - y_try;

                double X2_try = delta_y.Dot(delta_y);

                if (updateType == UpdateType.Quadratic)
                {
                    alpha = Jtdy.Dot(h) / ((X2_try - X2) / 2D + 2D * Jtdy.Dot(h));
                    h = h * alpha;
                    p_try = (p_try + h).Max(p_min).Min(p_max);
                    delta_y = y_dat - func(t, p_try);
                    X2_try = delta_y .Dot(delta_y);
                }
                dX2 = X2_try - X2;

                double rho = -dX2 / (2D * (lambda * h + Jtdy).Dot(h));

                if (dX2 < 0D) //found a better estimate
                {
                    X2 = X2_try;
                    p_old = p;
                    p = p_try;
                    y_old = y_hat;
                    y_hat = y_try;

                    if (iteration % (2 * n) == 0) //|| dX2 > 0 or is it rho > ep[3] ?
                        if (Jfunc == null)
                            J = Jacobian(p, y_hat);
                        else
                            J = Jfunc(t, p);
                    else
                        J = J + (y_hat - y_old - J * h).Cross(h) / h.Dot(h); //Broyden rank-1 update of J

                    JtJ = J.Transpose() * J;
                    Jtdy = J.Transpose() * delta_y;

                    switch (updateType)
                    {
                        case UpdateType.Marquardt:
                            lambda = Math.Max(lambda / lambda_DN_fac, 1E-7);
                            break;
                        case UpdateType.Quadratic:
                            lambda = Math.Max(lambda / (1 + alpha), 1E-7);
                            break;
                        case UpdateType.Nielsen:
                            lambda = lambda * Math.Max(1D / 3D, 1D - Math.Pow(2D * rho - 1D, 3));
                            nu = 2D;
                            break;
                    }

                    if (Jtdy.Abs().Max() < eps[0] && iteration > 2)
                    {
                        _result = 1;
                        stop = true;
                    }
                    else if ((h / p).Abs().Max() < eps[1] && iteration > 2)
                    {
                        _result = 2;
                        stop = true;
                    }
                    else if (X2 / (m - n + 1) < eps[2] && iteration > 2)
                    {
                        _result = 3;
                        stop = true;
                    }
                }
                else //Not a better estimate
                {
                    if (iteration % (2 * n) == 0) //update J every 2n th no matter what
                    {
                        if (Jfunc == null)
                            J = Jacobian(p, y_hat);
                        else
                            J = Jfunc(t, p);
                        JtJ = J.Transpose() * J;
                        Jtdy = J.Transpose() * (y_dat - y_hat);
                    }

                    switch (updateType)
                    {
                        case UpdateType.Marquardt:
                            lambda = Math.Min(lambda * lambda_UP_fac, 1E7);
                            break;
                        case UpdateType.Quadratic:
                            lambda = lambda + Math.Abs(dX2 / (2D * alpha));
                            break;
                        case UpdateType.Nielsen:
                            lambda = lambda * nu;
                            nu *= 2D;
                            break;
                    }
                }

                if (iteration > MaxIter && !stop)
                {
                    _result = -1;
                    return p;
                }
            }
            /************************** End Main loop ************************/

            return p;
        }
Exemple #14
0
 static void Main3(string[] args)
 {
     NVector t = new NVector(16000);
     for (int t0 = 0; t0 < 16000; t0++) t[t0] = (double)t0 / 512D;
     NVector p_true = new NVector(new double[] { -5000D, 5000D, 3000D, 4D, 0.01D, 0.12 });
     NVector y = new NVector(func(t, p_true));
     Random rand = new Random();
     for (int i = 0; i < 16000; i++)
         y[i] += (2D * rand.NextDouble() - 1D) * 90D;
     NVector p = LM.Calculate(new NVector(new double[] { -4000D, 0D, 2900D, 10D, 0.025, 0.25D }), t, y);
     Console.WriteLine("Result = " + LM.Result.ToString());
     Console.WriteLine("Iterations = " + LM.Iterations.ToString("0"));
     Console.WriteLine("Chi square = " + LM.ChiSquare);
     Console.WriteLine("SE of fit = " + LM.normalizedStandardErrorOfFit);
     Console.WriteLine("Estimates");
     Console.WriteLine(p.ToString("0.00000"));
     Console.WriteLine(LM.parameterStandardError.ToString("0.0000"));
     Console.ReadKey();
 }
Exemple #15
0
 static void Main2(string[] args)
 {
     NVector A = new NVector(new double[] { 1, 3, 5, -2, 0 });
     NVector B = new NVector(new double[] { -1, -2, 3, 1, 2 });
     NVector C = A + B;
     Console.WriteLine("A =" + A.ToString("0.000"));
     Console.WriteLine("B =" + B.ToString("0.000"));
     Console.WriteLine("A+B =" + C.ToString("0.000"));
     double p = A.Dot(B);
     NMMatrix E = A.Cross(B);
     Console.WriteLine("A x B =" + E.ToString("0.000"));
     E[4, 0] = -2;
     E[4, 1] = 3;
     E[4, 2] = 5;
     E[4, 3] = -5;
     E[4, 4] = 7;
     E[0, 0] = -7;
     E[1, 3] = -3;
     E[3, 4] = -3.5;
     E[2, 4] = -2;
     NMMatrix H = new NMMatrix(new double[,] { { 5, 3, -2 ,1}, { 0, 3, 2,-3 }, { 4, 2, 3,2 }, { -6, 2, 8,-5 } });
     Console.WriteLine("H =" + H.ToString("0.000"));
     NVector V = new NVector(new double[] { 1, -1, 3, -2 });
     Console.WriteLine("V =" + V.ToString("0.000"));
     Console.WriteLine(" V / H =" + (V / H).ToString("0.0000"));
     NMMatrix HI = H.Inverse();
     Console.WriteLine("Inverse H =" + HI.ToString("0.000"));
     Console.WriteLine("H * HI " + (H * HI).ToString("0.00000"));
     Console.ReadKey();
     NVector F = C / E;
     NMMatrix G = E.Inverse();
     NMMatrix N = (G * E - NMMatrix.I(5)).Apply((LinearAlgebra.F)Math.Abs);
     double e = N.Max();
     Console.WriteLine((e*1E15).ToString("0.00"));
     Console.ReadKey();
 }
Exemple #16
0
 public NVector Apply(F func)
 {
     NVector A = new NVector(_n);
     for (int i = 0; i < _n; i++)
         A._vector[i] = func(_vector[i]);
     return A;
 }
Exemple #17
0
 public NMMatrix Cross(NVector A)
 {
     NMMatrix C = new NMMatrix(_n, A._n);
     for (int i = 0; i < _n; i++)
         for (int j = 0; j < A._n; j++)
             C[i,j] += _vector[i] * A._vector[j];
     return C;
 }
Exemple #18
0
 public NMMatrix Augment(NVector V)
 {
     if (N != V.N) throw new Exception("NMMatrix.Concatenate: incompatable sizes");
     NMMatrix B = new NMMatrix(N, M + 1);
     for (int i = 0; i < N; i++)
     {
         for (int j = 0; j < M; j++)
             B[i, j] = this[i, j];
         B[i, M] = V[i];
     }
     return B;
 }
Exemple #19
0
 public NVector Min(NVector A)
 {
     NVector B = new NVector(this);
     for (int i = 0; i < _n; i++)
         if (A._vector[i] < _vector[i]) B._vector[i] = A._vector[i];
     return B;
 }
Exemple #20
0
 public NVector Diag()
 {
     if (_n != _m) throw new Exception("NMMatrix.Diag: non-square matrix");
     NVector A = new NVector(_n);
     for (int i = 0; i < _n; i++)
         A[i] = _matrix[i, i];
     return A;
 }
Exemple #21
0
 public NVector ExtractColumn(int col)
 {
     if (col < 0 || col >= this.M) throw new Exception("NMMatrix.ReplaceColumn: invalid column number");
     NVector V = new NVector(N);
     for (int j = 0; j < _n; j++)
         V[j] = this[j, col];
     return V;
 }
Exemple #22
0
 public void ReplaceColumn(int col, NVector V)
 {
     if (col < 0 || col >= this.M) throw new Exception("NMMatrix.ReplaceColumn: invalid column number");
     for (int j = 0; j < _n; j++)
         this[j, col] = V[j];
 }
Exemple #23
0
 public static NVector operator *(NMMatrix A, NVector B)
 {
     if (A.M != B._n) throw new Exception("NVector.Mul: incompatable sizes");
     NVector C = new NVector(A.N);
     for (int i = 0; i < A.N; i++)
     {
         double c = 0D;
         for (int j = 0; j < A.M; j++)
             c += A[i, j] * B._vector[j];
         C._vector[i] = c;
     }
     return C;
 }
Exemple #24
0
        /* Five parameter fitting functions
        static NVector func(NVector t, NVector p)
        {
            NVector y = new NVector(t.N);
            for (int i = 0; i < t.N; i++)
            {
                double t0 = t[i] - p[3];
                if (t0 > 0)
                    y[i] = p[4] + p[0] * (1D - Math.Exp(-p[1] * t0)) * Math.Exp(-p[2] * t0);
                else
                    y[i] = p[4];
            }
            return y;
        }

        static NMMatrix Jfunc(NVector t, NVector p)
        {
            NMMatrix J = new NMMatrix(t.N, p.N);
            for (int i = 0; i < t.N; i++)
            {
                J[i, 4] = 1D;
                double t0 = t[i] - p[3];
                if (t0 < 0D) continue;
                J[i, 0] = (1D - Math.Exp(-p[1] * t0)) * Math.Exp(-p[2] * t0);
                J[i, 1] = p[0] * t0 * Math.Exp(-(p[1] + p[2]) * t0);
                J[i, 2] = -p[0] * t0 * (1D - Math.Exp(-p[1] * t0)) * Math.Exp(-p[2] * t0);
                J[i, 3] = p[0] * (p[2] * (1D - Math.Exp(-p[1] * t0)) * Math.Exp(-p[2] * t0) - p[1] * Math.Exp(-(p[1] + p[2]) * t0));
            }
            return J;
        }
        */
        /* Six parameter fitting functions */
        static NVector func(NVector t, NVector p)
        {
            //parameters: A, B, C, a, b, t0
            NVector y = new NVector(t.N);
            for (int i = 0; i < t.N; i++)
            {
                double t0 = t[i] - p[5];
                if (t0 > 0)
                {
                    double ebt = Math.Exp(-p[4] * t0);
                    y[i] = p[2] + p[0] * ebt * (1D - Math.Exp(-p[3] * t0)) + (p[1] - p[2]) * (1D - ebt);
                }
                else
                    y[i] = p[2];
            }
            return y;
        }