//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 }
//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; }