Esempio n. 1
0
    public static void cvt(ref LCVData data, int m, int n, int sample_function_init,
                           int sample_function_cvt, int sample_num_cvt, int maxit, ref int seed,
                           ref double[] generator)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    CVT computes a Centroidal Voronoi Tessellation.
    //
    //  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.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    05 May 2003
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, the spatial dimension.
    //
    //    Input, int N, the number of Voronoi cells.
    //
    //    Input, int SAMPLE_FUNCTION_INIT, generator initialization function:
    //    -1, initializing function is RANDOM (C++ STDLIB library function);
    //    0, initializing function is UNIFORM;
    //    1, initializing function is HALTON;
    //    2, initializing function is GRID;
    //    3, initial values are set by the user.
    //
    //    Input, int SAMPLE_FUNCTION_CVT, region sampling function:
    //    -1, sampling function is RANDOM (C++ STDLIB library function);
    //    0, sampling function is UNIFORM;
    //    1, sampling function is HALTON;
    //    2, sampling function is GRID;
    //
    //    Input, int SAMPLE_NUM_CVT, the number of sample points.
    //
    //    Input, int MAXIT, the maximum number of correction iterations
    //    used in the Voronoi calculation.
    //
    //    Input/output, int *SEED, the random number seed.
    //
    //    Input/output, double GENERATOR[M*N], the Voronoi cell generators.
    //    On input, if SAMPLE_FUNCTION_INIT = 3, the user has initialized these.
    //    On output, the values have been through the CVT iteration.
    //
    {
        double     change_l2 = 0;
        int        it;
        const bool verbose = true;

        //
        //  Initialize the generators.
        //
        if (sample_function_init != 3)
        {
            const bool reset = true;

            Region.region_sampler(ref data.data, m, n, n, ref generator, sample_function_init, reset, ref seed);
        }

        switch (verbose)
        {
        //
        //  Carry out the iteration.
        //
        case true:
            Console.WriteLine("");
            Console.WriteLine("  STEP  L2 Change");
            Console.WriteLine("");
            break;
        }

        for (it = 1; it <= maxit; it++)
        {
            cvt_iteration(ref data, m, n, ref generator, sample_num_cvt, sample_function_cvt,
                          ref seed, ref change_l2);

            switch (verbose)
            {
            case true:
                Console.WriteLine(it.ToString(CultureInfo.InvariantCulture).PadLeft(4) + "  "
                                  + change_l2.ToString(CultureInfo.InvariantCulture).PadLeft(12) + "");
                break;
            }
        }
    }
Esempio n. 2
0
    public static void cvt_iteration(ref LCVData data, int m, int n, ref double[] generator, int sample_num_cvt,
                                     int sample_function_cvt, ref int seed, ref double change_l2)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    CVT_ITERATION 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.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    05 May 2003
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int M, the spatial dimension.
    //
    //    Input, int N, the number of Voronoi cells.
    //
    //    Input/output, double GENERATOR[M*N], the Voronoi
    //    cell generators.  On output, these have been modified
    //
    //    Input, int SAMPLE_NUM_CVT, the number of sample points.
    //
    //    Input, int SAMPLE_FUNCTION_CVT, region sampling function:
    //    -1, sampling function is RANDOM (C++ STDLIB library function);
    //    0, sampling function is UNIFORM;
    //    1, sampling function is HALTON;
    //    2, sampling function is GRID;
    //
    //    Input/output, int *SEED, the random number seed.
    //
    //    Output, double *CHANGE_L2, the L2 norm of the difference between
    //    the input and output data.
    //
    {
        int i;
        int j;
        int k;

        //
        double[] generator2 = new double[m * n];
        for (k = 0; k < m * n; k++)
        {
            generator2[k] = 0.0;
        }

        int[] count = new int[n];
        for (i = 0; i < n; i++)
        {
            count[i] = 0;
        }

        double[] x = new double[m];

        bool reset = true;

        seed = sample_function_cvt switch
        {
            //
            //  If we are using the C++ random number generator, then initialize using the current seed.
            //  (Currently, if we are using RANDOM for both the initializing and sampling, we make this
            //  call twice, which is inefficient and possibly misleading.)
            //
            -1 => entropyRNG.RNG.nextint(),
            _ => seed
        };

        for (j = 0; j < sample_num_cvt; j++)
        {
            //
            //  Generate a sampling point X.
            //
            Region.region_sampler(ref data.data, m, 1, sample_num_cvt, ref x, sample_function_cvt, reset,
                                  ref seed);

            reset = false;
            //
            //  Find the nearest cell generator.
            //
            int nearest = find_closest(m, n, x, generator);
            //
            //  Add X to the averaging data for GENERATOR(*,NEAREST).
            //
            for (i = 0; i < m; i++)
            {
                generator2[nearest * m + i] += x[i];
            }

            count[nearest] += 1;
        }

        //
        //  Compute the new generators.
        //
        for (j = 0; j < n; j++)
        {
            if (count[j] == 0)
            {
                continue;
            }

            for (i = 0; i < m; i++)
            {
                generator2[j * m + i] /= count[j];
            }
        }

        //
        //  Determine the change.
        //
        change_l2 = 0.0;
        for (k = 0; k < m * n; k++)
        {
            change_l2 += Math.Pow(generator2[k] - generator[k], 2);
        }

        change_l2 = Math.Sqrt(change_l2);
        //
        //  Update.
        //
        for (k = 0; k < m * n; k++)
        {
            generator[k] = generator2[k];
        }
    }