Beispiel #1
0
    public static void cvt_sample(ref CVTHaltonData data, int dim_num, int n, int n_now, int sample, bool initialize,
                                  ref int seed, ref double[] r)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    CVT_SAMPLE returns sample points.
    //
    //  Discussion:
    //
    //    N sample points are to be taken from the unit box of dimension DIM_NUM.
    //
    //    These sample points are usually created by a pseudorandom process
    //    for which the points are essentially indexed by a quantity called
    //    SEED.  To get N sample points, we generate values with indices
    //    SEED through SEED+N-1.
    //
    //    It may not be practical to generate all the sample points in a
    //    single call.  For that reason, the routine allows the user to
    //    request a total of N points, but to require that only N_NOW be
    //    generated now (on this call).
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    23 June 2005
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int N, the number of Voronoi cells.
    //
    //    Input, int N_NOW, the number of sample points to be generated
    //    on this call.  N_NOW must be at least 1.
    //
    //    Input, int SAMPLE, specifies how the sampling is done.
    //    -1, 'RANDOM', using C++ RANDOM function;
    //     0, 'UNIFORM', using a simple uniform RNG;
    //     1, 'HALTON', from a Halton sequence;
    //     2, 'GRID', points from a grid;
    //     3, 'USER', call "user" routine.
    //
    //    Input, bool INITIALIZE, is TRUE if the pseudorandom process should be
    //    reinitialized.
    //
    //    Input/output, int *SEED, the random number seed.
    //
    //    Output, double R[DIM_NUM*N_NOW], the sample points.
    //
    {
        switch (n_now)
        {
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("CVT_SAMPLE - Fatal error!");
            Console.WriteLine("  N_NOW < 1.");
            return;

        default:
            int i;
            int j;
            switch (sample)
            {
            case -1:
            {
                /*
                 * if (initialize)
                 * {
                 * random_initialize(ref seed);
                 * }
                 */
                for (j = 0; j < n_now; j++)
                {
                    for (i = 0; i < dim_num; i++)
                    {
                        r[i + j * dim_num] = RNG.nextdouble();        //(double) random() / (double) RAND_MAX;
                    }
                }

                seed += n_now * dim_num;
                break;
            }

            case 0:
                r = UniformRNG.r8mat_uniform_01(dim_num, n_now, ref seed);
                break;

            case 1:
            {
                data.halton_seed = new int[dim_num];
                data.halton_leap = new int[dim_num];
                data.halton_base = new int[dim_num];

                int halton_step = seed;

                for (i = 0; i < dim_num; i++)
                {
                    data.halton_seed[i] = 0;
                }

                for (i = 0; i < dim_num; i++)
                {
                    data.halton_leap[i] = 1;
                }

                for (i = 0; i < dim_num; i++)
                {
                    data.halton_base[i] = Prime.prime(i + 1);
                }

                Halton.i4_to_halton_sequence(dim_num, n_now, halton_step, data.halton_seed,
                                             data.halton_leap, data.halton_base, ref r);

                seed += n_now;
                break;
            }

            case 2:
            {
                double exponent = 1.0 / dim_num;
                data.ngrid = (int)Math.Pow(n, exponent);
                int rank_max = (int)Math.Pow(data.ngrid, dim_num);
                data.tuple = new int[dim_num];

                if (rank_max < n)
                {
                    data.ngrid += 1;
                    rank_max    = (int)Math.Pow(data.ngrid, dim_num);
                }

                switch (initialize)
                {
                case true:
                    data.rank = -1;
                    BTuple.tuple_next_fast(ref data.tupledata, data.ngrid, dim_num, data.rank, ref data.tuple);
                    break;
                }

                data.rank = seed % rank_max;

                for (j = 0; j < n_now; j++)
                {
                    BTuple.tuple_next_fast(ref data.tupledata, data.ngrid, dim_num, data.rank, ref data.tuple);
                    data.rank += 1;
                    data.rank %= rank_max;
                    for (i = 0; i < dim_num; i++)
                    {
                        r[i + j * dim_num] = (2.0 * data.tuple[i] - 1) / (2.0 * data.ngrid);
                    }
                }

                seed += n_now;
                break;
            }

            case 3:
                user(dim_num, n_now, ref seed, ref r);
                break;

            default:
                Console.WriteLine("");
                Console.WriteLine("CVT_SAMPLE - Fatal error!");
                Console.WriteLine("  The value of SAMPLE = " + sample + " is illegal.");
                break;
            }

            break;
        }
    }
Beispiel #2
0
    public static void cvt(ref CVTHaltonData data, int dim_num, int n, int batch, int init, int sample, int sample_num,
                           int it_max, int it_fixed, ref int seed, ref double[] r, ref int it_num, ref double it_diff,
                           ref double energy)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    CVT computes a Centroidal Voronoi Tessellation.
    //
    //  Discussion:
    //
    //    This routine initializes the data, and carries out the
    //    CVT iteration.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    23 June 2005
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Qiang Du, Vance Faber, and Max Gunzburger,
    //    Centroidal Voronoi Tessellations: Applications and Algorithms,
    //    SIAM Review, Volume 41, 1999, pages 637-676.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int N, the number of Voronoi cells.
    //
    //    Input, int BATCH, sets the maximum number of sample points
    //    generated at one time.  It is inefficient to generate the sample
    //    points 1 at a time, but memory intensive to generate them all
    //    at once.  You might set BATCH to min ( SAMPLE_NUM, 10000 ), for instance.
    //    BATCH must be at least 1.
    //
    //    Input, int INIT, specifies how the points are to be initialized.
    //    -1, 'RANDOM', using C++ RANDOM function;
    //     0, 'UNIFORM', using a simple uniform RNG;
    //     1, 'HALTON', from a Halton sequence;
    //     2, 'GRID', points from a grid;
    //     3, 'USER', call "user" routine;
    //     4, points are already initialized on input.
    //
    //    Input, int SAMPLE, specifies how the sampling is done.
    //    -1, 'RANDOM', using C++ RANDOM function;
    //     0, 'UNIFORM', using a simple uniform RNG;
    //     1, 'HALTON', from a Halton sequence;
    //     2, 'GRID', points from a grid;
    //     3, 'USER', call "user" routine.
    //
    //    Input, int SAMPLE_NUM, the number of sample points.
    //
    //    Input, int IT_MAX, the maximum number of iterations.
    //
    //    Input, int IT_FIXED, the maximum number of iterations to take
    //    with a fixed set of sample points.
    //
    //    Input/output, int *SEED, the random number seed.
    //
    //    Input/output, double R[DIM_NUM*N], the approximate CVT points.
    //    If INIT = 4 on input, then it is assumed that these values have been
    //    initialized.  On output, the CVT iteration has been applied to improve
    //    the value of the points.
    //
    //    Output, int *IT_NUM, the number of iterations taken.  Generally,
    //    this will be equal to IT_MAX, unless the iteration tolerance was
    //    satisfied early.
    //
    //    Output, double *IT_DIFF, the L2 norm of the difference
    //    between the iterates.
    //
    //    Output, double *ENERGY,  the discrete "energy", divided
    //    by the number of sample points.
    //
    {
        const bool DEBUG = true;
        bool       initialize;
        int        seed_base = 0;

        switch (batch)
        {
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("CVT - Fatal error!");
            Console.WriteLine("  The input value BATCH < 1.");
            return;
        }

        switch (seed)
        {
        case <= 0:
            Console.WriteLine("");
            Console.WriteLine("CVT - Fatal error!");
            Console.WriteLine("  The input value SEED <= 0.");
            return;
        }

        switch (DEBUG)
        {
        case true:
            Console.WriteLine("");
            Console.WriteLine("  Step       SEED          L2-Change        Energy");
            Console.WriteLine("");
            break;
        }

        it_num  = 0;
        it_diff = 0.0;
        energy  = 0.0;
        int seed_init = seed;

        //
        //  Initialize the data, unless the user has already done that.
        //
        if (init != 4)
        {
            initialize = true;
            cvt_sample(ref data, dim_num, n, n, init, initialize, ref seed, ref r);
        }

        switch (DEBUG)
        {
        case true:
            Console.WriteLine("  "
                              + it_num.ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                              + seed_init.ToString(CultureInfo.InvariantCulture).PadLeft(12) + "");
            break;
        }

        //
        //  If the initialization and sampling steps use the same random number
        //  scheme, then the sampling scheme does not have to be initialized.
        //
        initialize = init != sample;

        //
        //  Carry out the iteration.
        //
        while (it_num < it_max)
        {
            switch (it_num % it_fixed)
            {
            //
            //  If it's time to update the seed, save its current value
            //  as the starting value for all iterations in this cycle.
            //  If it's not time to update the seed, restore it to its initial
            //  value for this cycle.
            //
            case 0:
                seed_base = seed;
                break;

            default:
                seed = seed_base;
                break;
            }

            it_num   += 1;
            seed_init = seed;

            cvt_iterate(ref data, dim_num, n, batch, sample, initialize, sample_num, ref seed,
                        ref r, ref it_diff, ref energy);

            initialize = false;

            switch (DEBUG)
            {
            case true:
                Console.WriteLine("  "
                                  + it_num.ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                                  + seed_init.ToString(CultureInfo.InvariantCulture).PadLeft(12) + "  "
                                  + it_diff.ToString(CultureInfo.InvariantCulture).PadLeft(14) + "  "
                                  + energy.ToString(CultureInfo.InvariantCulture).PadLeft(14) + "");
                break;
            }
        }
    }
Beispiel #3
0
    public static void cvt_iterate(ref CVTHaltonData data, int dim_num, int n, int batch, int sample, bool initialize,
                                   int sample_num, ref int seed, ref double[] r, ref double it_diff, ref double energy)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    CVT_ITERATE takes one step of the CVT iteration.
    //
    //  Discussion:
    //
    //    The routine is given a set of points, called "generators", which
    //    define a tessellation of the region into Voronoi cells.  Each point
    //    defines a cell.  Each cell, in turn, has a centroid, but it is
    //    unlikely that the centroid and the generator coincide.
    //
    //    Each time this CVT iteration is carried out, an attempt is made
    //    to modify the generators in such a way that they are closer and
    //    closer to being the centroids of the Voronoi cells they generate.
    //
    //    A large number of sample points are generated, and the nearest generator
    //    is determined.  A count is kept of how many points were nearest to each
    //    generator.  Once the sampling is completed, the location of all the
    //    generators is adjusted.  This step should decrease the discrepancy
    //    between the generators and the centroids.
    //
    //    The centroidal Voronoi tessellation minimizes the "energy",
    //    defined to be the integral, over the region, of the square of
    //    the distance between each point in the region and its nearest generator.
    //    The sampling technique supplies a discrete estimate of this
    //    energy.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    20 September 2004
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Qiang Du, Vance Faber, and Max Gunzburger,
    //    Centroidal Voronoi Tessellations: Applications and Algorithms,
    //    SIAM Review, Volume 41, 1999, pages 637-676.
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int N, the number of Voronoi cells.
    //
    //    Input, int BATCH, sets the maximum number of sample points
    //    generated at one time.  It is inefficient to generate the sample
    //    points 1 at a time, but memory intensive to generate them all
    //    at once.  You might set BATCH to min ( SAMPLE_NUM, 10000 ), for instance.
    //    BATCH must be at least 1.
    //
    //    Input, int SAMPLE, specifies how the sampling is done.
    //    -1, 'RANDOM', using C++ RANDOM function;
    //     0, 'UNIFORM', using a simple uniform RNG;
    //     1, 'HALTON', from a Halton sequence;
    //     2, 'GRID', points from a grid;
    //     3, 'USER', call "user" routine.
    //
    //    Input, bool INITIALIZE, is TRUE if the SEED must be reset to SEED_INIT
    //    before computation.  Also, the pseudorandom process may need to be
    //    reinitialized.
    //
    //    Input, int SAMPLE_NUM, the number of sample points.
    //
    //    Input/output, int *SEED, the random number seed.
    //
    //    Input/output, double R[DIM_NUM*N], the Voronoi
    //    cell generators.  On output, these have been modified
    //
    //    Output, double *IT_DIFF, the L2 norm of the difference
    //    between the iterates.
    //
    //    Output, double *ENERGY,  the discrete "energy", divided
    //    by the number of sample points.
    //
    {
        int i;
        int j;

        //
        //  Take each generator as the first sample point for its region.
        //  This can slightly slow the convergence, but it simplifies the
        //  algorithm by guaranteeing that no region is completely missed
        //  by the sampling.
        //
        energy = 0.0;
        double[] r2      = new double[dim_num * n];
        int[]    count   = new int[n];
        int[]    nearest = new int[sample_num];
        double[] s       = new double[dim_num * sample_num];

        for (j = 0; j < n; j++)
        {
            for (i = 0; i < dim_num; i++)
            {
                r2[i + j * dim_num] = r[i + j * dim_num];
            }
        }

        for (j = 0; j < n; j++)
        {
            count[j] = 1;
        }

        //
        //  Generate the sampling points S.
        //
        int have = 0;

        while (have < sample_num)
        {
            int get = Math.Min(sample_num - have, batch);

            cvt_sample(ref data, dim_num, sample_num, get, sample, initialize, ref seed, ref s);

            initialize = false;
            have      += get;
            //
            //  Find the index N of the nearest cell generator to each sample point S.
            //
            find_closest(dim_num, n, get, s, r, ref nearest);
            //
            //  Add S to the centroid associated with generator N.
            //
            for (j = 0; j < get; j++)
            {
                int j2 = nearest[j];
                for (i = 0; i < dim_num; i++)
                {
                    r2[i + j2 * dim_num] += s[i + j * dim_num];
                }

                for (i = 0; i < dim_num; i++)
                {
                    energy += Math.Pow(r[i + j2 * dim_num] - s[i + j * dim_num], 2);
                }

                count[j2] += 1;
            }
        }

        //
        //  Estimate the centroids.
        //
        for (j = 0; j < n; j++)
        {
            for (i = 0; i < dim_num; i++)
            {
                r2[i + j * dim_num] /= count[j];
            }
        }

        //
        //  Determine the sum of the distances between generators and centroids.
        //
        it_diff = 0.0;

        for (j = 0; j < n; j++)
        {
            double term = 0.0;
            for (i = 0; i < dim_num; i++)
            {
                term += (r2[i + j * dim_num] - r[i + j * dim_num])
                        * (r2[i + j * dim_num] - r[i + j * dim_num]);
            }

            it_diff += Math.Sqrt(term);
        }

        //
        //  Replace the generators by the centroids.
        //
        for (j = 0; j < n; j++)
        {
            for (i = 0; i < dim_num; i++)
            {
                r[i + j * dim_num] = r2[i + j * dim_num];
            }
        }

        //
        //  Normalize the discrete energy estimate.
        //
        energy /= sample_num;
    }
Beispiel #4
0
    public static double cvt_energy(ref CVTHaltonData data, int dim_num, int n, int batch, int sample, bool initialize,
                                    int sample_num, ref int seed, double[] r)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    CVT_ENERGY computes the CVT energy of a dataset.
    //
    //  Discussion:
    //
    //    For a given number of generators, a CVT is a minimizer (or at least
    //    a local minimizer) of the CVT energy.  During a CVT iteration,
    //    it should generally be the case that the CVT energy decreases from
    //    step to step, and that perturbations or adjustments of an
    //    approximate CVT will almost always have higher CVT energy.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    03 December 2004
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the spatial dimension.
    //
    //    Input, int N, the number of generators.
    //
    //    Input, int BATCH, the maximum number of sample points to generate
    //    at one time.
    //
    //    Input, int SAMPLE, specifies how the sampling is done.
    //    -1, 'RANDOM', using C++ RANDOM function;
    //     0, 'UNIFORM', using a simple uniform RNG;
    //     1, 'HALTON', from a Halton sequence;
    //     2, 'GRID', points from a grid;
    //     3, 'USER', call "user" routine.
    //
    //    Input, bool INITIALIZE, is TRUE if the pseudorandom process
    //    should be reinitialized.
    //
    //    Input, int SAMPLE_NUM, the number of sample points to use.
    //
    //    Input/output, int *SEED, a seed for the random number generator.
    //
    //    Input, double R[DIM_NUM*N], the coordinates of the points.
    //
    //    Output, double CVT_ENERGY, the estimated CVT energy.
    //
    {
        int[]    nearest = new int[batch];
        double[] s       = new double [dim_num * batch];

        int    have   = 0;
        double energy = 0.0;

        while (have < sample_num)
        {
            int get = Math.Min(sample_num - have, batch);

            cvt_sample(ref data, dim_num, sample_num, get, sample, initialize, ref seed, ref s);

            have += get;

            find_closest(dim_num, n, get, s, r, ref nearest);

            int j;
            for (j = 0; j < get; j++)
            {
                int i;
                for (i = 0; i < dim_num; i++)
                {
                    energy += (s[i + j * dim_num] - r[i + nearest[j] * dim_num])
                              * (s[i + j * dim_num] - r[i + nearest[j] * dim_num]);
                }
            }
        }

        energy /= sample_num;

        return(energy);
    }