C#,数值计算——完全VEGAS编码的蒙特·卡洛计算方法与源程序

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 代码格式

cs 复制代码
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);
                    }
                }
            }
        }
    }
}
相关推荐
游是水里的游3 分钟前
【算法day19】回溯:分割与子集问题
算法
不想当程序猿_4 分钟前
【蓝桥杯每日一题】分糖果——DFS
c++·算法·蓝桥杯·深度优先
晚夜微雨问海棠呀5 分钟前
长沙景区数据分析项目实现
开发语言·python·信息可视化
graceyun6 分钟前
C语言初阶习题【9】数9的个数
c语言·开发语言
南城花随雪。23 分钟前
单片机:实现FFT快速傅里叶变换算法(附带源码)
单片机·嵌入式硬件·算法
dundunmm38 分钟前
机器学习之scikit-learn(简称 sklearn)
python·算法·机器学习·scikit-learn·sklearn·分类算法
古希腊掌管学习的神39 分钟前
[机器学习]sklearn入门指南(1)
人工智能·python·算法·机器学习·sklearn
波音彬要多做40 分钟前
41 stack类与queue类
开发语言·数据结构·c++·学习·算法
Swift社区1 小时前
Excel 列名称转换问题 Swift 解答
开发语言·excel·swift
一道微光1 小时前
Mac的M2芯片运行lightgbm报错,其他python包可用,x86_x64架构运行
开发语言·python·macos