Пример #1
0
 //copy constructor
 public NMMatrix(NMMatrix A)
 {
     _matrix = new double[A.N, A.M];
     _n = A.N;
     _m = A.M;
     for (int i = 0; i < _n; i++)
         for (int j = 0; j < _m; j++)
             _matrix[i, j] = A[i, j];
 }
Пример #2
0
        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;
        }
Пример #3
0
 public NMMatrix Diag()
 {
     NMMatrix A = new NMMatrix(_n, _n);
     for (int i = 0; i < _n; i++)
         A[i, i] = _vector[i];
     return A;
 }
Пример #4
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;
 }
Пример #5
0
 public NMMatrix Transpose()
 {
     //make shallow copy, so both transposed and untransposed matrix may be used in same calculation
     NMMatrix A = new NMMatrix();
     A._matrix = _matrix;
     A._m = _m;
     A._n = _n;
     A._transpose = !_transpose;
     return A;
 }
Пример #6
0
 public static NMMatrix operator *(NMMatrix A, NMMatrix B)
 {
     int l1 = A.N;
     int l2 = B.M;
     int l3 = A.M;
     if (l3 != B.N ) throw new Exception("NMMatrix.Mul: incompatable sizes");
     NMMatrix C = new NMMatrix(l1, l2);
     for (int i = 0; i < l1; i++)
         for (int j = 0; j < l2; j++)
         {
             double c = 0D;
             for (int k = 0; k < l3; k++)
                 c += A[i, k] * B[k, j];
             C._matrix[i, j] = c;
         }
     return C;
 }
Пример #7
0
 public NMMatrix ExtractMatrix(int col, int coln)
 {
     NMMatrix A = new NMMatrix(N, coln);
     for (int i = 0; i < N; i++)
         for (int j = 0; j < coln; j++)
             A[i, j] = this[i, col + j];
     return A;
 }
Пример #8
0
 public NMMatrix Apply(F func)
 {
     NMMatrix A = new NMMatrix(this);
     for (int i = 0; i < _n; i++)
         for (int j = 0; j < _m; j++)
             A[i, j] = func(A[i, j]);
     return A;
 }
Пример #9
0
 public NMMatrix Augment(NVector V)
 {
     if (N != V.N) throw new Exception("NMMatrix.Augment(Vector): 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;
 }
Пример #10
0
 public static NMMatrix operator /(NMMatrix A, double b)
 {
     int l1 = A.N;
     int l2 = A.M;
     NMMatrix C = new NMMatrix(l1,l2);
     for (int i = 0; i < l1; i++)
         for (int j = 0; j < l2; j++)
             C._matrix[i, j] = A[i, j] / b;
     return C;
 }
Пример #11
0
 public static NMMatrix I(int n)
 {
     NMMatrix A = new NMMatrix(n, n);
     for (int i = 0; i < n; i++)
         A._matrix[i, i] = 1D;
     return A;
 }
Пример #12
0
 public static NMMatrix operator -(NMMatrix A, NMMatrix B)
 {
     int l1 = A.N;
     int l2 = A.M;
     if (l1 != B.N || l2 != B.M) throw new Exception("NMMatrix.Subtract: incompatable sizes");
     NMMatrix C = new NMMatrix(A);
     for (int i = 0; i < l1; i++)
         for (int j = 0; j < l2; j++)
             C._matrix[i, j] -= B[i, j];
     return C;
 }
Пример #13
0
 public static NMMatrix operator +(NMMatrix A, NMMatrix B)
 {
     if (A.N != B.N || A.M != B.M) throw new Exception("NMMatrix.Add: incompatable sizes");
     NMMatrix C = new NMMatrix(A);
     for (int i = 0; i < A.N; i++)
         for (int j = 0; j < A.M; j++)
             C._matrix[i, j] += B[i, j];
     return C;
 }
Пример #14
0
 public static NMMatrix operator *(double a, NMMatrix B)
 {
     int l1 = B.N;
     int l2 = B.M;
     NMMatrix C = new NMMatrix(B);
     for (int i = 0; i < l1; i++)
         for (int j = 0; j < l2; j++)
             C._matrix[i, j] *= a;
     return C;
 }
Пример #15
0
 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;
 }
Пример #16
0
 public NMMatrix Augment(NMMatrix A)
 {
     if (N != A.N) throw new Exception("NMMatrix.Augment(Matrix): incompatable sizes");
     NMMatrix B = new NMMatrix(N, M + A.M);
     for (int i = 0; i < N; i++)
     {
         for (int j = 0; j < M; j++)
             B[i, j] = this[i, j];
         for (int j = 0; j < A.M; j++)
             B[i, M + j] = A[i, j];
     }
     return B;
 }
Пример #17
0
 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;
 }
Пример #18
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];
         eat = Math.Exp(-p[3] * t0);
         ebt = Math.Exp(-p[4] * t0);
         J[i, 1] = 1D - ebt; //B
         J[i, 2] = ebt; //C
         J[i, 4] = p[1] - p[2]; //beta
         J[i, 5] = (p[2] - p[1]) * p[4]; //t0
         if (t0 > 0D) //UnitStep portion
         {
             J[i, 0] = ebt * (1D - eat); //A
             J[i, 3] = p[0] * t0 * eat * ebt; //alpha
             J[i, 4] -= p[0] * (1D - eat); //beta
             J[i, 5] += p[0] * (p[4] * (1D - eat) - p[3] * eat); //t0
         }
         J[i, 4] *= t0 * ebt; //beta
         J[i, 5] *= ebt; //t0
     }
     return J;
 }