public static double[] vandermonde_coef_1d(int nd, double[] xd, double[] yd) //****************************************************************************80 // // Purpose: // // VANDERMONDE_COEF_1D computes coefficients of a 1D Vandermonde interpolant. // // Discussion: // // We assume the interpolant has the form // // p(x) = c1 + c2 * x + c3 * x^2 + ... + cn * x^(n-1). // // We have n data values (x(i),y(i)) which must be interpolated: // // p(x(i)) = c1 + c2 * x(i) + c3 * x(i)^2 + ... + cn * x(i)^(n-1) = y(i) // // This can be cast as an NxN linear system for the polynomial // coefficients: // // [ 1 x1 x1^2 ... x1^(n-1) ] [ c1 ] = [ y1 ] // [ 1 x2 x2^2 ... x2^(n-1) ] [ c2 ] = [ y2 ] // [ ...................... ] [ ... ] = [ ... ] // [ 1 xn xn^2 ... xn^(n-1) ] [ cn ] = [ yn ] // // and if the x values are distinct, the system is theoretically // invertible, so we can retrieve the coefficient vector c and // evaluate the interpolant. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 07 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int ND, the number of data points. // // Input, double XD[ND], YD[ND], the data values. // // Output, double VANDERMONDE_COEF_1D[ND], the coefficients of the // interpolating polynomial. // { double[] ad = vandermonde_matrix_1d(nd, xd); double[] cd = QRSolve.qr_solve(nd, nd, ad, yd); return(cd); }
public static double[] pwl_approx_1d(int nd, double[] xd, double[] yd, int nc, double[] xc) //****************************************************************************80 // // Purpose: // // PWL_APPROX_1D determines the control values for a PWL approximant. // // Discussion: // // The piecewise linear approximant is defined by NC control pairs // (XC(I),YC(I)) and approximates ND data pairs (XD(I),YD(I)). // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int ND, the number of data points. // ND must be at least 1. // // Input, double XD[ND], the data points. // // Input, double YD[ND], the data values. // // Input, int NC, the number of control points. // NC must be at least 1. // // Input, double XC[NC], the control points. Set these with a // command like // xc = r8vec_linspace_new ( nc, xmin, xmax ); // // Output, double PWL_APPROX_1D[NC], the control values. // { // // Define the NDxNC linear system that determines the control values. // double[] a = pwl_approx_1d_matrix(nd, xd, yd, nc, xc); // // Solve the system. // double[] yc = QRSolve.qr_solve(nd, nc, a, yd); return(yc); }
private static void test01(int prob) //****************************************************************************80 // // Purpose: // // TEST01 tests VANDERMONDE_INTERP_1D. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 07 October 2012 // // Author: // // John Burkardt // { const bool debug = false; int i; Console.WriteLine(""); Console.WriteLine("TEST01:"); Console.WriteLine(" Interpolate data from TEST_INTERP problem #" + prob + ""); int nd = TestInterp.p00_data_num(prob); Console.WriteLine(" Number of data points = " + nd + ""); double[] xy = TestInterp.p00_data(prob, 2, nd); switch (debug) { case true: typeMethods.r8mat_transpose_print(2, nd, xy, " Data array:"); break; } double[] xd = new double[nd]; double[] yd = new double[nd]; for (i = 0; i < nd; i++) { xd[i] = xy[0 + i * 2]; yd[i] = xy[1 + i * 2]; } // // Compute Vandermonde matrix and get condition number. // double[] ad = Vandermonde.vandermonde_matrix_1d(nd, xd); double condition = Matrix.condition_hager(nd, ad); Console.WriteLine(""); Console.WriteLine(" Condition of Vandermonde matrix is " + condition + ""); // // Solve linear system. // double[] cd = QRSolve.qr_solve(nd, nd, ad, yd); // // #1: Does interpolant match function at interpolation points? // int ni = nd; double[] xi = typeMethods.r8vec_copy_new(ni, xd); double[] yi = Vandermonde.vandermonde_value_1d(nd, cd, ni, xi); double int_error = typeMethods.r8vec_norm_affine(ni, yi, yd) / ni; Console.WriteLine(""); Console.WriteLine(" L2 interpolation error averaged per interpolant node = " + int_error + ""); // // #2: Compare estimated curve length to piecewise linear (minimal) curve length. // Assume data is sorted, and normalize X and Y dimensions by (XMAX-XMIN) and // (YMAX-YMIN). // double xmin = typeMethods.r8vec_min(nd, xd); double xmax = typeMethods.r8vec_max(nd, xd); double ymin = typeMethods.r8vec_min(nd, yd); double ymax = typeMethods.r8vec_max(nd, yd); ni = 501; xi = typeMethods.r8vec_linspace_new(ni, xmin, xmax); yi = Vandermonde.vandermonde_value_1d(nd, cd, ni, xi); double ld = 0.0; for (i = 0; i < nd - 1; i++) { ld += Math.Sqrt(Math.Pow((xd[i + 1] - xd[i]) / (xmax - xmin), 2) + Math.Pow((yd[i + 1] - yd[i]) / (ymax - ymin), 2)); } double li = 0.0; for (i = 0; i < ni - 1; i++) { li += Math.Sqrt(Math.Pow((xi[i + 1] - xi[i]) / (xmax - xmin), 2) + Math.Pow((yi[i + 1] - yi[i]) / (ymax - ymin), 2)); } Console.WriteLine(""); Console.WriteLine(" Normalized length of piecewise linear interpolant = " + ld + ""); Console.WriteLine(" Normalized length of polynomial interpolant = " + li + ""); }
public static void emweak(ref typeMethods.r8vecNormalData data, ref int seed, int method, int m, int p_max, ref double[] dtvals, ref double[] xerr) //****************************************************************************80 // // Purpose: // // EMWEAK tests the weak convergence of the Euler-Maruyama method. // // Discussion: // // The SDE is // // dX = lambda * X dt + mu * X dW, // X(0) = Xzero, // // where // // lambda = 2, // mu = 1, // Xzero = 1. // // The discretized Brownian path over [0,1] has dt = 2^(-9). // // The Euler-Maruyama method will use 5 different timesteps: // // 2^(p-10), p = 1,2,3,4,5. // // We examine weak convergence at T=1: // // | E (X_L) - E (X(T)) |. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 25 September 2012 // // Author: // // Original MATLAB version by Desmond Higham. // C++ version by John Burkardt. // // Reference: // // Desmond Higham, // An Algorithmic Introduction to Numerical Simulation of // Stochastic Differential Equations, // SIAM Review, // Volume 43, Number 3, September 2001, pages 525-546 // // Parameters: // // Input, int &SEED, a seed for the random number generator. // // Input, int METHOD. // 0, use the standard Euler-Maruyama method; // 1, use the weak Euler-Maruyama method. // // Input, int M, the number of simulations to perform. // A typical value is M = 1000. // // Input, int P_MAX, the number of time step sizes to use. // A typical value is 5. // // Output, double DTVALS[P_MAX], the time steps used. // // Output, double XERR[P_MAX], the averaged absolute error in the // solution estimate at the final time. // { int i; int p; // // Problem parameters; // const double lambda = 2.0; const double mu = 0.1; const double xzero = 1.0; // // Stepping parameters. // for (p = 0; p < p_max; p++) { dtvals[p] = Math.Pow(2.0, p - 9); } // // Take various Euler timesteps. // For stepsize dt, we will need to take L Euler steps to reach time TMAX. // double[] xtemp = new double[m]; double[] xem = new double[p_max]; for (p = 0; p < p_max; p++) { int l = (int)Math.Pow(2, 9 - p); double dt = dtvals[p]; for (i = 0; i < m; i++) { xtemp[i] = xzero; } int j; for (j = 0; j < l; j++) { double[] winc = typeMethods.r8vec_normal_01_new(m, ref data, ref seed); switch (method) { case 0: { for (i = 0; i < m; i++) { winc[i] = Math.Sqrt(dt) * winc[i]; } break; } default: { for (i = 0; i < m; i++) { winc[i] = Math.Sqrt(dt) * typeMethods.r8_sign(winc[i]); } break; } } for (i = 0; i < m; i++) { xtemp[i] = xtemp[i] + dt * lambda * xtemp[i] + mu * xtemp[i] * winc[i]; } } // // Average the M results for this stepsize. // xem[p] = typeMethods.r8vec_mean(m, xtemp); } // // Compute the error in the estimates for each stepsize. // for (p = 0; p < p_max; p++) { xerr[p] = Math.Abs(xem[p] - Math.Exp(lambda)); } // // Least squares fit of error = c * dt^q. // double[] a = new double[p_max * 2]; double[] rhs = new double[p_max]; for (i = 0; i < p_max; i++) { a[i + 0 * p_max] = 1.0; a[i + 1 * p_max] = Math.Log(dtvals[i]); rhs[i] = Math.Log(xerr[i]); } double[] sol = QRSolve.qr_solve(p_max, 2, a, rhs); Console.WriteLine(""); Console.WriteLine("EMWEAK:"); switch (method) { case 0: Console.WriteLine(" Using standard Euler-Maruyama method."); break; default: Console.WriteLine(" Using weak Euler-Maruyama method."); break; } Console.WriteLine(" Least squares solution to Error = c * dt ^ q"); Console.WriteLine(" (Expecting Q to be about 1.)"); Console.WriteLine(" Computed Q = " + sol[1] + ""); double resid = 0.0; for (i = 0; i < p_max; i++) { double e = a[i + 0 * p_max] * sol[0] + a[i + 1 * p_max] * sol[1] - rhs[i]; resid += e * e; } resid = Math.Sqrt(resid); Console.WriteLine(" Residual is " + resid + ""); }
// Last two ints before fcnData are for the array index baselines. public static int hybrd(Func <int, double[], double[], int, int, int, fcnData> fcn, int n, double[] x, double[] fvec, double xtol, int maxfev, int ml, int mu, double epsfcn, double[] diag, int mode, double factor, int nprint, int nfev, double[] fjac, int ldfjac, double[] r, int lr, double[] qtf, double[] wa1, double[] wa2, double[] wa3, double[] wa4, int fjacIndex, int rIndex, int qtfIndex, int wa1Index, int wa2Index, int wa3Index, int wa4Index) //****************************************************************************80 // // Purpose: // // hybrd() finds a zero of a system of N nonlinear equations. // // Discussion: // // The purpose of HYBRD is to find a zero of a system of // N nonlinear functions in N variables by a modification // of the Powell hybrid method. // // The user must provide FCN, which calculates the functions. // // The jacobian is calculated by a forward-difference approximation. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 08 April 2010 // // Author: // // Original FORTRAN77 version by Jorge More, Burt Garbow, Ken Hillstrom. // C++ version by John Burkardt. // // Reference: // // Jorge More, Burton Garbow, Kenneth Hillstrom, // User Guide for MINPACK-1, // Technical Report ANL-80-74, // Argonne National Laboratory, 1980. // // Parameters: // // fcn is the name of the user-supplied subroutine which // calculates the functions. fcn must be declared // in an external statement in the user calling // program, and should be written as follows. // // subroutine fcn(n,x,fvec,iflag) // integer n,iflag // double precision x(n),fvec(n) // ---------- // calculate the functions at x and // return this vector in fvec. // --------- // return // end // // the value of iflag should not be changed by fcn unless // the user wants to terminate execution of hybrd. // in this case set iflag to a negative integer. // // Input, int N, the number of functions and variables. // // Input/output, double X[N]. On input an initial estimate of the solution. // On output, the final estimate of the solution. // // Output, double FVEC[N], the functions evaluated at the output value of X. // // Input, double XTOL, a nonnegative value. Termination occurs when the // relative error between two consecutive iterates is at most XTOL. // // Input, int MAXFEV. Termination occurs when the number of calls to FCN // is at least MAXFEV by the end of an iteration. // // Input, int ML, specifies the number of subdiagonals within the band of // the jacobian matrix. If the jacobian is not banded, set // ml to at least n - 1. // // mu is a nonnegative integer input variable which specifies // the number of superdiagonals within the band of the // jacobian matrix. if the jacobian is not banded, set // mu to at least n - 1. // // epsfcn is an input variable used in determining a suitable // step length for the forward-difference approximation. this // approximation assumes that the relative errors in the // functions are of the order of epsfcn. if epsfcn is less // than the machine precision, it is assumed that the relative // errors in the functions are of the order of the machine // precision. // // diag is an array of length n. if mode = 1 (see // below), diag is internally set. if mode = 2, diag // must contain positive entries that serve as // multiplicative scale factors for the variables. // // mode is an integer input variable. if mode = 1, the // variables will be scaled internally. if mode = 2, // the scaling is specified by the input diag. other // values of mode are equivalent to mode = 1. // // factor is a positive input variable used in determining the // initial step bound. this bound is set to the product of // factor and the euclidean norm of diag*x if nonzero, or else // to factor itself. in most cases factor should lie in the // interval (.1,100.). 100. is a generally recommended value. // // nprint is an integer input variable that enables controlled // printing of iterates if it is positive. in this case, // fcn is called with iflag = 0 at the beginning of the first // iteration and every nprint iterations thereafter and // immediately prior to return, with x and fvec available // for printing. if nprint is not positive, no special calls // of fcn with iflag = 0 are made. // // info is an integer output variable. if the user has // terminated execution, info is set to the (negative) // value of iflag. see description of fcn. otherwise, // info is set as follows. // // info = 0 improper input parameters. // // info = 1 relative error between two consecutive iterates // is at most xtol. // // info = 2 number of calls to fcn has reached or exceeded // maxfev. // // info = 3 xtol is too small. no further improvement in // the approximate solution x is possible. // // info = 4 iteration is not making good progress, as // measured by the improvement from the last // five jacobian evaluations. // // info = 5 iteration is not making good progress, as // measured by the improvement from the last // ten iterations. // // nfev is an integer output variable set to the number of // calls to fcn. // // fjac is an output n by n array which contains the // orthogonal matrix q produced by the qr factorization // of the final approximate jacobian. // // ldfjac is a positive integer input variable not less than n // which specifies the leading dimension of the array fjac. // // r is an output array of length lr which contains the // upper triangular matrix produced by the qr factorization // of the final approximate jacobian, stored rowwise. // // lr is a positive integer input variable not less than // (n*(n+1))/2. // // qtf is an output array of length n which contains // the vector (q transpose)*fvec. // // wa1, wa2, wa3, and wa4 are work arrays of length n. // { double delta = 0; int[] iwa = new int[1]; int j; const double p001 = 0.001; const double p0001 = 0.0001; const double p1 = 0.1; const double p5 = 0.5; double xnorm = 0; // // Certain loops in this function were kept closer to their original FORTRAN77 // format, to avoid confusing issues with the array index L. These loops are // marked "DO NOT ADJUST", although they certainly could be adjusted (carefully) // once the initial translated code is tested. // // // EPSMCH is the machine precision. // double epsmch = typeMethods.r8_epsilon(); int info = 0; int iflag = 0; nfev = 0; switch (n) { // // Check the input parameters. // case <= 0: info = 0; return(info); } switch (xtol) { case < 0.0: info = 0; return(info); } switch (maxfev) { case <= 0: info = 0; return(info); } switch (ml) { case < 0: info = 0; return(info); } switch (mu) { case < 0: info = 0; return(info); } switch (factor) { case <= 0.0: info = 0; return(info); } if (ldfjac < n) { info = 0; return(info); } if (lr < n * (n + 1) / 2) { info = 0; return(info); } switch (mode) { case 2: { for (j = 0; j < n; j++) { switch (diag[j]) { case <= 0.0: info = 0; return(info); } } break; } } // // Evaluate the function at the starting point and calculate its norm. // iflag = 1; fcnData res = fcn(n, x, fvec, iflag, 0, 0); fvec = res.fvec; iflag = res.iflag; nfev = 1; switch (iflag) { case < 0: info = iflag; return(info); } double fnorm = Helpers.enorm(n, fvec); // // Determine the number of calls to FCN needed to compute the jacobian matrix. // int msum = Math.Min(ml + mu + 1, n); // // Initialize iteration counter and monitors. // int iter = 1; int ncsuc = 0; int ncfail = 0; int nslow1 = 0; int nslow2 = 0; // // Beginning of the outer loop. // for (;;) { bool jeval = true; // // Calculate the jacobian matrix. // iflag = 2; fdjac1(fcn, n, x, fvec, fjac, ldfjac, ref iflag, ml, mu, epsfcn, wa1, wa2, fjacIndex: fjacIndex, wa1Index: wa1Index, wa2Index: wa2Index); nfev += msum; switch (iflag) { case < 0: info = iflag; return(info); } // // Compute the QR factorization of the jacobian. // int tmpi = 1; QRSolve.qrfac(n, n, ref fjac, ldfjac, false, ref iwa, ref tmpi, ref wa1, ref wa2, rdiagIndex: wa1Index, acnormIndex: wa2Index); switch (iter) { // // On the first iteration and if MODE is 1, scale according // to the norms of the columns of the initial jacobian. // case 1: { switch (mode) { case 1: { for (j = 0; j < n; j++) { if (wa2[wa2Index + j] != 0.0) { diag[j] = wa2[wa2Index + j]; } else { diag[j] = 1.0; } } break; } } // // On the first iteration, calculate the norm of the scaled X // and initialize the step bound DELTA. // for (j = 0; j < n; j++) { wa3[wa3Index + j] = diag[j] * x[j]; } xnorm = Helpers.enorm(n, wa3); delta = xnorm switch { 0.0 => factor, _ => factor * xnorm }; break; } } // // Form Q' * FVEC and store in QTF. // int i; for (i = 0; i < n; i++) { qtf[qtfIndex + i] = fvec[i]; } double temp; double sum; for (j = 0; j < n; j++) { if (fjac[fjacIndex + j + j * ldfjac] == 0.0) { continue; } sum = 0.0; for (i = j; i < n; i++) { sum += fjac[fjacIndex + i + j * ldfjac] * qtf[qtfIndex + i]; } temp = -sum / fjac[fjacIndex + j + j * ldfjac]; for (i = j; i < n; i++) { qtf[qtfIndex + i] += fjac[fjacIndex + i + j * ldfjac] * temp; } } // // Copy the triangular factor of the QR factorization into R. // // DO NOT ADJUST THIS LOOP, BECAUSE OF L. // int l; for (j = 1; j <= n; j++) { l = j; for (i = 1; i <= j - 1; i++) { r[rIndex + (l - 1)] = fjac[fjacIndex + (i - 1) + (j - 1) * ldfjac]; l = l + n - i; } r[rIndex + (l - 1)] = wa1[wa1Index + (j - 1)]; switch (wa1[wa1Index + (j - 1)]) { case 0.0: Console.WriteLine(" Matrix is singular."); break; } } // // Accumulate the orthogonal factor in FJAC. // QRSolve.qform(n, n, ref fjac, ldfjac, qIndex: fjacIndex); switch (mode) { // // Rescale if necessary. // case 1: { for (j = 0; j < n; j++) { diag[j] = Math.Max(diag[j], wa2[wa2Index + j]); } break; } } // // Beginning of the inner loop. // for (;;) { switch (nprint) { // // If requested, call FCN to enable printing of iterates. // case > 0: { switch ((iter - 1) % nprint) { case 0: { iflag = 0; fcn(n, x, fvec, iflag, 0, 0); switch (iflag) { case < 0: info = iflag; return(info); } break; } } break; } } // // Determine the direction P. // dogleg(n, r, lr, diag, qtf, delta, ref wa1, wa2, wa3, rIndex: rIndex, qtbIndex: qtfIndex, xIndex: wa1Index, wa1Index: wa2Index, wa2Index: wa3Index); // // Store the direction P and X + P. Calculate the norm of P. // for (j = 0; j < n; j++) { wa1[wa1Index + j] = -wa1[j]; wa2[wa2Index + j] = x[j] + wa1[j]; wa3[wa3Index + j] = diag[j] * wa1[wa1Index + j]; } double pnorm = Helpers.enorm(n, wa3); delta = iter switch { // // On the first iteration, adjust the initial step bound. // 1 => Math.Min(delta, pnorm), _ => delta }; // // Evaluate the function at X + P and calculate its norm. // iflag = 1; fcn(n, wa2, wa4, iflag, wa2Index, wa4Index); nfev += 1; switch (iflag) { case < 0: info = iflag; return(info); } double fnorm1 = Helpers.enorm(n, wa4); // // Compute the scaled actual reduction. // double actred; if (fnorm1 < fnorm) { actred = 1.0 - fnorm1 / fnorm * (fnorm1 / fnorm); } else { actred = -1.0; } // // Compute the scaled predicted reduction. // // DO NOT ADJUST THIS LOOP, BECAUSE OF L. // l = 1; for (i = 1; i <= n; i++) { sum = 0.0; for (j = i; j <= n; j++) { sum += r[rIndex + (l - 1)] * wa1[wa1Index + (j - 1)]; l += 1; } wa3[i - 1] = qtf[i - 1] + sum; } temp = Helpers.enorm(n, wa3); double prered; if (temp < fnorm) { prered = 1.0 - temp / fnorm * (temp / fnorm); } else { prered = 0.0; } double ratio = prered switch { // // Compute the ratio of the actual to the predicted reduction. // > 0.0 => actred / prered, _ => 0.0 }; switch (ratio) { // // Update the step bound. // case < p1: ncsuc = 0; ncfail += 1; delta = p5 * delta; break; default: { ncfail = 0; ncsuc += 1; if (p5 <= ratio || 1 < ncsuc) { delta = Math.Max(delta, pnorm / p5); } delta = Math.Abs(ratio - 1.0) switch { <= p1 => pnorm / p5, _ => delta }; break; } }
public static double[] vandermonde_approx_1d_coef(int n, int m, double[] x, double[] y) //****************************************************************************80 // // Purpose: // // VANDERMONDE_APPROX_1D_COEF computes a 1D polynomial approximant. // // Discussion: // // We assume the approximating function has the form // // p(x) = c0 + c1 * x + c2 * x^2 + ... + cm * x^m. // // We have n data values (x(i),y(i)) which must be approximated: // // p(x(i)) = c0 + c1 * x(i) + c2 * x(i)^2 + ... + cm * x(i)^m = y(i) // // This can be cast as an Nx(M+1) linear system for the polynomial // coefficients: // // [ 1 x1 x1^2 ... x1^m ] [ c0 ] = [ y1 ] // [ 1 x2 x2^2 ... x2^m ] [ c1 ] = [ y2 ] // [ .................. ] [ ... ] = [ ... ] // [ 1 xn xn^2 ... xn^m ] [ cm ] = [ yn ] // // In the typical case, N is greater than M+1 (we have more data and equations // than degrees of freedom) and so a least squares solution is appropriate, // in which case the computed polynomial will be a least squares approximant // to the data. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of data points. // // Input, int M, the degree of the polynomial. // // Input, double X[N], Y[N], the data values. // // Output, double VANDERMONDE_APPROX_1D_COEF[M+1], the coefficients of // the approximating polynomial. C(0) is the constant term, and C(M) // multiplies X^M. // { double[] a = VandermondeMatrix.vandermonde_approx_1d_matrix(n, m, x); double[] c = QRSolve.qr_solve(n, m + 1, a, y); return(c); }
public static double[] vandermonde_approx_2d_coef(int n, int m, double[] x, double[] y, double[] z) //****************************************************************************80 // // Purpose: // // VANDERMONDE_APPROX_2D_COEF computes a 2D polynomial approximant. // // Discussion: // // We assume the approximating function has the form of a polynomial // in X and Y of total degree M. // // p(x,y) = c00 // + c10 * x + c01 * y // + c20 * x^2 + c11 * xy + c02 * y^2 // + ... // + cm0 * x^(m) + ... + c0m * y^m. // // If we let T(K) = the K-th triangular number // = sum ( 1 <= I <= K ) I // then the number of coefficients in the above polynomial is T(M+1). // // We have n data locations (x(i),y(i)) and values z(i) to approximate: // // p(x(i),y(i)) = z(i) // // This can be cast as an NxT(M+1) linear system for the polynomial // coefficients: // // [ 1 x1 y1 x1^2 ... y1^m ] [ c00 ] = [ z1 ] // [ 1 x2 y2 x2^2 ... y2^m ] [ c10 ] = [ z2 ] // [ 1 x3 y3 x3^2 ... y3^m ] [ c01 ] = [ z3 ] // [ ...................... ] [ ... ] = [ ... ] // [ 1 xn yn xn^2 ... yn^m ] [ c0m ] = [ zn ] // // In the typical case, N is greater than T(M+1) (we have more data and // equations than degrees of freedom) and so a least squares solution is // appropriate, in which case the computed polynomial will be a least squares // approximant to the data. // // The polynomial defined by the T(M+1) coefficients C could be evaluated // at the Nx2-vector x by the command // // pval = r8poly_value_2d ( m, c, n, x ) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 12 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the number of data points. // // Input, int M, the maximum degree of the polynomial. // // Input, double X[N], Y[N] the data locations. // // Input, double Z[N], the data values. // // Output, double VANDERMONDE_APPROX_2D_COEF[T(M+1)], the // coefficients of the approximating polynomial. // { int tm = typeMethods.triangle_num(m + 1); double[] a = VandermondeMatrix.vandermonde_approx_2d_matrix(n, m, tm, x, y); double[] c = QRSolve.qr_solve(n, tm, a, z); return(c); }
public static double[] chebyshev_coef_1d(int nd, double[] xd, double[] yd, ref double xmin, ref double xmax) //****************************************************************************80 // // Purpose: // // CHEBYSHEV_COEF_1D determines the Chebyshev interpolant coefficients. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 September 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int ND, the number of data points. // ND must be at least 1. // // Input, double XD[ND], the data locations. // // Input, double YD[ND], the data values. // // Output, double &XMIN, &XMAX, the interpolation interval. // // Output, double CHEBYSHEV_COEF_1D[ND], the Chebyshev coefficients. // { double[] c; int i; int j; switch (nd) { case 1: xmin = xd[0]; xmax = xd[0]; c = new double[nd]; c[0] = 1.0; return(c); } xmin = typeMethods.r8vec_min(nd, xd); xmax = typeMethods.r8vec_max(nd, xd); // // Map XD to [-1,+1]. // double[] x = new double[nd]; for (i = 0; i < nd; i++) { x[i] = (2.0 * xd[i] - xmin - xmax) / (xmax - xmin); } // // Form the Chebyshev Vandermonde matrix. // double[] a = new double[nd * nd]; for (j = 0; j < nd; j++) { for (i = 0; i < nd; i++) { a[i + j * nd] = Math.Cos(Math.Acos(x[i]) * j); } } // // Solve for the expansion coefficients. // c = QRSolve.qr_solve(nd, nd, a, yd); return(c); }
private static void test01(int prob, int m) //****************************************************************************80 // // Purpose: // // TEST01 tests VANDERMONDE_APPROX_1D_MATRIX. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 10 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int PROB, the problem number. // // Input, int M, the polynomial degree. // { const bool debug = false; int i; Console.WriteLine(""); Console.WriteLine("TEST01:"); Console.WriteLine(" Approximate data from TEST_INTERP problem #" + prob + ""); int nd = TestInterp.p00_data_num(prob); Console.WriteLine(" Number of data points = " + nd + ""); double[] xy = TestInterp.p00_data(prob, 2, nd); switch (debug) { case true: typeMethods.r8mat_transpose_print(2, nd, xy, " Data array:"); break; } double[] xd = new double[nd]; double[] yd = new double[nd]; for (i = 0; i < nd; i++) { xd[i] = xy[0 + i * 2]; yd[i] = xy[1 + i * 2]; } // // Compute the Vandermonde matrix. // Console.WriteLine(" Using polynomial approximant of degree " + m + ""); double[] a = VandermondeMatrix.vandermonde_approx_1d_matrix(nd, m, xd); // // Solve linear system. // double[] c = QRSolve.qr_solve(nd, m + 1, a, yd); // // #1: Does approximant match function at data points? // int ni = nd; double[] xi = typeMethods.r8vec_copy_new(ni, xd); double[] yi = Polynomial.r8poly_values(m, c, ni, xi); double app_error = typeMethods.r8vec_norm_affine(ni, yi, yd) / ni; Console.WriteLine(""); Console.WriteLine(" L2 data approximation error = " + app_error + ""); // // #2: Compare estimated curve length to piecewise linear (minimal) curve length. // Assume data is sorted, and normalize X and Y dimensions by (XMAX-XMIN) and // (YMAX-YMIN). // double xmin = typeMethods.r8vec_min(nd, xd); double xmax = typeMethods.r8vec_max(nd, xd); double ymin = typeMethods.r8vec_min(nd, yd); double ymax = typeMethods.r8vec_max(nd, yd); ni = 501; xi = typeMethods.r8vec_linspace_new(ni, xmin, xmax); yi = Polynomial.r8poly_values(m, c, ni, xi); double ld = 0.0; for (i = 0; i < nd - 1; i++) { ld += Math.Sqrt(Math.Pow((xd[i + 1] - xd[i]) / (xmax - xmin), 2) + Math.Pow((yd[i + 1] - yd[i]) / (ymax - ymin), 2)); } double li = 0.0; for (i = 0; i < ni - 1; i++) { li += Math.Sqrt(Math.Pow((xi[i + 1] - xi[i]) / (xmax - xmin), 2) + Math.Pow((yi[i + 1] - yi[i]) / (ymax - ymin), 2)); } Console.WriteLine(""); Console.WriteLine(" Normalized length of piecewise linear interpolant = " + ld + ""); Console.WriteLine(" Normalized length of polynomial interpolant = " + li + ""); }
public static void milstrong(ref typeMethods.r8vecNormalData data, ref int seed, int p_max, ref double[] dtvals, ref double[] xerr) //****************************************************************************80 // // Purpose: // // MILSTRONG tests the strong convergence of the Milstein method. // // Discussion: // // This function solves the stochastic differential equation // // dX = sigma * X * ( k - X ) dt + beta * X dW, // X(0) = Xzero, // // where // // sigma = 2, // k = 1, // beta = 1, // Xzero = 0.5. // // The discretized Brownian path over [0,1] has dt = 2^(-11). // // The Milstein method uses timesteps 128*dt, 64*dt, 32*dt, 16*dt // (also dt for reference). // // We examine strong convergence at T=1: // // E | X_L - X(T) |. // // The code is vectorized: all paths computed simultaneously. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 September 2012 // // Author: // // Original MATLAB version by Desmond Higham. // C++ version by John Burkardt. // // Reference: // // Desmond Higham, // An Algorithmic Introduction to Numerical Simulation of // Stochastic Differential Equations, // SIAM Review, // Volume 43, Number 3, September 2001, pages 525-546. // // Parameters: // // Input/output, int &SEED, a seed for the random // number generator. // // Input, int P_MAX, the number of time step sizes to use. // A typical value is 4. // // Output, double DTVALS[P_MAX], the time steps used. // // Output, double XERR[P_MAX], the averaged absolute error in the // solution estimate at the final time. // { int i; int j; int p; // // Set problem parameters. // const double sigma = 2.0; const double k = 1.0; const double beta = 0.25; const double xzero = 0.5; // // Set stepping parameters. // const double tmax = 1.0; int n = (int)Math.Pow(2, 11); double dt = tmax / n; // // Number of paths sampled. // const int m = 500; // // Define the increments dW. // double[] dw = typeMethods.r8mat_normal_01_new(m, n, ref data, ref seed); for (j = 0; j < n; j++) { for (i = 0; i < m; i++) { dw[i + j * m] = Math.Sqrt(dt) * dw[i + j * m]; } } // // Estimate the reference solution at time T M times. // double[] xref = new double[m]; for (i = 0; i < m; i++) { xref[i] = xzero; } for (j = 0; j < n; j++) { for (i = 0; i < m; i++) { xref[i] = xref[i] + dt * sigma * xref[i] * (k - xref[i]) + beta * xref[i] * dw[i + j * m] + 0.5 * beta * beta * xref[i] * (dw[i + j * m] * dw[i + j * m] - dt); } } // // Now compute M Milstein approximations at each of 4 timesteps, // and record the average errors. // for (p = 0; p < p_max; p++) { dtvals[p] = dt * 8.0 * Math.Pow(2.0, p + 1); } for (p = 0; p < p_max; p++) { xerr[p] = 0.0; } double[] xtemp = new double[m]; for (p = 0; p < p_max; p++) { int r = 8 * (int)Math.Pow(2, p + 1); double dtp = dtvals[p]; int l = n / r; for (i = 0; i < m; i++) { xtemp[i] = xzero; } for (j = 0; j < l; j++) { for (i = 0; i < m; i++) { double winc = 0.0; int i2; for (i2 = r * j; i2 < r * (j + 1); i2++) { winc += dw[i + i2 * m]; } xtemp[i] = xtemp[i] + dtp * sigma * xtemp[i] * (k - xtemp[i]) + beta * xtemp[i] * winc + 0.5 * beta * beta * xtemp[i] * (winc * winc - dtp); } } xerr[p] = 0.0; for (i = 0; i < m; i++) { xerr[p] += Math.Abs(xtemp[i] - xref[i]); } xerr[p] /= m; } // // Least squares fit of error = C * dt^q // double[] a = new double[p_max * 2]; double[] rhs = new double[p_max]; for (p = 0; p < p_max; p++) { a[p + 0 * p_max] = 1.0; a[p + 1 * p_max] = Math.Log(dtvals[p]); rhs[p] = Math.Log(xerr[p]); } double[] sol = QRSolve.qr_solve(p_max, 2, a, rhs); Console.WriteLine(""); Console.WriteLine("MILSTEIN:"); Console.WriteLine(" Least squares solution to Error = c * dt ^ q"); Console.WriteLine(" Expecting Q to be about 1."); Console.WriteLine(" Computed Q = " + sol[1] + ""); double resid = 0.0; for (i = 0; i < p_max; i++) { double e = a[i + 0 * p_max] * sol[0] + a[i + 1 * p_max] * sol[1] - rhs[i]; resid += e * e; } resid = Math.Sqrt(resid); Console.WriteLine(" Residual is " + resid + ""); }
private static void qform_test() //****************************************************************************80 // // Purpose: // // QFORM_TEST tests QFORM. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 January 2018 // // Author: // // John Burkardt // { int i; int j; int k; const int lda = 5; const int m = 5; const int n = 7; Console.WriteLine(""); Console.WriteLine("QFORM_TEST:"); Console.WriteLine(" QFORM constructs the Q factor explicitly"); Console.WriteLine(" after the use of QRFAC."); // // Set the matrix A. // double[] a = new double[m * n]; int seed = 123456789; for (j = 0; j < n; j++) { for (i = 0; i < m; i++) { a[i + j * m] = UniformRNG.r8_uniform_01(ref seed); } } typeMethods.r8mat_print(m, n, a, " Matrix A:"); // // Compute the QR factors. // const bool pivot = false; int[] ipivot = new int[n]; int lipvt = n; double[] rdiag = new double[n]; double[] acnorm = new double[n]; QRSolve.qrfac(m, n, ref a, lda, pivot, ref ipivot, ref lipvt, ref rdiag, ref acnorm); // // Extract the R factor. // double[] r = new double[m * n]; for (j = 0; j < n; j++) { for (i = 0; i < m; i++) { r[i + j * m] = 0.0; } } for (k = 0; k < Math.Min(m, n); k++) { r[k + k * m] = rdiag[k]; } for (j = 0; j < n; j++) { for (i = 0; i < Math.Min(j, m); i++) { r[i + j * m] = a[i + j * m]; } } typeMethods.r8mat_print(m, n, r, " Matrix R:"); // // Call QRFORM to form the Q factor. // double[] q = new double[m * m]; for (j = 0; j < m; j++) { for (i = 0; i < m; i++) { q[i + j * m] = 0.0; } } for (j = 0; j < Math.Min(m, n); j++) { for (i = 0; i < m; i++) { q[i + j * m] = a[i + j * m]; } } QRSolve.qform(m, n, ref q, m); typeMethods.r8mat_print(m, m, q, " Matrix Q:"); // // Compute Q*R. // double[] a2 = typeMethods.r8mat_mm_new(m, m, n, q, r); // // Compare Q*R to A. // typeMethods.r8mat_print(m, n, a2, " Matrix A2 = Q * R:"); }
public static void line_fekete_chebyshev(int m, double a, double b, int n, double[] x, ref int nf, ref double[] xf, ref double[] wf) //****************************************************************************80 // // Purpose: // // LINE_FEKETE_CHEBYSHEV: approximate Fekete points in an interval [A,B]. // // Discussion: // // We use the Chebyshev basis. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 April 2014 // // Author: // // John Burkardt // // Reference: // // Len Bos, Norm Levenberg, // On the calculation of approximate Fekete points: the univariate case, // Electronic Transactions on Numerical Analysis, // Volume 30, pages 377-397, 2008. // // Parameters: // // Input, int M, the number of basis polynomials. // // Input, double A, B, the endpoints of the interval. // // Input, int N, the number of sample points. // M <= N. // // Input, double X(N), the coordinates of the sample points. // // Output, int &NF, the number of Fekete points. // If the computation is successful, NF = M. // // Output, double XF(NF), the coordinates of the Fekete points. // // Output, double WF(NF), the weights of the Fekete points. // { int i; int j; if (n < m) { Console.WriteLine(""); Console.WriteLine("LINE_FEKETE_CHEBYSHEV - Fatal error!"); Console.WriteLine(" N < M."); return; } // // Compute the Chebyshev-Vandermonde matrix. // double[] v = VandermondeMatrix.cheby_van1(m, a, b, n, x); // // MOM(I) = Integral ( A <= x <= B ) Tab(A,B,I;x) dx // double[] mom = new double[m]; mom[0] = Math.PI * (b - a) / 2.0; for (i = 1; i < m; i++) { mom[i] = 0.0; } // // Solve the system for the weights W. // double[] w = QRSolve.qr_solve(m, n, v, mom); // // Extract the data associated with the nonzero weights. // nf = 0; for (j = 0; j < n; j++) { if (w[j] == 0.0) { continue; } if (nf >= m) { continue; } xf[nf] = x[j]; wf[nf] = w[j]; nf += 1; } }
public static void line_fekete_monomial(int m, double a, double b, int n, double[] x, ref int nf, ref double[] xf, ref double[] wf) //****************************************************************************80 // // Purpose: // // LINE_FEKETE_MONOMIAL: approximate Fekete points in an interval [A,B]. // // Discussion: // // We use the uniform weight and the monomial basis: // // P(j) = x^(j-1) // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 13 April 2014 // // Author: // // John Burkardt // // Reference: // // Alvise Sommariva, Marco Vianello, // Computing approximate Fekete points by QR factorizations of Vandermonde // matrices, // Computers and Mathematics with Applications, // Volume 57, 2009, pages 1324-1336. // // Parameters: // // Input, int M, the number of basis polynomials. // // Input, double A, B, the endpoints of the interval. // // Input, int N, the number of sample points. // M <= N. // // Input, double X(N), the coordinates of the sample points. // // Output, int &NF, the number of Fekete points. // If the computation is successful, NF = M. // // Output, double XF(NF), the coordinates of the Fekete points. // // Output, double WF(NF), the weights of the Fekete points. // { int j; if (n < m) { Console.WriteLine(""); Console.WriteLine("LINE_FEKETE_MONOMIAL - Fatal error!"); Console.WriteLine(" N < M."); return; } // // Form the moments. // double[] mom = Monomial.line_monomial_moments(a, b, m); // // Form the rectangular Vandermonde matrix V for the polynomial basis. // double[] v = new double[m * n]; for (j = 0; j < n; j++) { v[0 + j * m] = 1.0; int i; for (i = 1; i < m; i++) { v[i + j * m] = v[i - 1 + j * m] * x[j]; } } // // Solve the system for the weights W. // double[] w = QRSolve.qr_solve(m, n, v, mom); // // Extract the data associated with the nonzero weights. // nf = 0; for (j = 0; j < n; j++) { if (w[j] == 0.0) { continue; } if (nf >= m) { continue; } xf[nf] = x[j]; wf[nf] = w[j]; nf += 1; } }
public static double[] lagrange_approx_1d(int m, int nd, double[] xd, double[] yd, int ni, double[] xi) //****************************************************************************80 // // Purpose: // // LAGRANGE_APPROX_1D evaluates the Lagrange approximant of degree M. // // Discussion: // // The Lagrange approximant L(M,ND,XD,YD)(X) is a polynomial of // degree M which approximates the data (XD(I),YD(I)) for I = 1 to ND. // // We can represent any polynomial of degree M+1 as the sum of the Lagrange // basis functions at the M+1 Chebyshev points. // // L(M)(X) = sum ( 1 <= I <= M+1 ) C(I) LB(M,XC)(X) // // Given our data, we can seek the M+1 unknown coefficients C which minimize // the norm of || L(M)(XD(1:ND)) - YD(1:ND) ||. // // Given the coefficients, we can then evaluate the polynomial at the // points XI. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 09 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int M, the polynomial degree. // // Input, int ND, the number of data points. // ND must be at least 1. // // Input, double XD[ND], the data points. // // Input, double YD[ND], the data values. // // Input, int NI, the number of interpolation points. // // Input, double XI[NI], the interpolation points. // // Output, double LAGRANGE_APPROX_1D[NI], the interpolated values. // { int nc = m + 1; // // Evaluate the Chebyshev points. // const double a = -1.0; const double b = +1.0; double[] xc = typeMethods.r8vec_cheby_extreme_new(nc, a, b); // // Evaluate the Lagrange basis functions for the Chebyshev points // at the data points. // double[] ld = lagrange_basis_1d(nc, xc, nd, xd); // // The value of the Lagrange approximant at each data point should // approximate the data value: LD * YC = YD, where YC are the unknown // coefficients. // double[] yc = QRSolve.qr_solve(nd, nc, ld, yd); // // Now we want to evaluate the Lagrange approximant at the "interpolant // points": LI * YC = YI // double[] li = lagrange_basis_1d(nc, xc, ni, xi); double[] yi = typeMethods.r8mat_mv_new(ni, nc, li, yc); return(yi); }
private static void test02(int prob) //****************************************************************************80 // // Purpose: // // TEST02 tests VANDERMONDE_INTERP_1D_MATRIX. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 02 June 2013 // // Author: // // John Burkardt // // Parameters: // // Input, int PROB, the problem index. // { List <string> command_unit = new(); List <string> data_unit = new(); int i; List <string> interp_unit = new(); int j; Console.WriteLine(""); Console.WriteLine("TEST02:"); Console.WriteLine(" VANDERMONDE_INTERP_1D_MATRIX sets the Vandermonde linear system"); Console.WriteLine(" for the interpolating polynomial."); Console.WriteLine(" Interpolate data from TEST_INTERP problem #" + prob + ""); int nd = TestInterp.p00_data_num(prob); Console.WriteLine(" Number of data points = " + nd + ""); double[] xy = TestInterp.p00_data(prob, 2, nd); typeMethods.r8mat_transpose_print(2, nd, xy, " Data array:"); double[] xd = new double[nd]; double[] yd = new double[nd]; for (i = 0; i < nd; i++) { xd[i] = xy[0 + 2 * i]; yd[i] = xy[1 + 2 * i]; } // // Compute Vandermonde matrix and get condition number. // double[] ad = Vandermonde.vandermonde_matrix_1d(nd, xd); // // Solve linear system. // double[] cd = QRSolve.qr_solve(nd, nd, ad, yd); // // Create data file. // string data_filename = "data" + prob + ".txt"; for (j = 0; j < nd; j++) { data_unit.Add(" " + xd[j] + " " + yd[j] + ""); } File.WriteAllLines(data_filename, data_unit); Console.WriteLine(""); Console.WriteLine(" Created graphics data file \"" + data_filename + "\"."); // // Create interp file. // int ni = 501; double xmin = typeMethods.r8vec_min(nd, xd); double xmax = typeMethods.r8vec_max(nd, xd); double[] xi = typeMethods.r8vec_linspace_new(ni, xmin, xmax); double[] yi = Vandermonde.vandermonde_value_1d(nd, cd, ni, xi); string interp_filename = "interp" + prob + ".txt"; for (j = 0; j < ni; j++) { interp_unit.Add(" " + xi[j] + " " + yi[j] + ""); } File.WriteAllLines(interp_filename, interp_unit); Console.WriteLine(" Created graphics interp file \"" + interp_filename + "\"."); // // Plot the data and the interpolant. // string command_filename = "commands" + prob + ".txt"; string output_filename = "plot" + prob + ".png"; command_unit.Add("# " + command_filename + ""); command_unit.Add("#"); command_unit.Add("# Usage:"); command_unit.Add("# gnuplot < " + command_filename + ""); command_unit.Add("#"); command_unit.Add("set term png"); command_unit.Add("set output '" + output_filename + "'"); command_unit.Add("set xlabel '<---X--->'"); command_unit.Add("set ylabel '<---Y--->'"); command_unit.Add("set title 'Data versus Vandermonde polynomial interpolant'"); command_unit.Add("set grid"); command_unit.Add("set style data lines"); command_unit.Add("plot '" + data_filename + "' using 1:2 with points pt 7 ps 2 lc rgb 'blue',\\"); command_unit.Add(" '" + interp_filename + "' using 1:2 lw 3 linecolor rgb 'red'"); File.WriteAllLines(command_filename, command_unit); Console.WriteLine(" Created graphics command file \"" + command_filename + "\"."); }
private static void qr_solve_test() //****************************************************************************80 // // Purpose: // // QR_SOLVE_TEST tests QR_SOLVE. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 April 2012 // // Author: // // John Burkardt // { int prob; Console.WriteLine(""); Console.WriteLine("QR_SOLVE_TEST"); Console.WriteLine(" QR_SOLVE is a function with a simple interface which"); Console.WriteLine(" solves a linear system A*x = b in the least squares sense."); Console.WriteLine(" Compare a tabulated solution X1 to the QR_SOLVE result X2."); int prob_num = ProbabilityFunctions.p00_prob_num(); Console.WriteLine(""); Console.WriteLine(" Number of problems = " + prob_num + ""); Console.WriteLine(""); Console.WriteLine(" Index M N ||B|| ||X1 - X2|| ||X1|| ||X2|| ||R1|| ||R2||"); Console.WriteLine(""); for (prob = 1; prob <= prob_num; prob++) { // // Get problem size. // int m = ProbabilityFunctions.p00_m(prob); int n = ProbabilityFunctions.p00_n(prob); // // Retrieve problem data. // double[] a = ProbabilityFunctions.p00_a(prob, m, n); double[] b = ProbabilityFunctions.p00_b(prob, m); double[] x1 = ProbabilityFunctions.p00_x(prob, n); double b_norm = typeMethods.r8vec_norm(m, b); double x1_norm = typeMethods.r8vec_norm(n, x1); double[] r1 = typeMethods.r8mat_mv_new(m, n, a, x1); int i; for (i = 0; i < m; i++) { r1[i] -= b[i]; } double r1_norm = typeMethods.r8vec_norm(m, r1); // // Use QR_SOLVE on the problem. // double[] x2 = QRSolve.qr_solve(m, n, a, b); double x2_norm = typeMethods.r8vec_norm(n, x2); double[] r2 = typeMethods.r8mat_mv_new(m, n, a, x2); for (i = 0; i < m; i++) { r2[i] -= b[i]; } double r2_norm = typeMethods.r8vec_norm(m, r2); // // Compare tabulated and computed solutions. // double x_diff_norm = typeMethods.r8vec_norm_affine(n, x1, x2); // // Report results for this problem. // Console.WriteLine(" " + prob.ToString(CultureInfo.InvariantCulture).PadLeft(5) + " " + m.ToString(CultureInfo.InvariantCulture).PadLeft(4) + " " + n.ToString(CultureInfo.InvariantCulture).PadLeft(4) + " " + b_norm.ToString(CultureInfo.InvariantCulture).PadLeft(12) + " " + x_diff_norm.ToString(CultureInfo.InvariantCulture).PadLeft(12) + " " + x1_norm.ToString(CultureInfo.InvariantCulture).PadLeft(12) + " " + x2_norm.ToString(CultureInfo.InvariantCulture).PadLeft(12) + " " + r1_norm.ToString(CultureInfo.InvariantCulture).PadLeft(12) + " " + r2_norm.ToString(CultureInfo.InvariantCulture).PadLeft(12) + ""); } }
public static void emstrong(ref typeMethods.r8vecNormalData data, ref int seed, int m, int n, int p_max, ref double[] dtvals, ref double[] xerr) //****************************************************************************80 // // Purpose: // // EMSTRONG tests the strong convergence of the EM method. // // Discussion: // // The SDE is // // dX = lambda * X dt + mu * X dW, // X(0) = Xzero, // // where // // lambda = 2, // mu = 1, // Xzero = 1. // // The discretized Brownian path over [0,1] has dt = 2^(-9). // // The Euler-Maruyama method uses 5 different timesteps: // 16*dt, 8*dt, 4*dt, 2*dt, dt. // // We are interested in examining strong convergence at T=1, // that is // // E | X_L - X(T) |. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 28 September 2012 // // Author: // // Original Matlab version by Desmond Higham. // C++ version by John Burkardt. // // Reference: // // Desmond Higham, // An Algorithmic Introduction to Numerical Simulation of // Stochastic Differential Equations, // SIAM Review, // Volume 43, Number 3, September 2001, pages 525-546. // // Parameters: // // Input/output, int &SEED, a seed for the random // number generator. // // Input, int M, the number of simulations to perform. // A typical value is M = 1000. // // Input, int N, the number of time steps to take. // A typical value is N = 512. // // Input, int P_MAX, the number of time step sizes to use. // A typical value is 5. // // Output, double DTVALS[P_MAX], the time steps used. // // Output, double XERR[P_MAX], the averaged absolute error in the // solution estimate at the final time. // { int i; int p; int s; // // Set problem parameters. // const double lambda = 2.0; const double mu = 1.0; const double xzero = 1.0; // // Set stepping parameters. // const double tmax = 1.0; double dt = tmax / n; for (p = 0; p < p_max; p++) { dtvals[p] = dt * Math.Pow(2.0, p); } // // Sample over discrete Brownian paths. // for (p = 0; p < p_max; p++) { xerr[p] = 0.0; } for (s = 0; s < m; s++) { // // Define the increments dW. // double[] dw = typeMethods.r8vec_normal_01_new(n, ref data, ref seed); int j; for (j = 0; j < n; j++) { dw[j] = Math.Sqrt(dt) * dw[j]; } // // Sum the increments to get the Brownian path. // double[] w = new double[n + 1]; w[0] = 0.0; for (j = 1; j <= n; j++) { w[j] = w[j - 1] + dw[j - 1]; } // // Determine the true solution. // double xtrue = xzero * Math.Exp(lambda - 0.5 * mu * mu + mu * w[n]); // // Use the Euler-Maruyama method with 5 different time steps dt2 = r * dt // to estimate the solution value at time TMAX. // for (p = 0; p < p_max; p++) { double dt2 = dtvals[p]; int r = (int)Math.Pow(2, p); int l = n / r; double xtemp = xzero; for (j = 0; j < l; j++) { double winc = 0.0; int k; for (k = r * j; k < r * (j + 1); k++) { winc += dw[k]; } xtemp = xtemp + dt2 * lambda * xtemp + mu * xtemp * winc; } xerr[p] += Math.Abs(xtemp - xtrue); } } for (p = 0; p < p_max; p++) { xerr[p] /= m; } // // Least squares fit of error = c * dt^q. // double[] a = new double[p_max * 2]; double[] rhs = new double[p_max]; for (i = 0; i < p_max; i++) { a[i + 0 * p_max] = 1.0; a[i + 1 * p_max] = Math.Log(dtvals[i]); rhs[i] = Math.Log(xerr[i]); } double[] sol = QRSolve.qr_solve(p_max, 2, a, rhs); Console.WriteLine(""); Console.WriteLine("EMSTRONG:"); Console.WriteLine(" Least squares solution to Error = c * dt ^ q"); Console.WriteLine(" (Expecting Q to be about 1/2.)"); Console.WriteLine(" Computed Q = " + sol[1] + ""); double resid = 0.0; for (i = 0; i < p_max; i++) { double e = a[i + 0 * p_max] * sol[0] + a[i + 1 * p_max] * sol[1] - rhs[i]; resid += e * e; } resid = Math.Sqrt(resid); Console.WriteLine(" Residual is " + resid + ""); }
private static void dqrls_test() //****************************************************************************80 // // Purpose: // // DQRLS_TEST tests DQRLS. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 21 April 2012 // // Author: // // John Burkardt // { double[] b = { 1.0, 2.3, 4.6, 3.1, 1.2 } ; int i; int kr = 0; const int m = 5; const int n = 3; double[] a = new double[m * n]; int[] jpvt = new int[n]; double[] qraux = new double[n]; double[] x = new double[n]; // // Set up least-squares problem // quadratic model, equally-spaced points // Console.WriteLine(""); Console.WriteLine("DQRLS_TEST"); Console.WriteLine(" DQRLS solves a linear system A*x = b in the least squares sense."); for (i = 0; i < m; i++) { a[i + 0 * m] = 1.0; int j; for (j = 1; j < n; j++) { a[i + j * m] = a[i + (j - 1) * m] * (i + 1); } } double tol = 1.0E-06; typeMethods.r8mat_print(m, n, a, " Coefficient matrix A:"); typeMethods.r8vec_print(m, b, " Right hand side b:"); // // Solve least-squares problem // int itask = 1; int ind = QRSolve.dqrls(ref a, m, m, n, tol, ref kr, b, ref x, ref b, jpvt, qraux, itask); // // Print results // Console.WriteLine(""); Console.WriteLine(" Error code = " + ind + ""); Console.WriteLine(" Estimated matrix rank = " + kr + ""); typeMethods.r8vec_print(n, x, " Least squares solution x:"); typeMethods.r8vec_print(m, b, " Residuals A*x-b"); }
private static void test01(int prob, int grd, int m) //****************************************************************************80 // // Purpose: // // VANDERMONDE_APPROX_2D_TEST01 tests VANDERMONDE_APPROX_2D_MATRIX. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int PROB, the problem number. // // Input, int GRD, the grid number. // (Can't use GRID as the name because that's also a plotting function.) // // Input, int M, the total polynomial degree. // { Console.WriteLine(""); Console.WriteLine("TEST01:"); Console.WriteLine(" Approximate data from TEST_INTERP_2D problem #" + prob + ""); Console.WriteLine(" Use grid from TEST_INTERP_2D with index #" + grd + ""); Console.WriteLine(" Using polynomial approximant of total degree " + m + ""); int nd = Data_2D.g00_size(grd); Console.WriteLine(" Number of data points = " + nd + ""); double[] xd = new double[nd]; double[] yd = new double[nd]; Data_2D.g00_xy(grd, nd, ref xd, ref yd); double[] zd = new double[nd]; Data_2D.f00_f0(prob, nd, xd, yd, ref zd); switch (nd) { case < 10: typeMethods.r8vec3_print(nd, xd, yd, zd, " X, Y, Z data:"); break; } // // Compute the Vandermonde matrix. // int tm = typeMethods.triangle_num(m + 1); double[] a = VandermondeMatrix.vandermonde_approx_2d_matrix(nd, m, tm, xd, yd); // // Solve linear system. // double[] c = QRSolve.qr_solve(nd, tm, a, zd); // // #1: Does approximant match function at data points? // int ni = nd; double[] xi = typeMethods.r8vec_copy_new(ni, xd); double[] yi = typeMethods.r8vec_copy_new(ni, yd); double[] zi = Polynomial.r8poly_values_2d(m, c, ni, xi, yi); double app_error = typeMethods.r8vec_norm_affine(ni, zi, zd) / ni; Console.WriteLine(""); Console.WriteLine(" L2 data approximation error = " + app_error + ""); }
private static void test01(int prob, int m) //****************************************************************************80 // // Purpose: // // TEST01 tests VANDERMONDE_INTERP_2D_MATRIX. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 07 October 2012 // // Author: // // John Burkardt // // Parameters: // // Input, int PROB, the problem number. // // Input, int M, the degree of interpolation. // { const bool debug = false; Console.WriteLine(""); Console.WriteLine("TEST01:"); Console.WriteLine(" Interpolate data from TEST_INTERP_2D problem #" + prob + ""); Console.WriteLine(" Create an interpolant of total degree " + m + ""); int tmp1 = typeMethods.triangle_num(m + 1); Console.WriteLine(" Number of data values needed is " + tmp1 + ""); int seed = 123456789; double[] xd = UniformRNG.r8vec_uniform_01_new(tmp1, ref seed); double[] yd = UniformRNG.r8vec_uniform_01_new(tmp1, ref seed); double[] zd = new double[tmp1]; Data_2D.f00_f0(prob, tmp1, xd, yd, ref zd); switch (debug) { case true: typeMethods.r8vec3_print(tmp1, xd, yd, zd, " X, Y, Z data:"); break; } // // Compute the Vandermonde matrix. // double[] a = Vandermonde.vandermonde_interp_2d_matrix(tmp1, m, xd, yd); // // Solve linear system. // double[] c = QRSolve.qr_solve(tmp1, tmp1, a, zd); // // #1: Does interpolant match function at data points? // int ni = tmp1; double[] xi = typeMethods.r8vec_copy_new(ni, xd); double[] yi = typeMethods.r8vec_copy_new(ni, yd); double[] zi = Polynomial.r8poly_values_2d(m, c, ni, xi, yi); double app_error = typeMethods.r8vec_norm_affine(ni, zi, zd) / ni; Console.WriteLine(""); Console.WriteLine(" L2 data interpolation error = " + app_error + ""); }