//method to calculate the root for a system of functions given an initial guess/vector //Gradient Descent with Fixed Alpha public double[] GradientAlpha(FunctionMatrix f, double[] x, double toler) { int counter = 0; int dim = x.GetLength(0); int r = f.Rows; double[,] Jmat = new double[r, dim]; Matrix MJmat = new Matrix(Jmat); Vector VFg1 = new Vector(r); Vector Vz = new Vector(dim); Vector VFg3 = new Vector(r); Vector VFg2 = new Vector(r); Vector VFgc = new Vector(r); Vector VFgnew = new Vector(r); Vector Vxnew = new Vector(dim); double alpha2 = 0; double alpha3 = 0; double[] xold = x; double[] xnew = new double[dim]; double g1 = 0; double g2 = 0; double g3 = 0; double gc = 0; double gnew = 0; double normz = 0; double h1 = 0; double h2 = 0; double h3 = 0; double ac = 0; do { VFg1 = f.EvaluateVector(xold); g1 = VFg1.Magnitude(); //calculate the Jacobian Jmat = jacobi(f, xold, 0.001); //now update the Matrix object which represents the Jacobian for (int i = 0; i < r; i++) for (int j = 0; j < dim; j++) MJmat[i, j] = Jmat[i, j]; Vz = 2 * (MJmat * VFg1); normz = Math.Sqrt(Vz.Magnitude()); if (normz > toler) { Vz = (1 / normz) * Vz; alpha3 = 1; VFg3 = f.EvaluateVector((double[])((Vector)xold - (alpha3 * Vz))); g3 = VFg3.Magnitude(); while (Math.Abs(g3 - g1) > toler) { alpha3 = 0.5 * alpha3; VFg3 = f.EvaluateVector((double[])((Vector)xold - (alpha3 * Vz))); g3 = VFg3.Magnitude(); if (Math.Abs(alpha3) < 0.5 * toler) break; } alpha2 = 0.5 * alpha3; VFg2 = f.EvaluateVector((double[])((Vector)xold - (alpha2 * Vz))); g2 = VFg2.Magnitude(); //perform interpolation h1 = (g2 - g1) / alpha2; h2 = (g3 - g2) / (alpha3 - alpha2); h3 = (h2 - h1) / alpha3; ac = 0.5 * (alpha2 - (h1 / h3)); VFgc = f.EvaluateVector((double[])((Vector)xold - (ac * Vz))); gc = VFgc.Magnitude(); if (gc < g3) { Vxnew = ((Vector)xold) - (ac * Vz); VFgnew = f.EvaluateVector((double[])Vxnew); gnew = VFgnew.Magnitude(); } else { Vxnew = ((Vector)xold) - (alpha3 * Vz); VFgnew = f.EvaluateVector((double[])Vxnew); gnew = VFgnew.Magnitude(); } //test for convergence if (Math.Abs(gnew - g1) < toler) break; else { xold = (double[])Vxnew; counter++; } //end if } } while (counter < 100); return (double[])Vxnew; //end of method }
//method to calculate the root for a system of functions given an initial guess/vector public double[] newtonraphson(FunctionMatrix f, double[] x, double toler) { int maxiter = 1000; double err = 10000000; int counter = 0; int dim = x.GetLength(0); int r = f.Rows; double[] xn = new double[dim]; //populating vector xn for (int i = 0; i < dim; i++) xn[i] = x[i]; double[] xnp1 = new double[dim]; while ((counter < maxiter) && (err > toler)) { Vector Fn = f.EvaluateVector(xn); //converting to Vector Objects Vector Vxn = new Vector(xn); //Need to calculate the Jacobi and convert it to a matrix double[,] j = jacobi(f, xn, 0.001); double[,] jinv = s.find_inverse(j, j.GetLength(0)); Matrix Jinv = new Matrix(jinv); //this is just F(xn)/F'(xn) Vector tmp = Jinv * Fn; //xnp1 = xn - F(xn)/F'(xn) Vector Vxnp1 = Vxn - tmp; //what is the size of the err i.e. xnp1-xn Vector Diff = Vxnp1 - Vxn; err = Diff.maxNorm(); double[] t = new double[dim]; xnp1 = (double[])Vxnp1; xn = xnp1; counter++; } return xn; //end of method }
//method to calculate the inverse of a matrix using the Sherman Morrison formula //this method will be utilised in the Broyden method public double[,] BroydenAinv(double[,] Ainvold, double[] deltax, double[] deltaF) { Matrix MAinvold = new Matrix(Ainvold); Vector Vdeltax = new Vector(deltax); Vector VdeltaF = new Vector(deltaF); //placeholder vector, won't be used for anything apart from calling the outer product and dot product Vector methods Vector interim = new Vector(1); Vector temp = new Vector(interim.dot(MAinvold, VdeltaF)); Vector u = new Vector(Vdeltax - temp); Vector v = new Vector(interim.dot(Vdeltax, MAinvold)); Matrix numer = new Matrix(interim.outer(u, v)); double denom = interim.dot(Vdeltax, temp); Matrix update = new Matrix(1 / denom * numer); Matrix MAinvnew = new Matrix(MAinvold + update); double[,] Ainvnew = (double[,])MAinvnew; return Ainvnew; }
//method to calculate the root for a system of functions given an initial guess/vector public double[] BroydenShermanMorrison(FunctionMatrix f, double[] x, double toler) { double err = 10000000; int counter = 0; int dim = x.GetLength(0); int r = f.Rows; double[] xn = new double[dim]; //populating vector xn for (int i = 0; i < dim; i++) xn[i] = x[i]; double[] xnp1 = new double[dim]; //first iteration i.e. use Newton Raphson for one iteration, the Inverse of the Jacobi will be used as the Ainv for Broyden Vector Fn = f.EvaluateVector(xn); Vector Vxn = new Vector(xn); //Need to calculate the Jacobi and convert it to a matrix double[,] j = jacobi(f, xn, 0.001); double[,] jinv = s.find_inverse(j, j.GetLength(0)); Matrix Jinv = new Matrix(jinv); //this is just F(xn)/F'(xn) Vector tmp = Jinv * Fn; //xnp1 = xn - F(xn)/F'(xn) Vector Vxnp1 = Vxn - tmp; //what is the size of the err i.e. xnp1-xn Vector Vdeltax = Vxnp1 - Vxn; err = Vdeltax.maxNorm(); xnp1 = (double[])Vxnp1; Vector placeholder = new Vector(1); //we'll use these later Vector VFnold = f.EvaluateVector(xn); Vector VFnew = f.EvaluateVector(xnp1); Vector VdeltaF = VFnew - VFnold; double[,] Aold = new double[dim, dim]; double[,] Anew = new double[dim, dim]; //now we'll start on the Broyden iteration element if (err < toler) return xn; else { while ((err > toler) && (counter < 1000)) { if (counter == 0) { Aold = jinv; Anew = BroydenAinv(Aold, (double[])Vdeltax, (double[])VdeltaF); } else { Anew = BroydenAinv(Aold, (double[])Vdeltax, (double[])VdeltaF); } //now update all the variables Vxnp1 = Vxn - placeholder.dot(new Matrix(Anew), VFnew); Vdeltax = Vxnp1 - Vxn; err = Vdeltax.maxNorm(); Aold = Anew; VFnold = f.EvaluateVector((double[])Vxn); VFnew = f.EvaluateVector((double[])Vxnp1); VdeltaF = VFnew - VFnold; Vxn = Vxnp1; xn = (double[])Vxn; counter++; } return xn; } //end of method }
//dot product of a vector and a Matrix public Vector dot(Vector v, Matrix m) { int mrows = m.Rows; int mcols = m.Cols; int vrows = v.Rows; if (mcols == vrows) { double[] temp = new double[mrows]; for (int i = 0; i < mrows; i++) { double sum = 0; for (int j = 0; j < vrows; j++) { double c = m[i, j] * v[j]; sum = sum + m[i, j] * v[j]; } temp[i] = sum; } Vector ans = new Vector(temp); return ans; } else return v; }
//outer productover of two vectors //dot product of two vectors public Matrix outer(Vector v1, Vector v2) { int r1 = v1.Rows; int r2 = v2.Rows; double[,] temp = new double[v1.rows, v2.rows]; for (int i = 0; i < r1; i++) { for (int j = 0; j < r2; j++) { temp[i, j] = v1.data[i] * v2.data[j]; } } Matrix m = new Matrix(temp); return m; }
public static Vector operator -(Vector a) { Vector tmp = new Vector(a.rows); for (int i = 0; i < a.rows; i++) tmp.data[i] = -a.data[i]; return tmp; }
//dot product of two vectors public double dot(Vector v1, Vector v2) { int r1 = v1.Rows; int r2 = v2.Rows; if (r1 == r2) { double sum = 0; for (int i = 0; i < r1; i++) { sum = sum + v1.data[i] * v2.data[i]; } return sum; } else return 0; }
public static Vector operator +(Vector a) { Vector tmp = new Vector(a); return tmp; }
public static Vector operator -(Vector a, Vector b) { if (a.rows != b.rows) return null; Vector tmp = new Vector(a.rows); for (int i = 0; i < a.rows; i++) tmp.data[i] = a.data[i] - b.data[i]; return tmp; }
//Product of Matrix and vector public static Vector operator *(Matrix a, Vector b) { if (a.Cols != b.rows) return null; int i, j; double sum = 0; Vector tmp = new Vector(a.Rows); for (i = 0; i < a.Rows; i++) { sum = 0; for (j = 0; j < a.Cols; j++) sum += a[i, j] * b[j]; tmp[i] = sum; } return tmp; }
//scalar product public static Vector operator *(double a, Vector b) { Vector tmp = new Vector(b.rows); for (int i = 0; i < b.rows; i++) tmp[i] = a * b[i]; return tmp; }
//scalar product public static double operator *(Vector a, Vector b) { if (a.rows != b.rows) return 0; Vector tmp = new Vector(a.rows); double sum = 0; for (int i = 0; i < a.rows; i++) sum += a[i] * b[i]; return sum; }
public Vector(Vector val) { rows = val.rows; data = new double[rows]; for (int i = 0; i < rows; i++) data[i] = val.data[i]; }
public Vector EvaluateVector(double[] val) { Vector tmp = new Vector(rows); int i; for (i = 0; i < rows; i++) tmp[i] = f[i, 0](val); return tmp; }