public static double[] brownian(int dim_num, int n, ref typeMethods.r8NormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // BROWNIAN creates Brownian motion points. // // Discussion: // // A starting point is generated at the origin. The next point // is generated at a uniformly random angle and a (0,1) normally // distributed distance from the previous point. // // It is up to the user to rescale the data, if desired. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 19 August 2004 // // Author: // // John Burkardt // // Parameters: // // Input, int DIM_NUM, the dimension of the space. // // Input, int N, the number of points. // // Input, int &SEED, a seed for the random number generator. // // Output, double BROWNIAN[DIM_NUM*N], the Brownian motion points. // { int i; double[] direction = new double[dim_num]; double[] x = new double[dim_num * n]; // // Initial point. // int j = 0; for (i = 0; i < dim_num; i++) { x[i + j * dim_num] = 0.0; } // // Generate angles and steps. // for (j = 1; j < n; j++) { double r = typeMethods.r8_normal_01(ref data, ref seed); r = Math.Abs(r); direction_uniform_nd(dim_num, ref seed, ref direction); for (i = 0; i < dim_num; i++) { x[i + j * dim_num] = x[i + (j - 1) * dim_num] + r * direction[i]; } } return(x); }
public static double[] dirichlet_sample(int n, double[] a, ref typeMethods.r8NormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // DIRICHLET_SAMPLE samples the Dirichlet PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 June 2013 // // Author: // // John Burkardt // // Reference: // // Jerry Banks, editor, // Handbook of Simulation, // Engineering and Management Press Books, 1998, page 169. // // Parameters: // // Input, int N, the number of components. // // Input, double A[N], the probabilities for each component. // Each A(I) should be nonnegative, and at least one should be // positive. // // Input/output, int &SEED, a seed for the random // number generator. // // Output, double DIRICHLET_SAMPLE[N], a sample of the PDF. The entries // of X should sum to 1. // { dirichlet_check(n, a); double[] x = new double[n]; for (int i = 0; i < n; i++) { x[i] = gamma_sample(a[i], 1.0, ref data, ref seed); } // // Normalize the result. // double x_sum = typeMethods.r8vec_sum(n, x); for (int i = 0; i < n; i++) { x[i] /= x_sum; } return(x); }
public static double[] f_alpha(int n, double q_d, double alpha, ref typeMethods.r8NormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // F_ALPHA generates a 1/F^ALPHA noise sequence. // // Discussion: // // Thanks to Miro Stoyanov for pointing out that the second half of // the data returned by the inverse Fourier transform should be // discarded, 24 August 2010. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 24 August 2010 // // Author: // // Original C version by Todd Walter. // C++ version by John Burkardt. // // Reference: // // Jeremy Kasdin, // Discrete Simulation of Colored Noise and Stochastic Processes // and 1/f^a Power Law Noise Generation, // Proceedings of the IEEE, // Volume 83, Number 5, 1995, pages 802-827. // // Parameters: // // Input, int N, the number of samples of the noise to generate. // // Input, double Q_D, the variance of the noise. // // Input, double ALPHA, the exponent for the noise. // // Input/output, int *SEED, a seed for the random number generator. // // Output, double F_ALPHA[N], a sequence sampled with the given // power law. // { double h_azero = 0; int i; double w_azero = 0; // // Set the deviation of the noise. // q_d = Math.Sqrt(q_d); // // Generate the coefficients Hk. // double[] hfa = new double[2 * n]; hfa[0] = 1.0; for (i = 1; i < n; i++) { hfa[i] = hfa[i - 1] * (0.5 * alpha + (i - 1)) / i; } for (i = n; i < 2 * n; i++) { hfa[i] = 0.0; } // // Fill Wk with white noise. // double[] wfa = new double[2 * n]; for (i = 0; i < n; i++) { wfa[i] = q_d * typeMethods.r8_normal_01(ref data, ref seed); } for (i = n; i < 2 * n; i++) { wfa[i] = 0.0; } // // Perform the discrete Fourier transforms of Hk and Wk. // double[] h_a = new double[n]; double[] h_b = new double[n]; Slow.r8vec_sftf(2 * n, hfa, ref h_azero, ref h_a, ref h_b); double[] w_a = new double[n]; double[] w_b = new double[n]; Slow.r8vec_sftf(2 * n, wfa, ref w_azero, ref w_a, ref w_b); // // Multiply the two complex vectors. // w_azero *= h_azero; for (i = 0; i < n; i++) { double wr = w_a[i]; double wi = w_b[i]; w_a[i] = wr * h_a[i] - wi * h_b[i]; w_b[i] = wi * h_a[i] + wr * h_b[i]; } // // This scaling is introduced only to match the behavior // of the Numerical Recipes code... // w_azero = w_azero * 2 * n; for (i = 0; i < n - 1; i++) { w_a[i] *= n; w_b[i] *= n; } i = n - 1; w_a[i] = w_a[i] * 2 * n; w_b[i] = w_b[i] * 2 * n; // // Take the inverse Fourier transform of the result. // double[] x2 = Slow.r8vec_sftb(2 * n, w_azero, w_a, w_b); // // Only return the first N inverse Fourier transform values. // double[] x = new double[n]; for (i = 0; i < n; i++) { x[i] = x2[i]; } return(x); }
public static double[] dirichlet_mix_sample(int comp_max, int comp_num, int elem_num, double[] a, double[] comp_weight, ref typeMethods.r8NormalData data, ref int seed, ref int comp) //****************************************************************************80 // // Purpose: // // DIRICHLET_MIX_SAMPLE samples a Dirichlet mixture PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 June 2013 // // Author: // // John Burkardt // // Parameters: // // Input, int COMP_MAX, the leading dimension of A, which // must be at least COMP_NUM. // // Input, int COMP_NUM, the number of components in the // Dirichlet mixture density, that is, the number of distinct Dirichlet PDF's // that are mixed together. // // Input, int ELEM_NUM, the number of elements of an // observation. // // Input, double A[COMP_MAX*ELEM_NUM], the probabilities for // element ELEM_NUM in component COMP_NUM. // Each A(I,J) should be greater than or equal to 0.0. // // Input, double COMP_WEIGHT[COMP_NUM], the mixture weights of // the densities. // These do not need to be normalized. The weight of a given component is // the relative probability that that component will be used to generate // the sample. // // Input/output, int &SEED, a seed for the random // number generator. // // Output, int &COMP, the index of the component of the // Dirichlet mixture that was chosen to generate the sample. // // Output, double DIRICHLET_MIX_SAMPLE[ELEM_NUM], a sample of the PDF. // { // // Check. // for (int comp_i = 0; comp_i < comp_num; comp_i++) { for (int elem_i = 0; elem_i < elem_num; elem_i++) { switch (a[comp_i + elem_i * comp_max]) { case < 0.0: Console.WriteLine(""); Console.WriteLine("DIRICHLET_MIX_SAMPLE - Fatal error!"); Console.WriteLine(" A(COMP,ELEM) < 0.'"); Console.WriteLine(" COMP = " + comp_i + ""); Console.WriteLine(" ELEM = " + elem_i + ""); Console.WriteLine(" A(COMP,ELEM) = " + a[comp_i + elem_i * comp_max] + ""); break; } } } // // Choose a particular density MIX. // double comp_weight_sum = typeMethods.r8vec_sum(comp_num, comp_weight); double r = UniformRNG.r8_uniform_ab(0.0, comp_weight_sum, ref seed); comp = 0; double sum2 = 0.0; while (comp < comp_num) { sum2 += comp_weight[comp]; if (r <= sum2) { break; } comp += 1; } // // Sample density COMP. // double[] x = new double[elem_num]; for (int elem_i = 0; elem_i < elem_num; elem_i++) { x[elem_i] = gamma_sample(a[comp + elem_i * comp_max], 1.0, ref data, ref seed); } // // Normalize the result. // double x_sum = typeMethods.r8vec_sum(elem_num, x); for (int elem_i = 0; elem_i < elem_num; elem_i++) { x[elem_i] /= x_sum; } return(x); }
public static double gamma_sample(double a, double b, ref typeMethods.r8NormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // GAMMA_SAMPLE samples the Gamma PDF. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 05 June 2013 // // Author: // // Original FORTRAN77 version by Joachim Ahrens, Ulrich Dieter. // C++ version by John Burkardt. // // Reference: // // Joachim Ahrens, Ulrich Dieter, // Computer Methods for Sampling from Gamma, Beta, Poisson and // Binomial Distributions, // Computing, // Volume 12, Number 3, September 1974, pages 223-246. // // Joachim Ahrens, Ulrich Dieter, // Generating Gamma Variates by a Modified Rejection Technique, // Communications of the ACM, // Volume 25, Number 1, January 1982, pages 47-54. // // Parameters: // // Input, double A, B, the parameters of the PDF. // 0.0 < A, // 0.0 < B. // // Input/output, int &SEED, a seed for the random // number generator. // // Output, double GAMMA_SAMPLE, a sample of the PDF. // { const double a1 = 0.3333333; const double a2 = -0.2500030; const double a3 = 0.2000062; const double a4 = -0.1662921; const double a5 = 0.1423657; const double a6 = -0.1367177; const double a7 = 0.1233795; const double e1 = 1.0; const double e2 = 0.4999897; const double e3 = 0.1668290; const double e4 = 0.0407753; const double e5 = 0.0102930; const double q1 = 0.04166669; const double q2 = 0.02083148; const double q3 = 0.00801191; const double q4 = 0.00144121; const double q5 = -0.00007388; const double q6 = 0.00024511; const double q7 = 0.00024240; double e; double x; switch (a) { // // Allow A = 0. // case 0.0: x = 0.0; return(x); // // A < 1. // case < 1.0: { for (;;) { double p = UniformRNG.r8_uniform_01(ref seed); p = (1.0 + 0.3678794 * a) * p; e = exponential_01_sample(ref seed); switch (p) { case >= 1.0: { x = -Math.Log((1.0 + 0.3678794 * a - p) / a); if ((1.0 - a) * Math.Log(x) <= e) { x /= b; return(x); } break; } default: { x = Math.Exp(Math.Log(p) / a); if (x <= e) { x /= b; return(x); } break; } } } } // default: { double s2 = a - 0.5; double s = Math.Sqrt(a - 0.5); double d = Math.Sqrt(32.0) - 12.0 * Math.Sqrt(a - 0.5); double t = typeMethods.r8_normal_01(ref data, ref seed); x = Math.Pow(Math.Sqrt(a - 0.5) + 0.5 * t, 2); switch (t) { case >= 0.0: x /= b; return(x); } double u = UniformRNG.r8_uniform_01(ref seed); if (d * u <= t * t * t) { x /= b; return(x); } double r = 1.0 / a; double q0 = (((((( q7 * r + q6) * r + q5) * r + q4) * r + q3) * r + q2) * r + q1) * r; double bcoef; double c; double si; switch (a) { case <= 3.686: bcoef = 0.463 + s - 0.178 * s2; si = 1.235; c = 0.195 / s - 0.079 + 0.016 * s; break; case <= 13.022: bcoef = 1.654 + 0.0076 * s2; si = 1.68 / s + 0.275; c = 0.062 / s + 0.024; break; default: bcoef = 1.77; si = 0.75; c = 0.1515 / s; break; } double q; double v; switch (Math.Sqrt(a - 0.5) + 0.5 * t) { case > 0.0: { v = 0.5 * t / s; q = Math.Abs(v) switch { > 0.25 => q0 - s * t + 0.25 * t * t + 2.0 * s2 * Math.Log(1.0 + v), _ => q0 + 0.5 * t * t * ((((((a7 * v + a6) * v + a5) * v + a4) * v + a3) * v + a2) * v + a1) * v }; if (Math.Log(1.0 - u) <= q) { x /= b; return(x); } break; } } for (;;) { e = exponential_01_sample(ref seed); u = UniformRNG.r8_uniform_01(ref seed); t = u switch {
public static double[] orth_random(int n, ref typeMethods.r8NormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // ORTH_RANDOM returns the ORTH_RANDOM matrix. // // Discussion: // // The matrix is a random orthogonal matrix. // // Properties: // // The inverse of A is equal to A'. // A is orthogonal: A * A' = A' * A = I. // Because A is orthogonal, it is normal: A' * A = A * A'. // Columns and rows of A have unit Euclidean norm. // Distinct pairs of columns of A are orthogonal. // Distinct pairs of rows of A are orthogonal. // The L2 vector norm of A*x = the L2 vector norm of x for any vector x. // The L2 matrix norm of A*B = the L2 matrix norm of B for any matrix B. // det ( A ) = +1 or -1. // A is unimodular. // All the eigenvalues of A have modulus 1. // All singular values of A are 1. // All entries of A are between -1 and 1. // // Discussion: // // Thanks to Eugene Petrov, B I Stepanov Institute of Physics, // National Academy of Sciences of Belarus, for convincingly // pointing out the severe deficiencies of an earlier version of // this routine. // // Essentially, the computation involves saving the Q factor of the // QR factorization of a matrix whose entries are normally distributed. // However, it is only necessary to generate this matrix a column at // a time, since it can be shown that when it comes time to annihilate // the subdiagonal elements of column K, these (transformed) elements of // column K are still normally distributed random values. Hence, there // is no need to generate them at the beginning of the process and // transform them K-1 times. // // For computational efficiency, the individual Householder transformations // could be saved, as recommended in the reference, instead of being // accumulated into an explicit matrix format. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 11 July 2008 // // Author: // // John Burkardt // // Reference: // // Pete Stewart, // Efficient Generation of Random Orthogonal Matrices With an Application // to Condition Estimators, // SIAM Journal on Numerical Analysis, // Volume 17, Number 3, June 1980, pages 403-409. // // Parameters: // // Input, int N, the order of the matrix. // // Input/output, int &SEED, a seed for the random number // generator. // // Output, double ORTH_RANDOM[N*N] the matrix. // { int i; int j; // // Start with A = the identity matrix. // double[] a = typeMethods.r8mat_zero_new(n, n); for (i = 0; i < n; i++) { a[i + i * n] = 1.0; } // // Now behave as though we were computing the QR factorization of // some other random matrix. Generate the N elements of the first column, // compute the Householder matrix H1 that annihilates the subdiagonal elements, // and set A := A * H1' = A * H. // // On the second step, generate the lower N-1 elements of the second column, // compute the Householder matrix H2 that annihilates them, // and set A := A * H2' = A * H2 = H1 * H2. // // On the N-1 step, generate the lower 2 elements of column N-1, // compute the Householder matrix HN-1 that annihilates them, and // and set A := A * H(N-1)' = A * H(N-1) = H1 * H2 * ... * H(N-1). // This is our random orthogonal matrix. // double[] x = new double[n]; for (j = 0; j < n - 1; j++) { // // Set the vector that represents the J-th column to be annihilated. // for (i = 0; i < j; i++) { x[i] = 0.0; } for (i = j; i < n; i++) { x[i] = typeMethods.r8_normal_01(ref data, ref seed); } // // Compute the vector V that defines a Householder transformation matrix // H(V) that annihilates the subdiagonal elements of X. // // The COLUMN argument here is 1-based. // double[] v = typeMethods.r8vec_house_column(n, x, j + 1); // // Postmultiply the matrix A by H'(V) = H(V). // typeMethods.r8mat_house_axh(n, ref a, v); } return(a); }
public static double[] pds_random(int n, ref typeMethods.r8NormalData data, ref int seed) //****************************************************************************80 // // Purpose: // // PDS_RANDOM returns the PDS_RANDOM matrix. // // Discussion: // // The matrix is a "random" positive definite symmetric matrix. // // The matrix returned will have eigenvalues in the range [0,1]. // // Properties: // // A is symmetric: A' = A. // // A is positive definite: 0 < x'*A*x for nonzero x. // // The eigenvalues of A will be real. // // Licensing: // // This code is distributed under the GNU LGPL license. // // Modified: // // 15 June 2011 // // Author: // // John Burkardt // // Parameters: // // Input, int N, the order of the matrix. // // Input/output, int &SEED, a seed for the random // number generator. // // Output, double PDS_RANDOM[N*N], the matrix. // { int j; double[] a = new double[n * n]; // // Get a random set of eigenvalues. // double[] lambda = UniformRNG.r8vec_uniform_01_new(n, ref seed); // // Get a random orthogonal matrix Q. // double[] q = Orthogonal.orth_random(n, ref data, ref seed); // // Set A = Q * Lambda * Q'. // for (j = 0; j < n; j++) { int i; for (i = 0; i < n; i++) { a[i + j * n] = 0.0; int k; for (k = 0; k < n; k++) { a[i + j * n] += q[i + k * n] * lambda[k] * q[j + k * n]; } } } return(a); }
public static void stab_asymptotic(ref typeMethods.r8vecNormalData vdata, ref typeMethods.r8NormalData data, ref int seed, int n, int p_max) //****************************************************************************80 // // Purpose: // // STAB_ASYMPTOTIC examines asymptotic stability. // // Discussion: // // The function tests the asymptotic stability // of the Euler-Maruyama method applied to a stochastic differential // equation (SDE). // // The SDE is // // dX = lambda*X dt + mu*X dW, // X(0) = Xzero, // // where // // lambda is a constant, // mu is a constant, // Xzero = 1. // // 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 N, the number of time steps for the // first solution. // // Input, int P_MAX, the number of time step sizes. // { const string command_filename = "stab_asymptotic_commands.txt"; List <string> command = new(); const string data_filename0 = "stab_asymptotic0_data.txt"; List <string> out_data = new(); int p; Console.WriteLine(""); Console.WriteLine("STAB_ASYMPTOTIC:"); Console.WriteLine(" Investigate asymptotic stability of Euler-Maruyama"); Console.WriteLine(" solution with stepsize DT and MU."); Console.WriteLine(""); Console.WriteLine(" SDE is asymptotically stable if"); Console.WriteLine(" Real ( lambda - 1/2 mu^2 ) < 0."); Console.WriteLine(""); Console.WriteLine(" EM with DT is asymptotically stable if"); Console.WriteLine(" E log ( | 1 + lambda dt - sqrt(dt) mu n(0,1) | ) < 0."); Console.WriteLine(" where n(0,1) is a normal random value."); // // Problem parameters. // const double lambda = 0.5; double mu = Math.Sqrt(6.0); const double xzero = 1.0; // // Test the SDE. // Console.WriteLine(""); Console.WriteLine(" Lambda = " + lambda + ""); Console.WriteLine(" Mu = " + mu + ""); double test = lambda - 0.5 * mu * mu; Console.WriteLine(" SDE asymptotic stability test = " + test + ""); // // Step parameters. // const double tmax = 500.0; // // For each stepsize, compute the Euler-Maruyama solution. // string data_filename = data_filename0; double[] dtvals = new double[p_max]; for (p = 0; p < p_max; p++) { int nval = n * (int)Math.Pow(2, p); double dt = tmax / nval; dtvals[p] = dt; // // Test the EM for this DT. // Console.WriteLine(""); Console.WriteLine(" dt = " + dt + ""); double[] u = typeMethods.r8vec_normal_01_new(1000, ref vdata, ref seed); int i; for (i = 0; i < 1000; i++) { u[i] = Math.Log(Math.Abs(1.0 + lambda * dt - Math.Sqrt(dt) * mu * u[i])); } test = typeMethods.r8vec_mean(1000, u); Console.WriteLine(" EM asymptotic test = " + test + ""); double xtemp = xzero; double[] xemabs = new double[nval + 1]; xemabs[0] = xtemp; int j; for (j = 1; j <= nval; j++) { double winc = Math.Sqrt(dt) * typeMethods.r8_normal_01(ref data, ref seed); xtemp = xtemp + dt * lambda * xtemp + mu * xtemp * winc; xemabs[j] = Math.Abs(xtemp); } // // Write this data to a file. // Files.filename_inc(ref data_filename); // // We have to impose a tiny lower bound on the values because we // will end up plotting their logs. // double xmin = Math.Exp(-200.0); for (i = 0; i <= nval; i++) { double t = tmax * i / nval; out_data.Add(" " + t + " " + Math.Max(xemabs[i], xmin) + ""); } File.WriteAllLines(data_filename, out_data); Console.WriteLine(""); Console.WriteLine(" Data for DT = " + dt + " stored in \"" + data_filename + "\""); } command.Add("# stab_asymptotic_commands.txt"); command.Add("# created by sde::stab_asymptotic."); command.Add("#"); command.Add("# Usage:"); command.Add("# gnuplot < stab_asymptotic_commands.txt"); command.Add("#"); command.Add("set term png"); command.Add("set output 'stab_asymptotic.png'"); command.Add("set xlabel 't'"); command.Add("set ylabel '|X(t)|'"); command.Add("set title 'Absolute value of EM Solution'"); command.Add("set grid"); command.Add("set logscale y 10"); command.Add("set style data lines"); data_filename = data_filename0; Files.filename_inc(ref data_filename); command.Add("plot '" + data_filename + "' using 1:2, \\"); for (p = 1; p < p_max - 1; p++) { Files.filename_inc(ref data_filename); command.Add(" '" + data_filename + "' using 1:2, \\"); } Files.filename_inc(ref data_filename); command.Add(" '" + data_filename + "' using 1:2"); command.Add("quit"); File.WriteAllLines(command_filename, command); Console.WriteLine(" STAB_ASYMPTOTIC plot stored in \"" + command_filename + "\"."); }