Ejemplo n.º 1
0
    private static void test01()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST01 tests ADJ_SET.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    04 January 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        const int NODE_NUM = 10;
        const int ADJ_MAX  = NODE_NUM * (NODE_NUM - 1);

        int[] adj     = new int[ADJ_MAX];
        int   adj_num = 0;

        int[] adj_row = new int[NODE_NUM + 1];
        int   k;
        int   seed = 123456789;

        Console.WriteLine("");
        Console.WriteLine("TEST01");
        Console.WriteLine("  ADJ_SET sets up an adjacency matrix incrementally.");

        int n_calls = UniformRNG.i4_uniform(1, ADJ_MAX, ref seed);

        AdjacencyMatrix.adj_set(NODE_NUM, ADJ_MAX, ref adj_num, ref adj_row, ref adj, -1, -1);

        Console.WriteLine("");
        Console.WriteLine("  Creating and recording adjacency information:");
        Console.WriteLine("");

        for (k = 1; k <= n_calls; k++)
        {
            int i = UniformRNG.i4_uniform(1, NODE_NUM, ref seed);
            int j = UniformRNG.i4_uniform(1, NODE_NUM, ref seed);

            Console.WriteLine("  " + i.ToString().PadLeft(8)
                              + "  " + j.ToString().PadLeft(8) + "");

            AdjacencyMatrix.adj_set(NODE_NUM, ADJ_MAX, ref adj_num, ref adj_row, ref adj, i, j);
        }

        AdjacencyMatrix.adj_print(NODE_NUM, adj_num, adj_row, adj,
                                  "  Random adjacency matrix:");

        AdjacencyMatrix.adj_show(NODE_NUM, adj_num, adj_row, adj);
    }
Ejemplo n.º 2
0
    public static int[] perm_uniform(int n, int base_, ref int seed)
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    PERM_UNIFORM selects a random permutation of N objects.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    31 October 2008
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Reference:
    //
    //    Albert Nijenhuis, Herbert Wilf,
    //    Combinatorial Algorithms,
    //    Academic Press, 1978, second edition,
    //    ISBN 0-12-519260-6.
    //
    //  Parameters:
    //
    //    Input, int N, the number of objects to be permuted.
    //
    //    Input, int BASE, is 0 for a 0-based permutation and 1 for
    //    a 1-based permutation.
    //
    //    Input/output, int *SEED, a seed for the random number generator.
    //
    //    Output, int PERM_UNIFORM[N], a permutation of (BASE, BASE+1, ..., BASE+N-1).
    //
    {
        int[] p = new int[n];

        for (int i = 0; i < n; i++)
        {
            p[i] = i + base_;
        }

        for (int i = 0; i < n; i++)
        {
            int j = UniformRNG.i4_uniform(i, n - 1, ref seed);
            (p[i], p[j]) = (p[j], p[i]);
        }

        return(p);
    }
Ejemplo n.º 3
0
    private static void test055( )
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST055 tests OR on long long ints.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    12 May 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int seed = 123456789;

        Console.WriteLine();
        Console.WriteLine("TEST055");
        Console.WriteLine("  The function ^ computes the bitwise exclusive OR");
        Console.WriteLine("  of two LONG LONG INT's.");
        Console.WriteLine();
        Console.WriteLine("       I       J     I^J");
        Console.WriteLine();

        for (int test = 1; test <= 10; test++)
        {
            long i = UniformRNG.i4_uniform(0, 100, ref seed);
            long j = UniformRNG.i4_uniform(0, 100, ref seed);
            long k = i ^ j;

            string cout = "  ";
            string t    = i.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  ";
            cout += t;
            t     = j.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  ";
            cout += t;
            t     = k.ToString(CultureInfo.InvariantCulture).PadLeft(6);
            cout += t;
            Console.WriteLine(cout);
        }
    }
Ejemplo n.º 4
0
    private static void or_test( )
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    OR_TEST tests OR.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    23 January 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int seed = 123456789;

        Console.WriteLine();
        Console.WriteLine("OR_TEST");
        Console.WriteLine("  The function ^ computes the bitwise exclusive OR");
        Console.WriteLine("  of two integers.");
        Console.WriteLine();
        Console.WriteLine("       I       J     I^J");
        Console.WriteLine();

        for (int test = 1; test <= 10; test++)
        {
            int i = UniformRNG.i4_uniform(0, 100, ref seed);
            int j = UniformRNG.i4_uniform(0, 100, ref seed);
            int k = i ^ j;

            string cout = "  ";
            string t    = i.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  ";
            cout += t;
            t     = j.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  ";
            cout += t;
            t     = k.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  ";
            cout += t;
            Console.WriteLine(cout);
        }
    }
Ejemplo n.º 5
0
    private static void i4_bit_hi1_test( )
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    I4_BIT_HI1_TEST tests I4_BIT_HI1.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    23 January 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int seed = 123456789;

        Console.WriteLine();
        Console.WriteLine("I4_BIT_HI1_TEST");
        Console.WriteLine("  I4_BIT_HI1 returns the location of the high bit in an integer.");
        Console.WriteLine();
        Console.WriteLine("       I  I4_BIT_HI1(I)");
        Console.WriteLine();

        for (int test = 1; test <= 10; test++)
        {
            int i = UniformRNG.i4_uniform(0, 100, ref seed);
            int j = SobolSampler.i4_bit_hi1(i);

            string cout = "  ";
            string t    = i.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  ";
            cout += t;
            t     = j.ToString(CultureInfo.InvariantCulture).PadLeft(6);
            cout += t;
            Console.WriteLine(cout);
        }
    }
Ejemplo n.º 6
0
    private static void i8_bit_lo0_test( )
    //****************************************************************************80
    //
    //  Purpose:
    //
    //    I8_BIT_LO0_TEST tests I8_BIT_LO0.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    12 May 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int seed = 123456789;

        Console.WriteLine();
        Console.WriteLine("I8_BIT_LO0_TEST");
        Console.WriteLine("  I8_BIT_LO0 returns the location of the low zero bit");
        Console.WriteLine("  in an integer.");
        Console.WriteLine();
        Console.WriteLine("       I  I8_BIT_LO0(I)");
        Console.WriteLine();

        for (int test = 1; test <= 10; test++)
        {
            long i = UniformRNG.i4_uniform(0, 100, ref seed);
            int  j = SobolSampler.i8_bit_lo0(i);

            string cout = "  ";
            string t    = i.ToString(CultureInfo.InvariantCulture).PadLeft(6) + "  ";
            t    += j.ToString(CultureInfo.InvariantCulture).PadLeft(6);
            cout += t;
            Console.WriteLine(cout);
        }
    }
Ejemplo n.º 7
0
    public static void triangulation_search_delaunay(int node_num, double[] node_xy, int triangle_order,
                                                     int triangle_num, int[] triangle_node, int[] triangle_neighbor,
                                                     double[] p, ref int triangle, ref int edge, int pIndex = 0)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TRIANGULATION_SEARCH_DELAUNAY searches a triangulation for a point.
    //
    //  Discussion:
    //
    //    The algorithm "walks" from one triangle to its neighboring triangle,
    //    and so on, until a triangle is found containing point P, or P is found
    //    to be outside the convex hull.
    //
    //    The algorithm computes the barycentric coordinates of the point with
    //    respect to the current triangle.  If all three quantities are positive,
    //    the point is contained in the triangle.  If the I-th coordinate is
    //    negative, then (X,Y) lies on the far side of edge I, which is opposite
    //    from vertex I.  This gives a hint as to where to search next.
    //
    //    For a Delaunay triangulation, the search is guaranteed to terminate.
    //    For other triangulations, a cycle may occur.
    //
    //    Note the surprising fact that, even for a Delaunay triangulation of
    //    a set of nodes, the nearest point to (X,Y) need not be one of the
    //    vertices of the triangle containing (X,Y).
    //
    //    The code can be called for triangulations of any order, but only
    //    the first three nodes in each triangle are considered.  Thus, if
    //    higher order triangles are used, and the extra nodes are intended
    //    to give the triangle a polygonal shape, these will have no effect,
    //    and the results obtained here might be misleading.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    27 September 2006
    //
    //  Author:
    //
    //    Barry Joe,
    //    Department of Computing Science,
    //    University of Alberta,
    //    Edmonton, Alberta, Canada  T6G 2H1
    //
    //  Reference:
    //
    //    Barry Joe,
    //    GEOMPACK - a software package for the generation of meshes
    //    using geometric algorithms,
    //    Advances in Engineering Software,
    //    Volume 13, pages 325-331, 1991.
    //
    //  Parameters:
    //
    //    Input, int NODE_NUM, the number of nodes.
    //
    //    Input, double NODE_XY[2*NODE_NUM], the coordinates of the nodes.
    //
    //    Input, int TRIANGLE_ORDER, the order of the triangles.
    //
    //    Input, int TRIANGLE_NUM, the number of triangles in the triangulation.
    //
    //    Input, int TRIANGLE_NODE[TRIANGLE_ORDER*TRIANGLE_NUM],
    //    the nodes of each triangle.
    //
    //    Input, int TRIANGLE_NEIGHBOR[3*TRIANGLE_NUM], the triangle neighbor list.
    //
    //    Input, double P[2], the coordinates of a point.
    //
    //    Output, int *TRIANGLE, the index of the triangle where the search ended.
    //    If a cycle occurred, then TRIANGLE = -1.
    //
    //    Output, int *EDGE, indicates the position of the point (X,Y) in
    //    triangle TRIANGLE:
    //    0, the interior or boundary of the triangle;
    //    -1, outside the convex hull of the triangulation, past edge 1;
    //    -2, outside the convex hull of the triangulation, past edge 2;
    //    -3, outside the convex hull of the triangulation, past edge 3.
    //
    {
        int count = 0;

        edge = 0;

        int seed = RNG.nextint();

        triangle = UniformRNG.i4_uniform(1, triangle_num, ref seed);

        for (;;)
        {
            count += 1;

            if (triangle_num < count)
            {
                Console.WriteLine();
                Console.WriteLine("TRIANGULATION_SEARCH_DELAUNAY - Fatal error!");
                Console.WriteLine("  The algorithm seems to be cycling.");
                Console.WriteLine("  Current triangle is " + triangle + "");
                triangle = -1;
                edge     = -1;
                return;
            }

            //
            //  Get the vertices of triangle TRIANGLE.
            //
            int a = triangle_node[0 + (triangle - 1) * triangle_order] - 1;
            int b = triangle_node[1 + (triangle - 1) * triangle_order] - 1;
            int c = triangle_node[2 + (triangle - 1) * triangle_order] - 1;
            //
            //  Using vertex C as a base, compute the distances to vertices A and B,
            //  and the point (X,Y).
            //
            double dxa = node_xy[0 + a * 2] - node_xy[0 + c * 2];
            double dya = node_xy[1 + a * 2] - node_xy[1 + c * 2];

            double dxb = node_xy[0 + b * 2] - node_xy[0 + c * 2];
            double dyb = node_xy[1 + b * 2] - node_xy[1 + c * 2];

            double dxp = p[0 + pIndex] - node_xy[0 + c * 2];
            double dyp = p[1 + pIndex] - node_xy[1 + c * 2];

            double det = dxa * dyb - dya * dxb;
            //
            //  Compute the barycentric coordinates of the point (X,Y) with respect
            //  to this triangle.
            //
            double alpha = (dxp * dyb - dyp * dxb) / det;
            double beta  = (dxa * dyp - dya * dxp) / det;
            double gamma = 1.0 - alpha - beta;
            //
            //  If the barycentric coordinates are all positive, then the point
            //  is inside the triangle and we're done.
            //
            if (0.0 <= alpha &&
                0.0 <= beta &&
                0.0 <= gamma)
            {
                break;
            }

            switch (alpha)
            {
            //
            //  At least one barycentric coordinate is negative.
            //
            //  If there is a negative barycentric coordinate for which there exists
            //  an opposing triangle neighbor closer to the point, move to that triangle.
            //
            //  (Two coordinates could be negative, in which case we could go for the
            //  most negative one, or the most negative one normalized by the actual
            //  distance it represents).
            //
            case < 0.0 when 0 <= triangle_neighbor[1 + (triangle - 1) * 3]:
                triangle = triangle_neighbor[1 + (triangle - 1) * 3];
                continue;
            }

            switch (beta)
            {
            case < 0.0 when 0 <= triangle_neighbor[2 + (triangle - 1) * 3]:
                triangle = triangle_neighbor[2 + (triangle - 1) * 3];
                continue;
            }
            switch (gamma)
            {
            case < 0.0 when 0 <= triangle_neighbor[0 + (triangle - 1) * 3]:
                triangle = triangle_neighbor[0 + (triangle - 1) * 3];
                continue;
            }

            //
            //  All negative barycentric coordinates correspond to vertices opposite
            //  sides on the convex hull.
            //
            //  Note the edge and exit.
            //
            if (alpha < 0.0)
            {
                edge = -2;
                break;
            }

            if (beta < 0.0)
            {
                edge = -3;
                break;
            }
            if (gamma < 0.0)
            {
                edge = -1;
                break;
            }
            Console.WriteLine("");
            Console.WriteLine("TRIANGULATION_SEARCH - Fatal error!");
            Console.WriteLine("  The algorithm seems to have reached a dead end");
            Console.WriteLine("  after " + count + " steps.");
            triangle = -1;
            edge     = -1;
            return;
        }
    }
Ejemplo n.º 8
0
    private static void test06()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST06 tests LEVEL_SET;
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    05 January 2007
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        int adj_num = 0;
        int i;
        int level_num = 0;
        int node_num  = 0;
        int seed      = 123456789;

        Console.WriteLine("");
        Console.WriteLine("TEST06");
        Console.WriteLine("  LEVEL_SET computes the level sets of a graph,");
        Console.WriteLine("  given a root node (which defines level 1).");

        Burkardt.Graph.Adjacency.graph_01_size(ref node_num, ref adj_num);

        int[] adj_row = new int[node_num + 1];
        int[] adj     = new int[adj_num];

        Burkardt.Graph.Adjacency.graph_01_adj(node_num, adj_num, ref adj_row, ref adj);

        AdjacencyMatrix.adj_print(node_num, adj_num, adj_row, adj, "  Adjacency matrix:");

        AdjacencyMatrix.adj_show(node_num, adj_num, adj_row, adj);
        //
        //  Choose different roots.
        //
        int[] level     = new int[node_num];
        int[] level_row = new int[node_num + 1];
        int[] mask      = new int[node_num];

        for (i = 1; i <= 3; i++)
        {
            int root = UniformRNG.i4_uniform(1, node_num, ref seed);

            int j;
            for (j = 0; j < node_num; j++)
            {
                mask[j] = 1;
            }

            Burkardt.Graph.GenRCM.level_set(root, adj_num, adj_row, adj, ref mask, ref level_num,
                                            ref level_row, ref level, node_num);

            Burkardt.Graph.GenRCM.level_set_print(node_num, level_num, level_row, level);
        }
    }
Ejemplo n.º 9
0
    public static double[] cluster_initialize_3(int dim_num, int point_num, int cluster_num,
                                                double[] point, ref int seed)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //   CLUSTER_INITIALIZE_3 initializes the cluster centers to random values.
    //
    //  Discussion:
    //
    //    In this case, each point is randomly assigned to a cluster, and
    //    the cluster centers are then computed as the centroids of the points
    //    in the cluster.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    08 October 2011
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the number of spatial dimensions.
    //
    //    Input, int POINT_NUM, the number of points.
    //
    //    Input, int CLUSTER_NUM, the number of clusters.
    //
    //    Input, double POINT[DIM_NUM*POINT_NUM], the coordinates
    //    of the points.
    //
    //    Input/output, int SEED, a seed for the random
    //    number generator.
    //
    //    Output, double CLUSTER_INITIALIZE_3[DIM_NUM*CLUSTER_NUM],
    //    the coordinates of the cluster centers.
    //
    {
        int i;
        int j;
        int k;

        //
        //  Assign one point to each cluster center.
        //
        double[] cluster_center = new double[dim_num * cluster_num];

        for (k = 0; k < cluster_num; k++)
        {
            for (i = 0; i < dim_num; i++)
            {
                cluster_center[i + k * dim_num] = point[i + k * dim_num];
            }
        }

        int[] cluster_population = new int[cluster_num];

        for (k = 0; k < cluster_num; k++)
        {
            cluster_population[k] = 1;
        }

        //
        //  The rest of the points get assigned randomly.
        //
        for (j = cluster_num; j < point_num; j++)
        {
            k = UniformRNG.i4_uniform(1, cluster_num, ref seed);
            for (i = 0; i < dim_num; i++)
            {
                cluster_center[i + k * dim_num] += point[i + j * dim_num];
            }

            cluster_population[k] += 1;
        }

        //
        //  Now average the points to get the centroid.
        //
        for (k = 0; k < cluster_num; k++)
        {
            if (cluster_population[k] == 0)
            {
                continue;
            }

            for (i = 0; i < dim_num; i++)
            {
                cluster_center[i + k * dim_num] /= cluster_population[k];
            }
        }

        return(cluster_center);
    }
Ejemplo n.º 10
0
    private static void test180()

    //****************************************************************************80
    //
    //  Purpose:
    //
    //    TEST180 tests SORT_HEAP_EXTERNAL.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    29 April 2003
    //
    //  Author:
    //
    //    John Burkardt
    //
    {
        const int N = 20;

        int[] a = new int[N];

        Console.WriteLine("");
        Console.WriteLine("TEST180");
        Console.WriteLine("  SORT_HEAP_EXTERNAL sorts objects externally.");

        int indx = 0;
        int i;
        int j    = 0;
        int isgn = 0;
        int seed = 123456789;

        for (i = 0; i < N; i++)
        {
            a[i] = UniformRNG.i4_uniform(1, N, ref seed);
        }

        typeMethods.i4vec_print(N, a, "  Unsorted array:");
        //
        //  Call the sort routine over and over.
        //
        SortHeapExternalData data = new();

        for (;;)
        {
            Sort.sort_heap_external(ref data, N, ref indx, ref i, ref j, isgn);
            //
            //  If the return value of INDX is negative, we're asked to compare
            //  array elements I and J;

            i %= a.Length;
            j %= a.Length;

            if (indx < 0)
            {
                if (a[i] <= a[j])
                {
                    isgn = -1;
                }
                else
                {
                    isgn = 1;
                }
            }
            //
            //  ...and if the return value of INDX is positive, we're asked to switch
            //  array elements I and J;
            //
            else if (0 < indx)
            {
                typeMethods.i4_swap(ref a[i], ref a[j]);
                //
                //  ...and if the return value of INDX is 0, we're done.
                //
            }
            else
            {
                break;
            }
        }

        typeMethods.i4vec_print(N, a, "  Sorted array:");
    }
Ejemplo n.º 11
0
    public static void hmeans_w_02(int dim_num, int point_num, int cluster_num, int it_max,
                                   ref int it_num, double[] point, double[] weight, int[] cluster,
                                   double[] cluster_center, int[] cluster_population, double[] cluster_energy,
                                   ref int seed)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //   HMEANS_W_02 applies the weighted H-Means algorithm.
    //
    //  Discussion:
    //
    //    The input data for the weight H-Means problem includes:
    //    * a set of N data points X in M dimensions,
    //    * a set of N nonnegative weights W,
    //    * a desired number of clusters K.
    //    * an initial set of cluster centers Z,
    //    * an (optional) initial set of cluster assignments.
    //
    //    The goal is to determine K points Z, called cluster centers, and
    //    to assign each point X(I) to some cluster Z(J), so that we minimize
    //    the weighted standard deviation of the distance of each data point
    //    to the center of its cluster.  Writing J = CLUSTER(I) to
    //    indicate the index of the nearest cluster center Z(J) to the
    //    point X(I), the quantity we are trying to minimize is the sum
    //    of the weighted cluster energies E(J), where:
    //
    //      E(J) = Sum ( 1 <= I <= N ) W(I) * || X(I) - Z(J) ||^2
    //
    //    Here, we assume that we are using the Euclidean norm, so that
    //
    //      || X(I) - Z(J) ||^2 = Sum ( 1 <= K <= M )
    //        ( X(I)(K) - Z(J)(K) )^2
    //
    //    In this notation, X(I)(K) is the K-th spatial component of the
    //    I-th data point.
    //
    //    Note that this routine should give the same results as HMEANS_02
    //    in any case in which all the entries of the WEIGHT vector are equal.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    09 October 2011
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the number of spatial dimensions.
    //
    //    Input, int POINT_NUM, the number of points.
    //
    //    Input, int CLUSTER_NUM, the number of clusters.
    //
    //    Input, int IT_MAX, the maximum number of iterations.
    //
    //    Output, int &IT_NUM, the number of iterations taken.
    //
    //    Input, double POINT[DIM_NUM*POINT_NUM], the coordinates
    //    of the points.
    //
    //    Input, double WEIGHT[POINT_NUM], the weights
    //    assigned to the data points.  These must be nonnegative, and
    //    at least one must be strictly positive.
    //
    //    Input/output, int CLUSTER[POINT_NUM].  On input, the user
    //    may specify an initial cluster for each point, or leave all entrie of
    //    CLUSTER set to 0.  On output, CLUSTER contains the index of the
    //    cluster to which each data point belongs.
    //
    //    Input/output, double CLUSTER_CENTER[DIM_NUM*CLUSTER_NUM],
    //    the coordinates of the cluster centers.
    //
    //    Output, int CLUSTER_POPULATION[CLUSTER_NUM], the number of
    //    points assigned to each cluster.
    //
    //    Output, double CLUSTER_ENERGY[CLUSTER_NUM], the energy of
    //    the clusters.
    //
    //    Input/output, int *SEED, a seed for the random
    //    number generator.
    //
    {
        int    i;
        int    j;
        int    k;
        double point_energy;
        double point_energy_min;

        switch (cluster_num)
        {
        //
        //  Data checks.
        //
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_W_02 - Fatal error!");
            Console.WriteLine("  CLUSTER_NUM < 1.");
            return;
        }

        switch (dim_num)
        {
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_W_02 - Fatal error!");
            Console.WriteLine("  DIM_NUM < 1.");
            return;
        }

        switch (point_num)
        {
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_W_02 - Fatal error!");
            Console.WriteLine("  POINT_NUM < 1.");
            return;
        }

        switch (it_max)
        {
        case < 0:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_W_02 - Fatal error!");
            Console.WriteLine("  IT_MAX < 0.");
            return;
        }

        if (typeMethods.r8vec_any_negative(point_num, weight))
        {
            Console.WriteLine("");
            Console.WriteLine("HMEANS_W_02 - Fatal error!");
            Console.WriteLine("  Some weight entry is negative.");
            return;
        }

        if (typeMethods.r8vec_all_nonpositive(point_num, weight))
        {
            Console.WriteLine("");
            Console.WriteLine("HMEANS_W_02 - Fatal error!");
            Console.WriteLine("  No weight entry is positive.");
            return;
        }

        //
        //  On input, legal entries in CLUSTER are preserved, but
        //  otherwise, each point is assigned to its nearest cluster.
        //
        for (j = 0; j < point_num; j++)
        {
            if (cluster[j] >= 0 && cluster_num > cluster[j])
            {
                continue;
            }

            point_energy_min = typeMethods.r8_huge();
            for (k = 0; k < cluster_num; k++)
            {
                point_energy = 0.0;
                for (i = 0; i < dim_num; i++)
                {
                    point_energy += Math.Pow(point[i + j * dim_num] - cluster_center[i + k * dim_num], 2);
                }

                if (!(point_energy < point_energy_min))
                {
                    continue;
                }

                point_energy_min = point_energy;
                cluster[j]       = k;
            }
        }

        it_num = 0;

        for (;;)
        {
            //
            //  Given centers, assign points to nearest center.
            //
            typeMethods.i4vec_zero(cluster_num, ref cluster_population);
            typeMethods.r8vec_zero(cluster_num, ref cluster_energy);
            double[] cluster_weight = typeMethods.r8vec_zero_new(cluster_num);

            int swap = 0;

            for (j = 0; j < point_num; j++)
            {
                point_energy_min = typeMethods.r8_huge();
                k = cluster[j];

                int k2;
                for (k2 = 0; k2 < cluster_num; k2++)
                {
                    point_energy = 0.0;
                    for (i = 0; i < dim_num; i++)
                    {
                        point_energy += Math.Pow(point[i + j * dim_num] - cluster_center[i + k2 * dim_num], 2);
                    }

                    if (!(point_energy < point_energy_min))
                    {
                        continue;
                    }

                    point_energy_min = point_energy;
                    cluster[j]       = k2;
                }

                if (k != cluster[j])
                {
                    swap += 1;
                }

                k = cluster[j];
                cluster_energy[k]     += weight[j] * point_energy_min;
                cluster_population[k] += 1;
                cluster_weight[k]     += weight[j];
            }

            if (0 < it_num)
            {
                if (swap == 0)
                {
                    break;
                }
            }

            if (it_max <= it_num)
            {
                break;
            }

            it_num += 1;
            //
            //  Given points in cluster, replace center by weighted centroid.
            //
            typeMethods.r8vec_zero(dim_num * cluster_num, ref cluster_center);

            for (j = 0; j < point_num; j++)
            {
                k = cluster[j];
                for (i = 0; i < dim_num; i++)
                {
                    cluster_center[i + k * dim_num] += weight[j] * point[i + j * dim_num];
                }
            }

            for (k = 0; k < cluster_num; k++)
            {
                if (cluster_weight[k] != 0.0)
                {
                    for (i = 0; i < dim_num; i++)
                    {
                        cluster_center[i + k * dim_num] /= cluster_weight[k];
                    }
                }
                else
                {
                    j = UniformRNG.i4_uniform(0, point_num - 1, ref seed);
                    for (i = 0; i < dim_num; i++)
                    {
                        cluster_center[i + k * dim_num] = point[i + j * dim_num];
                    }
                }
            }
        }

        //
        //  Compute the energy based on the final value of the cluster centers.
        //
        typeMethods.r8vec_zero(cluster_num, ref cluster_energy);

        for (j = 0; j < point_num; j++)
        {
            k = cluster[j];

            point_energy = 0.0;
            for (i = 0; i < dim_num; i++)
            {
                point_energy += Math.Pow(point[i + j * dim_num] - cluster_center[i + k * dim_num], 2);
            }

            cluster_energy[k] += weight[j] * point_energy;
        }
    }
Ejemplo n.º 12
0
    public static void hmeans_02(int dim_num, int point_num, int cluster_num, int it_max,
                                 ref int it_num, double[] point, int[] cluster, double[] cluster_center,
                                 int[] cluster_population, double[] cluster_energy, ref int seed)

    //****************************************************************************80
    //
    //  Purpose:
    //
    //   HMEANS_02 applies the H-Means algorithm.
    //
    //  Discussion:
    //
    //    This is a simple routine to group a set of points into K clusters,
    //    each with a center point, in such a way that the total cluster
    //    energy is minimized.  The total cluster energy is the sum of the
    //    squares of the distances of each point to the center of its cluster.
    //
    //    The algorithm begins with an initial estimate for the cluster centers:
    //
    //    1. The points are assigned to the nearest cluster centers.
    //
    //    2. The iteration exit ( 1 );s if the total energy has not changed
    //        significantly, or we have reached the maximum number of iterations.
    //
    //    3. Each cluster center is replaced by the centroid of the points
    //       in the cluster.
    //
    //    4. Return to step 1.
    //
    //    The algorithm may fail to find the best solution.
    //
    //  Licensing:
    //
    //    This code is distributed under the GNU LGPL license.
    //
    //  Modified:
    //
    //    08 October 2011
    //
    //  Author:
    //
    //    John Burkardt
    //
    //  Parameters:
    //
    //    Input, int DIM_NUM, the number of spatial dimensions.
    //
    //    Input, int POINT_NUM, the number of points.
    //
    //    Input, int CLUSTER_NUM, the number of clusters.
    //
    //    Input, int IT_MAX, the maximum number of iterations.
    //
    //    Output, int IT_NUM, the number of iterations taken.
    //
    //    Input, double POINT[DIM_NUM*POINT_NUM], the coordinates
    //    of the points.
    //
    //    Input/output, int CLUSTER[POINT_NUM].  On input, the user
    //    may specify an initial cluster for each point, or leave all entrie of
    //    CLUSTER set to 0.  On output, CLUSTER contains the index of the
    //    cluster to which each data point belongs.
    //
    //    Input/output, double CLUSTER_CENTER[DIM_NUM*CLUSTER_NUM],
    //    the coordinates of the cluster centers.
    //
    //    Output, int CLUSTER_POPULATION[CLUSTER_NUM], the number of
    //    points assigned to each cluster.
    //
    //    Output, double CLUSTER_ENERGY[CLUSTER_NUM], the energy of
    //    the clusters.
    //
    //    Input/output, int *SEED, a seed for the random
    //    number generator.
    //
    {
        const bool debug = false;
        int        i;
        int        j;
        int        k;
        double     point_energy;
        double     point_energy_min;

        switch (cluster_num)
        {
        //
        //  Data checks.
        //
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_02 - Fatal error!");
            Console.WriteLine("  CLUSTER_NUM < 1.");
            return;
        }

        switch (dim_num)
        {
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_02 - Fatal error!");
            Console.WriteLine("  DIM_NUM < 1.");
            return;
        }

        switch (point_num)
        {
        case < 1:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_02 - Fatal error!");
            Console.WriteLine("  POINT_NUM < 1.");
            return;
        }

        switch (it_max)
        {
        case < 0:
            Console.WriteLine("");
            Console.WriteLine("HMEANS_02 - Fatal error!");
            Console.WriteLine("  IT_MAX < 0.");
            return;
        }

        //
        //  On input, legal entries in CLUSTER are preserved, but
        //  otherwise, each point is assigned to its nearest cluster.
        //
        for (j = 0; j < point_num; j++)
        {
            if (cluster[j] >= 0 && cluster_num > cluster[j])
            {
                continue;
            }

            point_energy_min = typeMethods.r8_huge();
            for (k = 0; k < cluster_num; k++)
            {
                point_energy = 0.0;
                for (i = 0; i < dim_num; i++)
                {
                    point_energy += Math.Pow(point[i + j * dim_num] - cluster_center[i + k * dim_num], 2);
                }

                if (!(point_energy < point_energy_min))
                {
                    continue;
                }

                point_energy_min = point_energy;
                cluster[j]       = k;
            }
        }

        it_num = 0;

        for (;;)
        {
            //
            //  Given centers, assign points to nearest center.
            //
            typeMethods.i4vec_zero(cluster_num, ref cluster_population);
            typeMethods.r8vec_zero(cluster_num, ref cluster_energy);

            int swap = 0;

            for (j = 0; j < point_num; j++)
            {
                point_energy_min = typeMethods.r8_huge();
                k = cluster[j];

                int k2;
                for (k2 = 0; k2 < cluster_num; k2++)
                {
                    point_energy = 0.0;
                    for (i = 0; i < dim_num; i++)
                    {
                        point_energy += Math.Pow(point[i + j * dim_num] - cluster_center[i + k2 * dim_num], 2);
                    }

                    if (!(point_energy < point_energy_min))
                    {
                        continue;
                    }

                    point_energy_min = point_energy;
                    cluster[j]       = k2;
                }

                if (k != cluster[j])
                {
                    swap += 1;
                }

                k = cluster[j];
                cluster_energy[k]     += point_energy_min;
                cluster_population[k] += 1;
            }

            switch (debug)
            {
            case true:
                Console.WriteLine("  " + it_num.ToString(CultureInfo.InvariantCulture).PadLeft(3)
                                  + "  " + typeMethods.r8vec_sum(cluster_num, cluster_energy).ToString(CultureInfo.InvariantCulture)
                                  .PadLeft(14) + "");
                break;
            }

            if (0 < it_num)
            {
                if (swap == 0)
                {
                    break;
                }
            }

            if (it_max <= it_num)
            {
                break;
            }

            it_num += 1;
            //
            //  Given points in cluster, replace center by centroid.
            //
            typeMethods.r8vec_zero(dim_num * cluster_num, ref cluster_center);

            for (j = 0; j < point_num; j++)
            {
                k = cluster[j];
                for (i = 0; i < dim_num; i++)
                {
                    cluster_center[i + k * dim_num] += point[i + j * dim_num];
                }
            }

            for (k = 0; k < cluster_num; k++)
            {
                if (cluster_population[k] != 0)
                {
                    for (i = 0; i < dim_num; i++)
                    {
                        cluster_center[i + k * dim_num] /= cluster_population[k];
                    }
                }
                else
                {
                    j = UniformRNG.i4_uniform(0, point_num - 1, ref seed);
                    for (i = 0; i < dim_num; i++)
                    {
                        cluster_center[i + k * dim_num] = point[i + j * dim_num];
                    }
                }
            }
        }

        //
        //  Compute the energy based on the final value of the cluster centers.
        //
        typeMethods.r8vec_zero(cluster_num, ref cluster_energy);

        for (j = 0; j < point_num; j++)
        {
            k = cluster[j];

            point_energy = 0.0;
            for (i = 0; i < dim_num; i++)
            {
                point_energy += Math.Pow(point[i + j * dim_num] - cluster_center[i + k * dim_num], 2);
            }

            cluster_energy[k] += point_energy;
        }
    }