1 文本格式
using System;
namespace Legalsoft.Truffer
{
/// <summary>
/// Complete VEGAS Code
/// adaptive/recursive Monte Carlo
/// </summary>
public abstract class VEGAS
{
const int NDMX = 50;
const int MXDIM = 10;
const int RANSEED = 5330;
const double ALPH = 1.5;
const double TINY = 1.0e-30;
private Ran ran_vegas = new Ran(RANSEED);
//public static delegateFuncVectorDouble func_v_d { get; set; } = null;
public VEGAS()
{
}
public abstract double fxn(double[] x, double wgt);
public static void rebin(double rc, int nd, double[] r, double[] xin, double[,] xi, int j)
{
//int i;
int k = 0;
double dr = 0.0;
//double xn = 0.0;
double xo = 0.0;
for (int i = 0; i < nd - 1; i++)
{
while (rc > dr)
{
dr += r[(++k) - 1];
}
if (k > 1)
{
xo = xi[j, k - 2];
}
double xn = xi[j, k - 1];
dr -= rc;
xin[i] = xn - (xn - xo) * dr / r[k - 1];
}
for (int i = 0; i < nd - 1; i++)
{
xi[j, i] = xin[i];
}
xi[j, nd - 1] = 1.0;
}
/// <summary>
/// Performs Monte Carlo integration of a user-supplied ndim-dimensional
/// function fxn over a rectangular volume specified by regn[0..2 * ndim - 1], a
/// vector consisting of ndim "lower left" coordinates of the region followed
/// by ndim "upper right" coordinates.The integration consists of itmx
/// iterations, each with approximately ncall calls to the function.After each
/// iteration the grid is refined; more than 5 or 10 iterations are rarely
/// useful.The input flag init signals whether this call is a new start or a
/// subsequent call for additional iterations(see comments in the code). The
/// input flag nprn(normally 0) controls the amount of diagnostic output.
/// Returned answers are tgral (the best estimate of the integral), sd(its
/// standard deviation), and chi2a(X^2 per degree of freedom, an indicator of
/// whether consistent results are being obtained).
/// </summary>
/// <param name="regn"></param>
/// <param name="init"></param>
/// <param name="ncall"></param>
/// <param name="itmx"></param>
/// <param name="nprn"></param>
/// <param name="tgral"></param>
/// <param name="sd"></param>
/// <param name="chi2a"></param>
public void vegas(double[] regn, int init, int ncall, int itmx, int nprn, ref double tgral, ref double sd, ref double chi2a)
{
int mds = 0;
int ndo = 0;
double schi = 0.0;
double si = 0.0;
double swgt = 0.0;
int[] ia = new int[MXDIM];
int[] kg = new int[MXDIM];
double[] dt = new double[MXDIM];
double[] dx = new double[MXDIM];
double[] r = new double[NDMX];
double[] x = new double[MXDIM];
double[] xin = new double[NDMX];
double[,] d = new double[NDMX, MXDIM];
double[,] di = new double[NDMX, MXDIM];
double[,] xi = new double[MXDIM, NDMX];
//Ran ran_vegas = new Ran(RANSEED);
int ndim = regn.Length / 2;
if (init <= 0)
{
mds = ndo = 1;
for (int j = 0; j < ndim; j++)
{
xi[j, 0] = 1.0;
}
}
if (init <= 1)
{
si = swgt = schi = 0.0;
}
if (init <= 2)
{
int nd = NDMX;
int ng = 1;
if (mds != 0)
{
ng = (int)Math.Pow(ncall / 2.0 + 0.25, 1.0 / ndim);
mds = 1;
if ((2 * ng - NDMX) >= 0)
{
mds = -1;
int n1pg = ng / NDMX + 1;
nd = ng / n1pg;
ng = n1pg * nd;
}
}
int k = 1;
for (int i = 0; i < ndim; i++)
{
k *= ng;
}
int npg = Math.Max((int)(ncall / k), 2);
double calls = (double)npg * (double)k;
double dxg = 1.0 / ng;
double dv2g = 1.0;
for (int i = 0; i < ndim; i++)
{
dv2g *= dxg;
}
dv2g = Globals.SQR(calls * dv2g) / npg / npg / (npg - 1.0);
int xnd = nd;
dxg *= xnd;
double xjac = 1.0 / calls;
for (int j = 0; j < ndim; j++)
{
dx[j] = regn[j + ndim] - regn[j];
xjac *= dx[j];
}
if (nd != ndo)
{
for (int i = 0; i < Math.Max(nd, ndo); i++)
{
r[i] = 1.0;
}
for (int j = 0; j < ndim; j++)
{
rebin(ndo / xnd, nd, r, xin, xi, j);
}
ndo = nd;
}
if (nprn >= 0)
{
/*
Console.Write(" Input parameters for vegas");
Console.Write(" ndim= ");
Console.Write("{0,4}", ndim);
Console.Write("{0,4}", " ncall= ");
Console.Write("{0,8}", calls);
Console.Write("{0}", "\n");
Console.Write("{0,34}", " it=");
Console.Write("{0,5}", it);
Console.Write("{0,5}", " itmx=");
Console.Write("{0,5}", itmx);
Console.Write("{0}", "\n");
Console.Write("{0,34}", " nprn=");
Console.Write("{0,5}", nprn);
Console.Write("{0,5}", " ALPH=");
Console.Write("{0,9}", ALPH);
Console.Write("{0}", "\n");
Console.Write("{0,34}", " mds=");
Console.Write("{0,5}", mds);
Console.Write("{0,5}", " nd=");
Console.Write("{0,5}", nd);
Console.Write("{0}", "\n");
for (j = 0; j < ndim; j++)
{
Console.Write("{0,30}", " x1[");
Console.Write("{0,2}", j);
Console.Write("{0,2}", "]= ");
Console.Write("{0,11}", regn[j]);
Console.Write("{0}", " xu[");
Console.Write("{0,2}", j);
Console.Write("{0}", "]= ");
Console.Write("{0,11}", regn[j + ndim]);
Console.Write("{0}", "\n");
}
*/
for (int it = 0; it < itmx; it++)
{
double ti = 0.0;
double tsi = 0.0;
for (int j = 0; j < ndim; j++)
{
kg[j] = 1;
for (int i = 0; i < nd; i++)
{
d[i, j] = di[i, j] = 0.0;
}
}
for (; ; )
{
double fb = 0.0;
double f2b = 0.0;
for (k = 0; k < npg; k++)
{
double w1gt = xjac;
for (int j = 0; j < ndim; j++)
{
double xn = (kg[j] - ran_vegas.doub()) * dxg + 1.0;
ia[j] = Math.Max(Math.Min((int)xn, NDMX), 1);
double xo;
double rc;
if (ia[j] > 1)
{
xo = xi[j, ia[j] - 1] - xi[j, ia[j] - 2];
rc = xi[j, ia[j] - 2] + (xn - ia[j]) * xo;
}
else
{
xo = xi[j, ia[j] - 1];
rc = (xn - ia[j]) * xo;
}
x[j] = regn[j] + rc * dx[j];
w1gt *= xo * xnd;
}
double f = w1gt * fxn(x, w1gt);
double f2 = f * f;
fb += f;
f2b += f2;
for (int j = 0; j < ndim; j++)
{
di[ia[j] - 1, j] += f;
if (mds >= 0)
{
d[ia[j] - 1, j] += f2;
}
}
}
f2b = Math.Sqrt(f2b * npg);
f2b = (f2b - fb) * (f2b + fb);
if (f2b <= 0.0)
{
f2b = TINY;
}
ti += fb;
tsi += f2b;
if (mds < 0)
{
for (int j = 0; j < ndim; j++)
{
d[ia[j] - 1, j] += f2b;
}
}
for (k = ndim - 1; k >= 0; k--)
{
kg[k] %= ng;
if (++kg[k] != 1)
{
break;
}
}
if (k < 0)
{
break;
}
}
tsi *= dv2g;
double wgt = 1.0 / tsi;
si += wgt * ti;
schi += wgt * ti * ti;
swgt += wgt;
tgral = si / swgt;
chi2a = (schi - si * tgral) / (it + 0.0001);
if (chi2a < 0.0)
{
chi2a = 0.0;
}
sd = Math.Sqrt(1.0 / swgt);
tsi = Math.Sqrt(tsi);
}
if (nprn >= 0)
{
/*
Console.Write(" iteration no. ");
Console.Write("{0,3}", (it + 1));
Console.Write("{0,3}", " : integral = ");
Console.Write("{0,14}", ti);
Console.Write("{0,14}", " +/- ");
Console.Write("{0,9}", tsi);
Console.Write("{0}", "\n");
Console.Write("{0}", " all iterations: ");
Console.Write("{0}", " integral =");
Console.Write("{0,14}", tgral);
Console.Write("{0}", "+-");
Console.Write("{0,9}", sd);
Console.Write("{0,9}", " chi**2/IT n =");
Console.Write("{0,9}", chi2a);
Console.Write("{0}", "\n");
if (nprn != 0)
{
for (j = 0; j < ndim; j++)
{
Console.Write("{0}", " DATA FOR axis ");
Console.Write("{0,2}", j);
Console.Write("{0}", "\n");
Console.Write("{0}", " X delta i X delta i");
Console.Write("{0}", " X deltai");
Console.Write("{0}", "\n");
for (i = nprn / 2; i < nd - 2; i += nprn + 2)
{
Console.Write("{0,8}", xi[j, i]);
Console.Write("{0,12}", di[i, j]);
Console.Write("{0,12}", xi[j, i + 1]);
Console.Write("{0,12}", di[i + 1, j]);
Console.Write("{0,12}", xi[j, i + 2]);
Console.Write("{0,12}", di[i + 2, j]);
Console.Write("{0,12}", "\n");
}
}
}
*/
}
for (int j = 0; j < ndim; j++)
{
double xo = d[0, j];
double xn = d[1, j];
d[0, j] = (xo + xn) / 2.0;
dt[j] = d[0, j];
for (int i = 2; i < nd; i++)
{
double rc = xo + xn;
xo = xn;
xn = d[i, j];
d[i - 1, j] = (rc + xn) / 3.0;
dt[j] += d[i - 1, j];
}
d[nd - 1, j] = (xo + xn) / 2.0;
dt[j] += d[nd - 1, j];
}
for (int j = 0; j < ndim; j++)
{
double rc = 0.0;
for (int i = 0; i < nd; i++)
{
if (d[i, j] < TINY)
{
d[i, j] = TINY;
}
r[i] = Math.Pow((1.0 - d[i, j] / dt[j]) / (Math.Log(dt[j]) - Math.Log(d[i, j])), ALPH);
rc += r[i];
}
rebin(rc / xnd, nd, r, xin, xi, j);
}
}
}
}
}
}
2 代码格式
using System;
namespace Legalsoft.Truffer
{
/// <summary>
/// Complete VEGAS Code
/// adaptive/recursive Monte Carlo
/// </summary>
public abstract class VEGAS
{
const int NDMX = 50;
const int MXDIM = 10;
const int RANSEED = 5330;
const double ALPH = 1.5;
const double TINY = 1.0e-30;
private Ran ran_vegas = new Ran(RANSEED);
//public static delegateFuncVectorDouble func_v_d { get; set; } = null;
public VEGAS()
{
}
public abstract double fxn(double[] x, double wgt);
public static void rebin(double rc, int nd, double[] r, double[] xin, double[,] xi, int j)
{
//int i;
int k = 0;
double dr = 0.0;
//double xn = 0.0;
double xo = 0.0;
for (int i = 0; i < nd - 1; i++)
{
while (rc > dr)
{
dr += r[(++k) - 1];
}
if (k > 1)
{
xo = xi[j, k - 2];
}
double xn = xi[j, k - 1];
dr -= rc;
xin[i] = xn - (xn - xo) * dr / r[k - 1];
}
for (int i = 0; i < nd - 1; i++)
{
xi[j, i] = xin[i];
}
xi[j, nd - 1] = 1.0;
}
/// <summary>
/// Performs Monte Carlo integration of a user-supplied ndim-dimensional
/// function fxn over a rectangular volume specified by regn[0..2 * ndim - 1], a
/// vector consisting of ndim "lower left" coordinates of the region followed
/// by ndim "upper right" coordinates.The integration consists of itmx
/// iterations, each with approximately ncall calls to the function.After each
/// iteration the grid is refined; more than 5 or 10 iterations are rarely
/// useful.The input flag init signals whether this call is a new start or a
/// subsequent call for additional iterations(see comments in the code). The
/// input flag nprn(normally 0) controls the amount of diagnostic output.
/// Returned answers are tgral (the best estimate of the integral), sd(its
/// standard deviation), and chi2a(X^2 per degree of freedom, an indicator of
/// whether consistent results are being obtained).
/// </summary>
/// <param name="regn"></param>
/// <param name="init"></param>
/// <param name="ncall"></param>
/// <param name="itmx"></param>
/// <param name="nprn"></param>
/// <param name="tgral"></param>
/// <param name="sd"></param>
/// <param name="chi2a"></param>
public void vegas(double[] regn, int init, int ncall, int itmx, int nprn, ref double tgral, ref double sd, ref double chi2a)
{
int mds = 0;
int ndo = 0;
double schi = 0.0;
double si = 0.0;
double swgt = 0.0;
int[] ia = new int[MXDIM];
int[] kg = new int[MXDIM];
double[] dt = new double[MXDIM];
double[] dx = new double[MXDIM];
double[] r = new double[NDMX];
double[] x = new double[MXDIM];
double[] xin = new double[NDMX];
double[,] d = new double[NDMX, MXDIM];
double[,] di = new double[NDMX, MXDIM];
double[,] xi = new double[MXDIM, NDMX];
//Ran ran_vegas = new Ran(RANSEED);
int ndim = regn.Length / 2;
if (init <= 0)
{
mds = ndo = 1;
for (int j = 0; j < ndim; j++)
{
xi[j, 0] = 1.0;
}
}
if (init <= 1)
{
si = swgt = schi = 0.0;
}
if (init <= 2)
{
int nd = NDMX;
int ng = 1;
if (mds != 0)
{
ng = (int)Math.Pow(ncall / 2.0 + 0.25, 1.0 / ndim);
mds = 1;
if ((2 * ng - NDMX) >= 0)
{
mds = -1;
int n1pg = ng / NDMX + 1;
nd = ng / n1pg;
ng = n1pg * nd;
}
}
int k = 1;
for (int i = 0; i < ndim; i++)
{
k *= ng;
}
int npg = Math.Max((int)(ncall / k), 2);
double calls = (double)npg * (double)k;
double dxg = 1.0 / ng;
double dv2g = 1.0;
for (int i = 0; i < ndim; i++)
{
dv2g *= dxg;
}
dv2g = Globals.SQR(calls * dv2g) / npg / npg / (npg - 1.0);
int xnd = nd;
dxg *= xnd;
double xjac = 1.0 / calls;
for (int j = 0; j < ndim; j++)
{
dx[j] = regn[j + ndim] - regn[j];
xjac *= dx[j];
}
if (nd != ndo)
{
for (int i = 0; i < Math.Max(nd, ndo); i++)
{
r[i] = 1.0;
}
for (int j = 0; j < ndim; j++)
{
rebin(ndo / xnd, nd, r, xin, xi, j);
}
ndo = nd;
}
if (nprn >= 0)
{
/*
Console.Write(" Input parameters for vegas");
Console.Write(" ndim= ");
Console.Write("{0,4}", ndim);
Console.Write("{0,4}", " ncall= ");
Console.Write("{0,8}", calls);
Console.Write("{0}", "\n");
Console.Write("{0,34}", " it=");
Console.Write("{0,5}", it);
Console.Write("{0,5}", " itmx=");
Console.Write("{0,5}", itmx);
Console.Write("{0}", "\n");
Console.Write("{0,34}", " nprn=");
Console.Write("{0,5}", nprn);
Console.Write("{0,5}", " ALPH=");
Console.Write("{0,9}", ALPH);
Console.Write("{0}", "\n");
Console.Write("{0,34}", " mds=");
Console.Write("{0,5}", mds);
Console.Write("{0,5}", " nd=");
Console.Write("{0,5}", nd);
Console.Write("{0}", "\n");
for (j = 0; j < ndim; j++)
{
Console.Write("{0,30}", " x1[");
Console.Write("{0,2}", j);
Console.Write("{0,2}", "]= ");
Console.Write("{0,11}", regn[j]);
Console.Write("{0}", " xu[");
Console.Write("{0,2}", j);
Console.Write("{0}", "]= ");
Console.Write("{0,11}", regn[j + ndim]);
Console.Write("{0}", "\n");
}
*/
for (int it = 0; it < itmx; it++)
{
double ti = 0.0;
double tsi = 0.0;
for (int j = 0; j < ndim; j++)
{
kg[j] = 1;
for (int i = 0; i < nd; i++)
{
d[i, j] = di[i, j] = 0.0;
}
}
for (; ; )
{
double fb = 0.0;
double f2b = 0.0;
for (k = 0; k < npg; k++)
{
double w1gt = xjac;
for (int j = 0; j < ndim; j++)
{
double xn = (kg[j] - ran_vegas.doub()) * dxg + 1.0;
ia[j] = Math.Max(Math.Min((int)xn, NDMX), 1);
double xo;
double rc;
if (ia[j] > 1)
{
xo = xi[j, ia[j] - 1] - xi[j, ia[j] - 2];
rc = xi[j, ia[j] - 2] + (xn - ia[j]) * xo;
}
else
{
xo = xi[j, ia[j] - 1];
rc = (xn - ia[j]) * xo;
}
x[j] = regn[j] + rc * dx[j];
w1gt *= xo * xnd;
}
double f = w1gt * fxn(x, w1gt);
double f2 = f * f;
fb += f;
f2b += f2;
for (int j = 0; j < ndim; j++)
{
di[ia[j] - 1, j] += f;
if (mds >= 0)
{
d[ia[j] - 1, j] += f2;
}
}
}
f2b = Math.Sqrt(f2b * npg);
f2b = (f2b - fb) * (f2b + fb);
if (f2b <= 0.0)
{
f2b = TINY;
}
ti += fb;
tsi += f2b;
if (mds < 0)
{
for (int j = 0; j < ndim; j++)
{
d[ia[j] - 1, j] += f2b;
}
}
for (k = ndim - 1; k >= 0; k--)
{
kg[k] %= ng;
if (++kg[k] != 1)
{
break;
}
}
if (k < 0)
{
break;
}
}
tsi *= dv2g;
double wgt = 1.0 / tsi;
si += wgt * ti;
schi += wgt * ti * ti;
swgt += wgt;
tgral = si / swgt;
chi2a = (schi - si * tgral) / (it + 0.0001);
if (chi2a < 0.0)
{
chi2a = 0.0;
}
sd = Math.Sqrt(1.0 / swgt);
tsi = Math.Sqrt(tsi);
}
if (nprn >= 0)
{
/*
Console.Write(" iteration no. ");
Console.Write("{0,3}", (it + 1));
Console.Write("{0,3}", " : integral = ");
Console.Write("{0,14}", ti);
Console.Write("{0,14}", " +/- ");
Console.Write("{0,9}", tsi);
Console.Write("{0}", "\n");
Console.Write("{0}", " all iterations: ");
Console.Write("{0}", " integral =");
Console.Write("{0,14}", tgral);
Console.Write("{0}", "+-");
Console.Write("{0,9}", sd);
Console.Write("{0,9}", " chi**2/IT n =");
Console.Write("{0,9}", chi2a);
Console.Write("{0}", "\n");
if (nprn != 0)
{
for (j = 0; j < ndim; j++)
{
Console.Write("{0}", " DATA FOR axis ");
Console.Write("{0,2}", j);
Console.Write("{0}", "\n");
Console.Write("{0}", " X delta i X delta i");
Console.Write("{0}", " X deltai");
Console.Write("{0}", "\n");
for (i = nprn / 2; i < nd - 2; i += nprn + 2)
{
Console.Write("{0,8}", xi[j, i]);
Console.Write("{0,12}", di[i, j]);
Console.Write("{0,12}", xi[j, i + 1]);
Console.Write("{0,12}", di[i + 1, j]);
Console.Write("{0,12}", xi[j, i + 2]);
Console.Write("{0,12}", di[i + 2, j]);
Console.Write("{0,12}", "\n");
}
}
}
*/
}
for (int j = 0; j < ndim; j++)
{
double xo = d[0, j];
double xn = d[1, j];
d[0, j] = (xo + xn) / 2.0;
dt[j] = d[0, j];
for (int i = 2; i < nd; i++)
{
double rc = xo + xn;
xo = xn;
xn = d[i, j];
d[i - 1, j] = (rc + xn) / 3.0;
dt[j] += d[i - 1, j];
}
d[nd - 1, j] = (xo + xn) / 2.0;
dt[j] += d[nd - 1, j];
}
for (int j = 0; j < ndim; j++)
{
double rc = 0.0;
for (int i = 0; i < nd; i++)
{
if (d[i, j] < TINY)
{
d[i, j] = TINY;
}
r[i] = Math.Pow((1.0 - d[i, j] / dt[j]) / (Math.Log(dt[j]) - Math.Log(d[i, j])), ALPH);
rc += r[i];
}
rebin(rc / xnd, nd, r, xin, xi, j);
}
}
}
}
}
}