public lsfit(vector x, vector y, vector yerr, Func <double, double>[] fs) { int dsize = x.size; int nf = fs.Length; matrix A = new matrix(dsize, nf); vector b = new vector(dsize); fun = fs; for (int i = 0; i < dsize; i++) { b[i] = y[i] / yerr[i]; for (int k = 0; k < nf; k++) { A[i, k] = fs[k](x[i]) / yerr[i]; } } qr_decomp_GS decomp = new qr_decomp_GS(A); q = decomp.Q; r = decomp.R; c = decomp.solve(b); qr_decomp_GS decomp_covar = new qr_decomp_GS(A.T * A); covar = decomp_covar.inverse(); cerr = new vector(covar.size1); for (int i = 0; i < covar.size1; i++) { cerr[i] = Sqrt(covar[i, i]); } }
} // newton complex public static (vector, int) newton( Func <vector, vector> f, // func takes vector(x1,...,xn) returns vector(f1(..),..,fn(..)) vector x, // starting values of vector(x1,...,xn) double eps = 1e-3, // accuracy goal ||f(x)||<eps double dx = 1e-7 // finite difference used in numerical eval of jacobian ) { // overload that implements a multiple-dimensional newton rootfinder for real functions of real variables int n = x.size; int nsteps = 0; vector fx = f(x); double lam; do { nsteps++; // create jacobian matrix J = jacobian(f, x, fx, dx); // find jacobian inverse by QR-decomposition qr_decomp_GS qrd = new qr_decomp_GS(J); matrix J_inv = qrd.inverse(); // solve J*Dx = - fx for newton stepsize Dx vector Dx = -J_inv * fx; // lambda factor lam = 1.0; // backtracking linesearch algorithm (first failing is good, second is step out try again) while (f(x + lam * Dx).norm2() > fx.norm2() * (1 - lam / 2) & lam > 1.0 / 64) { lam /= 2; } // norm2 is an euclidean vector norm by its definition, with over/underflow potential // Update values x = x + lam * Dx; fx = f(x); }while (fx.norm2() > eps); Error.WriteLine($"rootf.newton returning x, a condition is satisfied"); Error.WriteLine($"f(x).norm2() {fx.norm2()}"); Error.WriteLine($"eps {eps}"); Error.WriteLine($"lam {lam}"); Error.WriteLine($"dx {dx}\n"); return(x, nsteps); } // qnewton real vector
static void B() { WriteLine("Problem B"); var rand = new System.Random(); int m = 2 + rand.Next(6); int n = m; WriteLine("Random square matrix A"); matrix A = make_random_matrix(n, m); A.print("A = "); qr_decomp_GS decomposition = new qr_decomp_GS(A); matrix B = decomposition.inverse(); WriteLine("B inverse of Q*R."); B.print("B = "); matrix I = A * B; I.print("A * B = "); }