C#,数值计算——Miser的计算方法与源程序

1 文本格式

using System;

namespace Legalsoft.Truffer
{
    public class Miser
    {
        const int RANSEED = 5331;
        static Ran ran = new Ran(RANSEED);

        public Miser()
        {
        }

        public static void ranpt(double[] pt, double[] regn)
        {
            int n = pt.Length;
            for (int j = 0; j < n; j++)
            {
                pt[j] = regn[j] + (regn[n + j] - regn[j]) * ran.doub();
            }
        }

        /// <summary>
        /// Monte Carlo samples a user-supplied ndim-dimensional function func in 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 function is sampled a total of npts times, at locations
        /// determined by the method of recursive stratified sampling.The mean value
        /// of the function in the region is returned as ave; an estimate of the
        /// statistical uncertainty of ave(square of standard deviation) is returned
        /// as var.The input parameter dith should normally be set to zero, but can be
        /// set to(e.g.) 0.1 if func's active region falls on the boundary of a
        /// power-of-two subdivision of region.
        /// </summary>
        /// <param name="regn"></param>
        /// <param name="npts"></param>
        /// <param name="dith"></param>
        /// <param name="ave"></param>
        /// <param name="xvar"></param>
        public static void miser(RealValueFun func, double[] regn, int npts, double dith, ref double ave, ref double xvar)
        {
            const int MNPT = 15;
            const int MNBS = 60;
            const double PFAC = 0.1;
            const double TINY = 1.0e-30;
            const double BIG = 1.0e30;

            int iran = 0;
            int ndim = regn.Length / 2;
            double[] pt = new double[ndim];
            if (npts < MNBS)
            {
                double summ = 0.0;
                double summ2 = 0.0;
                for (int n = 0; n < npts; n++)
                {
                    ranpt(pt, regn);
                    double fval = func.funk(pt);
                    summ += fval;
                    summ2 += fval * fval;
                }
                ave = summ / npts;
                xvar = Math.Max(TINY, (summ2 - summ * summ / npts) / (npts * npts));
            }
            else
            {
                double[] rmid = new double[ndim];
                int npre = Math.Max((int)(npts * PFAC), (int)MNPT);
                double[] fmaxl = new double[ndim];
                double[] fmaxr = new double[ndim];
                double[] fminl = new double[ndim];
                double[] fminr = new double[ndim];
                for (int j = 0; j < ndim; j++)
                {
                    iran = (iran * 2661 + 36979) % 175000;
                    double s = Globals.SIGN(dith, (double)(iran - 87500));
                    rmid[j] = (0.5 + s) * regn[j] + (0.5 - s) * regn[ndim + j];
                    fminl[j] = fminr[j] = BIG;
                    fmaxl[j] = fmaxr[j] = (-BIG);
                }
                for (int n = 0; n < npre; n++)
                {
                    ranpt(pt, regn);
                    double fval = func.funk(pt);
                    for (int j = 0; j < ndim; j++)
                    {
                        if (pt[j] <= rmid[j])
                        {
                            fminl[j] = Math.Min(fminl[j], fval);
                            fmaxl[j] = Math.Max(fmaxl[j], fval);
                        }
                        else
                        {
                            fminr[j] = Math.Min(fminr[j], fval);
                            fmaxr[j] = Math.Max(fmaxr[j], fval);
                        }
                    }
                }
                double sumb = BIG;
                int jb = -1;
                double siglb = 1.0;
                double sigrb = 1.0;
                for (int j = 0; j < ndim; j++)
                {
                    if (fmaxl[j] > fminl[j] && fmaxr[j] > fminr[j])
                    {
                        double sigl = Math.Max(TINY, Math.Pow(fmaxl[j] - fminl[j], 2.0 / 3.0));
                        double sigr = Math.Max(TINY, Math.Pow(fmaxr[j] - fminr[j], 2.0 / 3.0));
                        double sum = sigl + sigr;
                        if (sum <= sumb)
                        {
                            sumb = sum;
                            jb = j;
                            siglb = sigl;
                            sigrb = sigr;
                        }
                    }
                }
                if (jb == -1)
                {
                    jb = (ndim * iran) / 175000;
                }
                double rgl = regn[jb];
                double rgm = rmid[jb];
                double rgr = regn[ndim + jb];
                double fracl = Math.Abs((rgm - rgl) / (rgr - rgl));
                int nptl = (int)(MNPT + (npts - npre - 2 * MNPT) * fracl * siglb / (fracl * siglb + (1.0 - fracl) * sigrb));
                int nptr = npts - npre - nptl;
                double[] regn_temp = new double[2 * ndim];
                for (int j = 0; j < ndim; j++)
                {
                    regn_temp[j] = regn[j];
                    regn_temp[ndim + j] = regn[ndim + j];
                }
                regn_temp[ndim + jb] = rmid[jb];
                double avel = 0.0;
                double varl = 0.0;
                miser(func, regn_temp, nptl, dith, ref avel, ref varl);
                regn_temp[jb] = rmid[jb];
                regn_temp[ndim + jb] = regn[ndim + jb];
                miser(func, regn_temp, nptr, dith, ref ave, ref xvar);
                ave = fracl * avel + (1 - fracl) * ave;
                xvar = fracl * fracl * varl + (1 - fracl) * (1 - fracl) * xvar;
            }
        }

    }
}
 

2 代码格式

using System;

namespace Legalsoft.Truffer
{
    public class Miser
    {
        const int RANSEED = 5331;
        static Ran ran = new Ran(RANSEED);

        public Miser()
        {
        }

        public static void ranpt(double[] pt, double[] regn)
        {
            int n = pt.Length;
            for (int j = 0; j < n; j++)
            {
                pt[j] = regn[j] + (regn[n + j] - regn[j]) * ran.doub();
            }
        }

        /// <summary>
        /// Monte Carlo samples a user-supplied ndim-dimensional function func in 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 function is sampled a total of npts times, at locations
        /// determined by the method of recursive stratified sampling.The mean value
        /// of the function in the region is returned as ave; an estimate of the
        /// statistical uncertainty of ave(square of standard deviation) is returned
        /// as var.The input parameter dith should normally be set to zero, but can be
        /// set to(e.g.) 0.1 if func's active region falls on the boundary of a
        /// power-of-two subdivision of region.
        /// </summary>
        /// <param name="regn"></param>
        /// <param name="npts"></param>
        /// <param name="dith"></param>
        /// <param name="ave"></param>
        /// <param name="xvar"></param>
        public static void miser(RealValueFun func, double[] regn, int npts, double dith, ref double ave, ref double xvar)
        {
            const int MNPT = 15;
            const int MNBS = 60;
            const double PFAC = 0.1;
            const double TINY = 1.0e-30;
            const double BIG = 1.0e30;

            int iran = 0;
            int ndim = regn.Length / 2;
            double[] pt = new double[ndim];
            if (npts < MNBS)
            {
                double summ = 0.0;
                double summ2 = 0.0;
                for (int n = 0; n < npts; n++)
                {
                    ranpt(pt, regn);
                    double fval = func.funk(pt);
                    summ += fval;
                    summ2 += fval * fval;
                }
                ave = summ / npts;
                xvar = Math.Max(TINY, (summ2 - summ * summ / npts) / (npts * npts));
            }
            else
            {
                double[] rmid = new double[ndim];
                int npre = Math.Max((int)(npts * PFAC), (int)MNPT);
                double[] fmaxl = new double[ndim];
                double[] fmaxr = new double[ndim];
                double[] fminl = new double[ndim];
                double[] fminr = new double[ndim];
                for (int j = 0; j < ndim; j++)
                {
                    iran = (iran * 2661 + 36979) % 175000;
                    double s = Globals.SIGN(dith, (double)(iran - 87500));
                    rmid[j] = (0.5 + s) * regn[j] + (0.5 - s) * regn[ndim + j];
                    fminl[j] = fminr[j] = BIG;
                    fmaxl[j] = fmaxr[j] = (-BIG);
                }
                for (int n = 0; n < npre; n++)
                {
                    ranpt(pt, regn);
                    double fval = func.funk(pt);
                    for (int j = 0; j < ndim; j++)
                    {
                        if (pt[j] <= rmid[j])
                        {
                            fminl[j] = Math.Min(fminl[j], fval);
                            fmaxl[j] = Math.Max(fmaxl[j], fval);
                        }
                        else
                        {
                            fminr[j] = Math.Min(fminr[j], fval);
                            fmaxr[j] = Math.Max(fmaxr[j], fval);
                        }
                    }
                }
                double sumb = BIG;
                int jb = -1;
                double siglb = 1.0;
                double sigrb = 1.0;
                for (int j = 0; j < ndim; j++)
                {
                    if (fmaxl[j] > fminl[j] && fmaxr[j] > fminr[j])
                    {
                        double sigl = Math.Max(TINY, Math.Pow(fmaxl[j] - fminl[j], 2.0 / 3.0));
                        double sigr = Math.Max(TINY, Math.Pow(fmaxr[j] - fminr[j], 2.0 / 3.0));
                        double sum = sigl + sigr;
                        if (sum <= sumb)
                        {
                            sumb = sum;
                            jb = j;
                            siglb = sigl;
                            sigrb = sigr;
                        }
                    }
                }
                if (jb == -1)
                {
                    jb = (ndim * iran) / 175000;
                }
                double rgl = regn[jb];
                double rgm = rmid[jb];
                double rgr = regn[ndim + jb];
                double fracl = Math.Abs((rgm - rgl) / (rgr - rgl));
                int nptl = (int)(MNPT + (npts - npre - 2 * MNPT) * fracl * siglb / (fracl * siglb + (1.0 - fracl) * sigrb));
                int nptr = npts - npre - nptl;
                double[] regn_temp = new double[2 * ndim];
                for (int j = 0; j < ndim; j++)
                {
                    regn_temp[j] = regn[j];
                    regn_temp[ndim + j] = regn[ndim + j];
                }
                regn_temp[ndim + jb] = rmid[jb];
                double avel = 0.0;
                double varl = 0.0;
                miser(func, regn_temp, nptl, dith, ref avel, ref varl);
                regn_temp[jb] = rmid[jb];
                regn_temp[ndim + jb] = regn[ndim + jb];
                miser(func, regn_temp, nptr, dith, ref ave, ref xvar);
                ave = fracl * avel + (1 - fracl) * ave;
                xvar = fracl * fracl * varl + (1 - fracl) * (1 - fracl) * xvar;
            }
        }

    }
}

猜你喜欢

转载自blog.csdn.net/beijinghorn/article/details/132982875