예제 #1
0
        private static void p1bucket(bilist **bucket, /* buckets holding bucket list */
                                     bilist *lptr,    /* elements within bucket */
                                     int maxdeg       /* maximum degree of a vertex */
                                     )
        {
            bilist *bptr; /* loops through list at a bucket */
            int     val;  /* element in a bucket */
            int     size; /* array spacing */
            int     i;    /* loop counter */

            size = (int)(&(lptr[1]) - &(lptr[0]));
            for (i = 2 * maxdeg; i >= 0; i--)
            {
                if (bucket[i] != null)
                {
                    Console.Write("  Bucket {0:d}:", i - maxdeg);
                    for (bptr = bucket[i]; bptr != null; bptr = bptr->next)
                    {
                        val = ((int)(bptr - lptr)) / size;
                        Console.Write(" {0:d}", val);
                    }

                    Console.WriteLine();
                }
            }
        }
예제 #2
0
/* Set up data structures for refine_part. */
        private static void make_maps_ref(vtx_data **graph,                /* graph data structure */
                                          bilist *set_list,                /* lists of vertices in each set */
                                          bilist *vtx_elems,               /* start of storage for vertices */
                                          int *assignment,                 /* set assignments for graph */
                                          int *sub_assign,                 /* assignment file for subgraph */
                                          int set1, int set2,              /* set value denoting subgraph */
                                          int *glob2loc,                   /* graph -> subgraph numbering map */
                                          int *loc2glob,                   /* subgraph -> graph numbering map */
                                          int *psub_nvtxs,                 /* number of vtxs in subgraph */
                                          int *pvwgt_max,                  /* returned largest vwgt */
                                          int *pvwgt_sum1, int *pvwgt_sum2 /* returned set sizes */
                                          )
        {
            bilist *ptr;                  /* loops through set lists */
            int     vwgt_max;             /* largest vertex weight in subgraph */
            int     vwgt_sum1, vwgt_sum2; /* sum of vertex weights in sets */
            int     vtx;                  /* vertex in subgraph */
            int     size;                 /* array spacing */
            int     j;                    /* loop counter */

            size     = (int)(&(vtx_elems[1]) - &(vtx_elems[0]));
            j        = 1;
            vwgt_max = vwgt_sum1 = vwgt_sum2 = 0;
            for (ptr = set_list[set1].next; ptr != null; ptr = ptr->next)
            {
                vtx           = ((int)(ptr - vtx_elems)) / size;
                sub_assign[j] = 0;
                glob2loc[vtx] = j;
                loc2glob[j]   = vtx;
                if (graph[vtx]->vwgt > vwgt_max)
                {
                    vwgt_max = graph[vtx]->vwgt;
                }

                vwgt_sum1 += graph[vtx]->vwgt;
                j++;
            }

            for (ptr = set_list[set2].next; ptr != null; ptr = ptr->next)
            {
                vtx           = ((int)(ptr - vtx_elems)) / size;
                sub_assign[j] = 1;
                glob2loc[vtx] = j;
                loc2glob[j]   = vtx;
                if (graph[vtx]->vwgt > vwgt_max)
                {
                    vwgt_max = graph[vtx]->vwgt;
                }

                vwgt_sum2      += graph[vtx]->vwgt;
                assignment[vtx] = set1;
                j++;
            }

            *pvwgt_sum1 = vwgt_sum1;
            *pvwgt_sum2 = vwgt_sum2;
            *pvwgt_max  = vwgt_max;
            *psub_nvtxs = j - 1;
        }
예제 #3
0
        public static void movebilist(bilist *lptr,     /* ptr to element to move */
                                      bilist **oldlist, /* head of list to remove it from */
                                      bilist **newlist  /* head of list to add it to */
                                      )

/* Move an element from a old bidirectional list to new one. */
        {
            removebilist(lptr, oldlist);

            add2bilist(lptr, newlist);
        }
예제 #4
0
/* Note: bi-directional lists aren't assumed to be sorted. */
        private static void add2bilist( /* add val to unsorted list */
            bilist *lptr,               /* element to add */
            bilist **list               /* list added to */
            )
        {
            lptr->next = *list;
            if (*list != null)
            {
                (*list)->prev = lptr;
            }
            lptr->prev = null;
            *list = lptr;
        }
예제 #5
0
 public static void free_klv(
     /* Free everything malloc'd for KLV. */
     bilist **lbuckets,  /* space for bucket sorts */
     bilist **rbuckets,  /* space for bucket sorts */
     bilist *llistspace, /* space for all bidirectional elements */
     bilist *rlistspace, /* space for all bidirectional elements */
     int *ldvals,        /* change in penalty for each possible move */
     int *rdvals         /* change in penalty for each possible move */
     )
 {
     Marshal.FreeHGlobal((IntPtr)rlistspace);
     Marshal.FreeHGlobal((IntPtr)llistspace);
     Marshal.FreeHGlobal((IntPtr)rdvals);
     Marshal.FreeHGlobal((IntPtr)ldvals);
     Marshal.FreeHGlobal((IntPtr)rbuckets);
     Marshal.FreeHGlobal((IntPtr)lbuckets);
 }
예제 #6
0
        private static void removebilist(bilist *lptr, /* ptr to element to remove */
                                         bilist **list /* head of list to remove it from */
                                         )

/* Remove an element from a bidirectional list. */
        {
            if (lptr->next != null)
            {
                lptr->next->prev = lptr->prev;
            }
            if (lptr->prev != null)
            {
                lptr->prev->next = lptr->next;
            }
            else
            {
                *list = lptr->next;
            }
        }
예제 #7
0
/* Idea:
 * 'buckets[i][j]' is a set of buckets to sort moves from i to j.
 * listspace[i] is space for lists in buckets[i][j].
 * Loop through all nonequal pairs [i][j], taking the first element
 * in each list.  Compare them all to find the largest allowed move.
 * Make that move, and save it in movelist.
 */

        public static void bucketsort1(vtx_data **graph,              /* graph data structure */
                                       int vtx,                       /* vertex being added to lists */
                                       bilist ****buckets,            /* array of lists for bucket sort */
                                       bilist **listspace,            /* list data structure for each vertex */
                                       int **dvals,                   /* d-values for each vertex for removing */
                                       int *sets,                     /* processor each vertex is assigned to */
                                       float *[]           term_wgts, /* weights for terminal propagation */
                                       int maxdval,                   /* maximum possible dvalue for a vertex */
                                       int nsets,                     /* number of sets being divided into */
                                       int [][] hops,                 /* hop cost between sets */
                                       bool useEdgeWeights            /* are edge weights being used? */
                                       )
        {
            bilist *lptr  = null; /* pointer to an element in listspace */
            float * ewptr = null; /* loops through edge weights */
            int *   edges = null; /* edge list for a vertex */
            int     myset;        /* set that current vertex belongs to */
            int     newset;       /* set current vertex could move to */
            int     set;          /* set that neighboring vertex belongs to */
            int     weight;       /* edge weight for a particular edge */
            float   tval;         /* terminal propagation value */
            int     val;          /* terminal propagation rounded value */
            double  cut_cost;     /* relative cut/hop importance */
            double  hop_cost;     /* relative hop/cut importance */
            int     myhop;        /* hops associated with current vertex */
            int     j, l;         /* loop counters */

            /* Compute d-vals by seeing which sets neighbors belong to. */
            cut_cost = hop_cost = 1;
            if (term_wgts[1] != null)
            {
                if (CUT_TO_HOP_COST > 1)
                {
                    cut_cost = CUT_TO_HOP_COST;
                }
                else
                {
                    hop_cost = 1.0 / CUT_TO_HOP_COST;
                }
            }

            weight = (int)(cut_cost + .5);
            myset  = sets[vtx];

            /* Initialize all the preference values. */
            if (term_wgts[1] != null)
            {
                /* Using terminal propagation. */
                if (myset == 0) /* No terminal value. */
                {
                    for (newset = 1; newset < nsets; newset++)
                    {
                        tval = (term_wgts[newset])[vtx];
                        if (tval < 0)
                        {
                            val = (int)(-tval * hop_cost + .5);
                            val = -val;
                        }
                        else
                        {
                            val = (int)(tval * hop_cost + .5);
                        }
                        dvals[vtx][newset - 1] = val;
                    }
                }
                else
                {
                    tval = -(term_wgts[myset])[vtx];
                    if (tval < 0)
                    {
                        val = (int)(-tval * hop_cost + .5);
                        val = -val;
                    }
                    else
                    {
                        val = (int)(tval * hop_cost + .5);
                    }
                    dvals[vtx][0] = val;
                    l             = 1;
                    for (newset = 1; newset < nsets; newset++)
                    {
                        if (newset != myset)
                        {
                            tval = (term_wgts[newset])[vtx] - (term_wgts[myset])[vtx];
                            if (tval < 0)
                            {
                                val = (int)(-tval * hop_cost + .5);
                                val = -val;
                            }
                            else
                            {
                                val = (int)(tval * hop_cost + .5);
                            }
                            dvals[vtx][l] = val;
                            l++;
                        }
                    }
                }
            }
            else
            {
                for (j = 0; j < nsets - 1; j++)
                {
                    dvals[vtx][j] = 0;
                }
            }

            /* First count the neighbors in each set. */
            edges = graph[vtx]->edges;
            if (useEdgeWeights)
            {
                ewptr = graph[vtx]->ewgts;
            }
            for (j = graph[vtx]->nedges - 1; j != 0; j--)
            {
                set = sets[*(++edges)];
                if (set < 0)
                {
                    set = -set - 1;
                }
                if (useEdgeWeights)
                {
                    weight = (int)(*(++ewptr) * cut_cost + .5);
                }
                myhop = hops[myset][set];

                l = 0;
                for (newset = 0; newset < nsets; newset++)
                {
                    if (newset != myset)
                    {
                        dvals[vtx][l] += weight * (myhop - hops[newset][set]);
                        l++;
                    }
                }
            }

            /* Now add to appropriate buckets. */
            l = 0;
            for (newset = 0; newset < nsets; newset++)
            {
                if (newset != myset)
                {
                    lptr = listspace[l];
                    add2bilist(&lptr[vtx], &buckets[myset][newset][dvals[vtx][l] + maxdval]);
                    ++l;
                }
            }
        }
예제 #8
0
        /* Idea:
         * 'buckets[i][j]' is a set of buckets to sort moves from i to j.
         * listspace[i] is space for lists in buckets[i][j].
         * Loop through all nonequal pairs [i][j], taking the first element
         * in each list.  Compare them all to find the largest allowed move.
         * Make that move, and save it in movelist.
         */

/* Routine slightly streamlined for case with only two sets. */

        public static void bucketsorts_bi(vtx_data **graph,              /* graph data structure */
                                          int nvtxs,                     /* number of vertices */
                                          bilist ****buckets,            /* array of lists for bucket sort */
                                          bilist **listspace,            /* list data structure for each vertex */
                                          int **dvals,                   /* d-values for each vertex for removing */
                                          int *sets,                     /* processor each vertex is assigned to */
                                          float *[]           term_wgts, /* weights for terminal propagation */
                                          int maxdval,                   /* maximum possible dvalue for a vertex */
                                          int nsets,                     /* number of sets being divided into */
                                          bool parity,                   /* work in forward or backward direction? */
                                          int [][] hops,                 /* hop cost between sets */
                                          int *bspace,                   /* indices for randomly ordering vtxs */
                                          int list_length,               /* number of values in bspace to work with */
                                          int npass,                     /* which pass through KL is this? */
                                          bool useEdgeWeights            /* are edge weights being used? */
                                          )
        {
            bilist **bptr  = null; /* loops through set of buckets */
            bilist * lptr  = null; /* pointer to an element in listspace */
            float *  ewptr = null; /* loops through edge weights */
            float *  twptr = null; /* weights for terminal propagation */
            int *    bsptr = null; /* loops through bspace */
            int *    edges = null; /* edge list for a vertex */
            int      myset;        /* set current vertex belongs to */
            int      other_set;    /* set current vertex doesn't belong to */
            int      set;          /* set that neighboring vertex belongs to */
            int      weight;       /* edge weight for a particular edge */
            int      vtx;          /* vertex in graph */
            int      val;          /* terminal propagation rounded value */
            double   cut_cost;     /* relative cut/hop importance */
            double   hop_cost;     /* relative hop/cut importance */
            int      myhop;        /* hops associated with current vertex */
            int      i, j;         /* loop counters */

            /* For each vertex, compute d-values for each possible transition. */
            /* Then store them in each appropriate bucket. */

            if (npass == 1 || !KL_UNDO_LIST || list_length == nvtxs)
            {
                /* Empty all the buckets. */
                /* Last clause catches case where lists weren't undone. */
                bptr = buckets[0][1];
                for (i = nsets * (nsets - 1) * (2 * maxdval + 1); i != 0; i--)
                {
                    *bptr++ = null;
                }
            }

            /* Randomize the order of the vertices */

            if ((KL_UNDO_LIST && list_length == nvtxs) || !KL_UNDO_LIST)
            {
                list_length = nvtxs;
                bsptr       = bspace;
                if (parity)
                {
                    for (i = 1; i <= nvtxs; i++)
                    {
                        *bsptr++ = i;
                    }
                }
                else
                {
                    for (i = nvtxs; i != 0; i--)
                    {
                        *bsptr++ = i;
                    }
                }
            }
            if (KL_RANDOM)
            {
                randomize(bspace - 1, list_length);
            }

            /* Now compute d-vals by seeing which sets neighbors belong to. */
            cut_cost = hop_cost = 1;
            if (term_wgts[1] != null)
            {
                if (CUT_TO_HOP_COST > 1)
                {
                    cut_cost = CUT_TO_HOP_COST;
                }
                else
                {
                    hop_cost = 1.0 / CUT_TO_HOP_COST;
                }
            }

            weight = (int)(cut_cost + .5);

            bsptr = bspace;
            twptr = term_wgts[1];
            for (i = 0; i < list_length; i++) /* Loop through vertices. */
            {
                vtx       = *bsptr++;
                myset     = sets[vtx];
                other_set = myset == 0 ? 1 : 0;

                /* Initialize all the preference values. */
                if (twptr != null)
                {
                    /* Using terminal propagation.  Round to integer value. */
                    if (twptr[vtx] < 0)
                    {
                        val = (int)(-twptr[vtx] * hop_cost + .5);
                        val = -val;
                    }
                    else
                    {
                        val = (int)(twptr[vtx] * hop_cost + .5);
                    }
                    if (myset == 0)
                    {
                        dvals[vtx][0] = val;
                    }
                    else
                    {
                        dvals[vtx][0] = -val;
                    }
                }
                else
                {
                    dvals[vtx][0] = 0;
                }

                /* First count the neighbors in each set. */
                edges = graph[vtx]->edges;
                if (useEdgeWeights)
                {
                    ewptr = graph[vtx]->ewgts;
                }
                for (j = graph[vtx]->nedges - 1; j != 0; j--)
                {
                    set = sets[*(++edges)];
                    if (set < 0)
                    {
                        set = -set - 1;
                    }
                    if (useEdgeWeights)
                    {
                        weight = (int)((*(++ewptr)) * cut_cost + .5);
                    }
                    myhop = hops[myset][set];

                    dvals[vtx][0] += weight * (myhop - hops[other_set][set]);
                }

                /* Now add to appropriate buckets. */
                lptr = listspace[0];
                add2bilist(&lptr[vtx], &buckets[myset][other_set][dvals[vtx][0] + maxdval]);
            }
        }
예제 #9
0
        public static void bucketsortsv(vtx_data **graph,   /* graph data structure */
                                        int nvtxs,          /* number of vertices */
                                        bilist **lbuckets,  /* array of lists for bucket sort */
                                        bilist **rbuckets,  /* array of lists for bucket sort */
                                        bilist *llistspace, /* list data structure for each vertex */
                                        bilist *rlistspace, /* list data structure for each vertex */
                                        int *ldvals,        /* d-values for each vertex for removing */
                                        int *rdvals,        /* d-values for each vertex for removing */
                                        int *sets,          /* processor each vertex is assigned to */
                                        int maxdval,        /* maximum possible dvalue for a vertex */
                                        bool parity,        /* work in forward or backward direction? */
                                        int *bspace,        /* indices for randomly ordering vtxs */
                                        int list_length     /* number of values in bspace to work with */
                                        )
        {
            bilist **lbptr;        /* loops through set of buckets */
            bilist **rbptr;        /* loops through set of buckets */
            int *    bsptr;        /* loops through bspace */
            int *    edges;        /* edge list for a vertex */
            int      left_weight;  /* my neighbors in 0 set */
            int      right_weight; /* my neighbors in 1 set */
            int      vtx;          /* vertex in graph */
            int      neighbor;     /* neighbor of vertex */
            int      set;          /* set that neighboring vertex belongs to */
            int      i, j;         /* loop counters */

            /* For each vertex, compute d-values and store in buckets. */

            /* Empty all the buckets. */
            rbptr = lbuckets;
            lbptr = rbuckets;
            for (i = (2 * maxdval + 1); i != 0; i--)
            {
                *lbptr++ = null;
                *rbptr++ = null;
            }

            /* Randomize the order of the vertices */

            if ((KL_UNDO_LIST && list_length == nvtxs) || (!KL_UNDO_LIST && !KL_RANDOM) || list_length == 0)
            {
                /* Don't need to reoder if about to randomize. */
                list_length = nvtxs;
                bsptr       = bspace;
                if (parity)
                {
                    for (i = 1; i <= nvtxs; i++)
                    {
                        *bsptr++ = i;
                    }
                }
                else
                {
                    for (i = nvtxs; i != 0; i--)
                    {
                        *bsptr++ = i;
                    }
                }
            }

            if (KL_RANDOM)
            {
                randomize(bspace - 1, list_length);
            }

            /* Now compute d-vals by seeing which sets neighbors belong to. */

            bsptr = bspace;
            for (i = 0; i < list_length; i++)
            {
                /* Loop through vertices. */
                vtx = *bsptr++;
                if (sets[vtx] == 2)
                {
                    /* Only worry about separator vertices. */

                    /* Initialize all the preference values. */
                    left_weight = right_weight = 0;

                    /* First count the neighbors in each set. */
                    edges = graph[vtx]->edges;
                    for (j = graph[vtx]->nedges - 1; j != 0; j--)
                    {
                        neighbor = *(++edges);
                        set      = sets[neighbor];
                        if (set < 0)
                        {
                            set = -set - 1;
                        }

                        if (set == 0)
                        {
                            left_weight += graph[neighbor]->vwgt;
                        }
                        else if (set == 1)
                        {
                            right_weight += graph[neighbor]->vwgt;
                        }
                    }

                    ldvals[vtx] = graph[vtx]->vwgt - right_weight;
                    rdvals[vtx] = graph[vtx]->vwgt - left_weight;

                    /* Now add to appropriate buckets. */
                    add2bilist(&llistspace[vtx], &lbuckets[ldvals[vtx] + maxdval]);
                    add2bilist(&rlistspace[vtx], &rbuckets[rdvals[vtx] + maxdval]);
                }
            }
        }
예제 #10
0
        public static void make_bndy_list(vtx_data **graph,   /* data structure for graph */
                                          bilist *movelist,   /* list of vtxs to be moved */
                                          bilist ****buckets, /* array of lists for bucket sort */
                                          bilist **listspace, /* list data structure for each vertex */
                                          int *sets,          /* processor each vertex is assigned to */
                                          int nsets,          /* number of sets divided into */
                                          int *bspace,        /* list of active vertices for bucketsort */
                                          int **tops,         /* top of each set of buckets */
                                          int **bndy_list     /* list of boundary vertices returned */
                                          )
        {
            bilist *bptr;        /* loops through bspace */
            int     vtx;         /* vertex that was moved */
            int     set;         /* set a vertex is in */
            int     list_length; /* number of active vertices */
            int     bndy_length; /* number of vertices actually on boundary */
            int     size;        /* array spacing */
            int     i, j, k;     /* loop counters */

            /* First push all the moved vertices onto list, so they can be flagged. */
            /* They've already been removed from buckets, so want to avoid them. */
            size        = (int)(&(listspace[0][1]) - &(listspace[0][0]));
            bptr        = movelist;
            list_length = 0;
            while (bptr != null)
            {
                vtx = ((int)(bptr - listspace[0])) / size;
                bspace[list_length++] = vtx;
                bptr = bptr->next;
            }

            /* Now get all the vertices still in the bucket lists. */
            for (k = tops[0][1]; k >= 0; k--)
            {
                bptr = buckets[0][1][k];
                while (bptr != null)
                {
                    vtx = ((int)(bptr - listspace[0])) / size;
                    bspace[list_length++] = vtx;
                    bptr = bptr->next;
                }
            }

            for (i = 1; i < nsets; i++)
            {
                for (k = tops[i][0]; k >= 0; k--)
                {
                    bptr = buckets[i][0][k];
                    while (bptr != null)
                    {
                        vtx = ((int)(bptr - listspace[0])) / size;
                        bspace[list_length++] = vtx;
                        bptr = bptr->next;
                    }
                }
            }

            /* Now that list is constructed, go reconstruct all the set numbers. */
            bndy_length = 0;
            for (i = 0; i < list_length; i++)
            {
                vtx = bspace[i];
                set = sets[vtx];
                for (j = 1; j < graph[vtx]->nedges; j++)
                {
                    if (sets[graph[vtx]->edges[j]] != set)
                    {
                        bspace[bndy_length++] = vtx;
                        break;
                    }
                }
            }

            /* Finally, copy boundary vertices into boundary list. */
            *bndy_list = (int *)Marshal.AllocHGlobal((bndy_length + 1) * sizeof(int));
            for (i = 0; i < bndy_length; i++)
            {
                (*bndy_list)[i] = bspace[i];
            }

            (*bndy_list)[bndy_length] = 0;
        }
예제 #11
0
 private static void p1bucket(bilist **a, bilist *b, int c)
 {
     throw new NotImplementedException("I couldn't find the implementation for this in Chaco source.");
 }
예제 #12
0
        /*
         * Keep guys moved in and guys moving out of separator.
         * To restore, move all undesirable guys back.
         * (1) guys moved out of separator get put back in.
         * (2) guys moved into separator (bspace) get put back.
         * Note: Should be done in this order.
         * Note: No neighbors need be considered.
         * (3) To clear dvals, I should compute touch all guys that
         * were ever in separator (bspace) and their neighbors.
         */

        public static bool nway_klv(vtx_data **graph,   /* data structure for graph */
                                    int nvtxs,          /* number of vtxs in graph */
                                    bilist **lbuckets,  /* array of lists for bucket sort */
                                    bilist **rbuckets,  /* array of lists for bucket sort */
                                    bilist *llistspace, /* list data structure for each vertex */
                                    bilist *rlistspace, /* list data structure for each vertex */
                                    int *ldvals,        /* d-values for each transition */
                                    int *rdvals,        /* d-values for each transition */
                                    int *sets,          /* processor each vertex is assigned to */
                                    int maxdval,        /* maximum d-value for a vertex */
                                    double[] goal,      /* desired set sizes */
                                    int max_dev,        /* largest allowed deviation from balance */
                                    int **bndy_list,    /* list of vertices on boundary (0 ends) */
                                    double[] weightsum  /* sum of vweights in each set (in and out) */
                                    )
        {
            bilist **to_buckets;           /* buckets I'm moving to */
            bilist **from_buckets;         /* buckets I'm moving from */
            bilist * to_listspace;         /* list structure I'm moving to */
            bilist * from_listspace;       /* list structure I'm moving from */
            bilist * out_list;             /* list of vtxs moved out of separator */
            int *    to_dvals;             /* d-values I'm moving to */
            int *    from_dvals;           /* d-values I'm moving from */
            int *    bspace;               /* list of active vertices for bucketsort */
            int *    edges;                /* edge list for a vertex */
            int *    edges2;               /* edge list for a vertex */
            int *    bdy_ptr;              /* loops through bndy_list */
            double   total_weight;         /* weight of all vertices */
            double   partial_weight;       /* weight of vertices not in separator */
            double   ratio;                /* fraction of weight not in separator */
            double   time;                 /* timing parameter */
            double   delta0;               /* largest negative deviation from goal size */
            double   delta1;               /* largest negative deviation from goal size */
            double   left_imbalance = 0.0; /* imbalance if I move to the left */
            double   right_imbalance;      /* imbalance if I move to the right */
            double   balance_val;          /* how imbalanced is it */
            double   balance_best;         /* best balance yet if trying hard */
            bool     flag;                 /* condition indicator */
            int      to = -1, from;        /* sets moving into / out of */
            int      rtop, ltop;           /* top of each set of buckets */
            int *    to_top;               /* ptr to top of set moving to */
            int      lvtx, rvtx;           /* next vertex to move left/right */
            int      lweight, rweight;     /* weights of moving vertices */
            int      weightfrom = 0;       /* weight moving out of a set */
            int      list_length;          /* how long is list of vertices to bucketsort? */
            bool     balanced;             /* is partition balanced? */
            bool     temp_balanced;        /* is intermediate partition balanced? */
            bool     ever_balanced;        /* has any partition been balanced? */
            int      bestvtx = -1;         /* best vertex to move */
            int      bestval = -1;         /* best change in value for a vtx move */
            int      vweight;              /* weight of best vertex */
            int      gtotal;               /* sum of changes from moving */
            int      improved;             /* total improvement from KL */
            double   bestg;                /* maximum gtotal found in KL loop */
            double   bestg_min;            /* smaller than any possible bestg */
            int      beststep;             /* step where maximum value occurred */
            int      bestlength;           /* step where maximum value occurred */
            int      neighbor;             /* neighbor of a vertex */
            int      step_cutoff;          /* number of negative steps in a row allowed */
            int      cost_cutoff;          /* amount of negative d-values allowed */
            int      neg_steps;            /* number of negative steps in a row */
            int      neg_cost;             /* decrease in sum of d-values */
            int      vtx;                  /* vertex number */
            int      dval;                 /* dval of a vertex */
            int      group, group2;        /* set that a vertex is assigned to */
            bool     left_too_big;         /* is left set too large? */
            bool     right_too_big;        /* is right set too large? */
            int      vwgt;                 /* weight of a vertex */
            int      gain;                 /* reduction in separator due to a move */
            int      neighbor2;            /* neighbor of a vertex */
            int      step;                 /* loops through movements of vertices */
            bool     parity;               /* sort forwards or backwards? */
            bool     done;                 /* has termination criteria been achieved? */
            int      nbad;                 /* number of unhelpful passes in a row */
            int      npass;                /* total number of passes */
            int      nbadtries;            /* number of unhelpful passes before quitting */
            bool     enforce_balance;      /* force a balanced partition? */
            bool     enforce_balance_hard; /* really force a balanced partition? */
            int      i, j, k;              /* loop counters */

            nbadtries = KL_NTRIES_BAD;

            enforce_balance      = false;
            enforce_balance_hard = false;

            total_weight = goal[0] + goal[1];

            bspace = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));

            if (bspace == null)
            {
                return(true);
            }

            bdy_ptr     = *bndy_list;
            list_length = 0;
            while (*bdy_ptr != 0)
            {
                bspace[list_length++] = *bdy_ptr++;
            }

            Marshal.FreeHGlobal((IntPtr)(*bndy_list));

            clear_dvals(graph, nvtxs, ldvals, rdvals, bspace, list_length);

            step_cutoff = KL_BAD_MOVES;
            cost_cutoff = maxdval * step_cutoff / 7;
            if (cost_cutoff < step_cutoff)
            {
                cost_cutoff = step_cutoff;
            }

            partial_weight = weightsum[0] + weightsum[1];
            ratio          = partial_weight / total_weight;
            delta0         = Math.Abs(weightsum[0] - goal[0] * ratio);
            delta1         = Math.Abs(weightsum[1] - goal[1] * ratio);
            balanced       =
                (delta0 + delta1 <= max_dev) && weightsum[0] != total_weight && weightsum[1] != total_weight;

            bestg_min = -2.0 * nvtxs * maxdval;
            parity    = false;
            nbad      = 0;
            npass     = 0;
            improved  = 0;
            done      = false;
            while (!done)
            {
                npass++;
                ever_balanced = false;
                balance_best  = delta0 + delta1;

                /* Initialize various quantities. */
                ltop = rtop = 2 * maxdval;

                gtotal     = 0;
                bestg      = bestg_min;
                beststep   = -1;
                bestlength = list_length;
                out_list   = null;

                neg_steps = 0;

                /* Compute the initial d-values, and bucket-sort them. */
                time = seconds();
                bucketsortsv(graph, nvtxs, lbuckets, rbuckets, llistspace, rlistspace, ldvals, rdvals, sets,
                             maxdval, parity, bspace, list_length);
                parity          = !parity;
                kl_bucket_time += seconds() - time;

                if (DEBUG_KL == DebugFlagKL.PrintBucket)
                {
                    Console.WriteLine("After sorting, left buckets:");
                    p1bucket(lbuckets, llistspace, maxdval);
                    Console.WriteLine("              right buckets:");
                    p1bucket(rbuckets, rlistspace, maxdval);
                }

                /* Now determine the set of vertex moves. */

                for (step = 1;; step++)
                {
                    /* Find the highest d-value in each set. */
                    /* But only consider moves from large to small sets, or moves */
                    /* in which balance is preserved. */
                    /* Break ties in some nonarbitrary manner. */
                    bestval = -maxdval - 1;

                    partial_weight = weightsum[0] + weightsum[1];
                    ratio          = partial_weight / total_weight;
                    left_too_big   = (weightsum[0] > (goal[0] + .5 * max_dev) * ratio);
                    right_too_big  = (weightsum[1] > (goal[1] + .5 * max_dev) * ratio);

                    while (ltop >= 0 && lbuckets[ltop] == null)
                    {
                        --ltop;
                    }

                    if (ltop >= 0 && !left_too_big)
                    {
                        lvtx           = (int)(((long)lbuckets[ltop] - (long)llistspace) / sizeof(bilist));
                        lweight        = graph[lvtx]->vwgt;
                        rweight        = lweight - (ltop - maxdval);
                        weightfrom     = rweight;
                        to             = 0;
                        bestvtx        = lvtx;
                        bestval        = ltop - maxdval;
                        partial_weight = weightsum[0] + lweight + weightsum[1] - rweight;
                        ratio          = partial_weight / total_weight;
                        left_imbalance = Math.Max(Math.Abs(weightsum[0] + lweight - goal[0] * ratio),
                                                  Math.Abs(weightsum[1] - rweight - goal[1] * ratio));
                    }

                    while (rtop >= 0 && rbuckets[rtop] == null)
                    {
                        --rtop;
                    }

                    if (rtop >= 0 && !right_too_big)
                    {
                        rvtx            = (int)(((long)rbuckets[rtop] - (long)rlistspace) / sizeof(bilist));
                        rweight         = graph[rvtx]->vwgt;
                        lweight         = rweight - (rtop - maxdval);
                        partial_weight  = weightsum[0] - lweight + weightsum[1] + rweight;
                        ratio           = partial_weight / total_weight;
                        right_imbalance = Math.Max(Math.Abs(weightsum[0] - lweight - goal[0] * ratio),
                                                   Math.Abs(weightsum[1] + rweight - goal[1] * ratio));
                        if (rtop - maxdval > bestval || (rtop - maxdval == bestval &&
                                                         (right_imbalance < left_imbalance ||
                                                          (right_imbalance == left_imbalance && drandom() < .5))))
                        {
                            to         = 1;
                            weightfrom = lweight;
                            bestvtx    = rvtx;
                            bestval    = rtop - maxdval;
                        }
                    }

                    if (bestval == -maxdval - 1)
                    {
                        /* No allowed moves */
                        if (DEBUG_KL != DebugFlagKL.NoDebugging)
                        {
                            Console.WriteLine("No KLV moves at step {0:d}.  bestg = {1:g} at step {2:d}.", step, bestg, beststep);
                        }

                        break;
                    }

                    if (to == 0)
                    {
                        from           = 1;
                        to_listspace   = llistspace;
                        from_listspace = rlistspace;
                        to_dvals       = ldvals;
                        from_dvals     = rdvals;
                        to_buckets     = lbuckets;
                        from_buckets   = rbuckets;
                        to_top         = &ltop;
                    }
                    else
                    {
                        from           = 0;
                        to_listspace   = rlistspace;
                        from_listspace = llistspace;
                        to_dvals       = rdvals;
                        from_dvals     = ldvals;
                        to_buckets     = rbuckets;
                        from_buckets   = lbuckets;
                        to_top         = &rtop;
                    }

                    vweight = graph[bestvtx]->vwgt;

                    weightsum[to]   += vweight;
                    weightsum[from] -= weightfrom;

                    /* Check if this partition is balanced. */
                    partial_weight = weightsum[0] + weightsum[1];
                    ratio          = partial_weight / total_weight;
                    delta0         = Math.Abs(weightsum[0] - goal[0] * ratio);
                    delta1         = Math.Abs(weightsum[1] - goal[1] * ratio);
                    temp_balanced  = (delta0 + delta1 <= max_dev) && weightsum[0] != total_weight &&
                                     weightsum[1] != total_weight;
                    ever_balanced = (ever_balanced || temp_balanced);
                    balance_val   = delta0 + delta1;

                    gtotal += bestval;

                    if ((gtotal > bestg && temp_balanced) ||
                        (enforce_balance_hard && balance_val < balance_best))
                    {
                        bestg    = gtotal;
                        beststep = step;
                        if (balance_val < balance_best)
                        {
                            balance_best = balance_val;
                        }

                        if (temp_balanced)
                        {
                            enforce_balance_hard = false;
                        }
                    }

                    if (DEBUG_KL == DebugFlagKL.MoreInfo || DEBUG_KL == DebugFlagKL.PrintBucket)
                    {
                        Console.WriteLine("At KLV step {0:d}, bestvtx={1:d}, bestval={2:d} (2->{3:d}), wt0 = {4:g,} wt1 = {5:g}", step, bestvtx, bestval, to, weightsum[0], weightsum[1]);
                    }

                    /* Monitor the stopping criteria. */
                    if (bestval < 0)
                    {
                        if (!enforce_balance || ever_balanced)
                        {
                            neg_steps++;
                        }

                        if (bestg != bestg_min)
                        {
                            neg_cost = (int)bestg - gtotal;
                        }
                        else
                        {
                            neg_cost = -maxdval - 1;
                        }

                        if ((neg_steps > step_cutoff || neg_cost > cost_cutoff) &&
                            !(enforce_balance && bestg == bestg_min))
                        {
                            if (DEBUG_KL != DebugFlagKL.NoDebugging)
                            {
                                if (neg_steps > step_cutoff || neg_cost > cost_cutoff)
                                {
                                    Console.WriteLine("KLV step cutoff at step {0:d}.  bestg = {1:g} at step {2:d}.", step, bestg, beststep);
                                }
                            }

                            weightsum[to]   -= vweight;
                            weightsum[from] += weightfrom;
                            break;
                        }
                    }
                    else if (bestval > 0)
                    {
                        neg_steps = 0;
                    }

                    /* Remove vertex from its buckets, and flag it as finished. */
                    sets[bestvtx] = to;
                    removebilist(&to_listspace[bestvtx], &to_buckets[bestval + maxdval]);

                    /*
                     *          printf("After to removebilist\n");
                     *          p1bucket(to_buckets, to_listspace, maxdval);
                     */

                    if (from_dvals[bestvtx] != -maxdval - 1)
                    {
                        removebilist(&from_listspace[bestvtx], &from_buckets[from_dvals[bestvtx] + maxdval]);

                        /*
                         *              printf("After from removebilist\n");
                         *              p1bucket(from_buckets, from_listspace, maxdval);
                         */
                    }

                    from_dvals[bestvtx] = -maxdval - 1;

                    /* Now keep track of vertices moved out of separator so */
                    /* I can restore them as needed. */
                    llistspace[bestvtx].next = out_list;
                    out_list = &(llistspace[bestvtx]);

                    /* Now update the d-values of all the neighbors */
                    /* And neighbors of neighbors ... */

                    /* If left move:
                     * 1. Separator neighbors right gain => infinity
                     * 2. Left neighbors unaffected.
                     * 3. Right neighbors move into separator.
                     *    A. Right gain = infinity.
                     *    B. Left gain = computed.
                     *    C. For any of their neighbors in separator increase left gain.
                     */

                    edges = graph[bestvtx]->edges;
                    for (j = graph[bestvtx]->nedges - 1; j != 0; j--)
                    {
                        neighbor = *(++edges);

                        group = sets[neighbor];

                        if (group == 2)
                        {
                            /* In separator. */
                            gain = from_dvals[neighbor] + maxdval;
                            /* Gain in the from direction => -infinity */
                            if (gain >= 0)
                            {
                                removebilist(&from_listspace[neighbor], &from_buckets[gain]);

                                /*
                                 *                      printf("\n  After removing %d\n", neighbor);
                                 *                      p1bucket(from_buckets, from_listspace, maxdval);
                                 */
                                from_dvals[neighbor] = -maxdval - 1;
                            }
                        }
                        else if (group == from)
                        {
                            /* Gain in the from direction => -infinity */
                            sets[neighbor]       = 2;
                            from_dvals[neighbor] = -maxdval - 1;

                            if (to == 0)
                            {
                                bspace[list_length++] = -neighbor;
                            }
                            else
                            {
                                bspace[list_length++] = neighbor;
                            }

                            edges2 = graph[neighbor]->edges;
                            vwgt   = graph[neighbor]->vwgt;
                            gain   = graph[neighbor]->vwgt;
                            flag   = false;
                            for (k = graph[neighbor]->nedges - 1; k != 0; k--)
                            {
                                neighbor2 = *(++edges2);
                                group2    = sets[neighbor2];
                                if (group2 == 2)
                                {
                                    dval = to_dvals[neighbor2] + maxdval;
                                    if (dval >= 0)
                                    {
                                        movebilist(&to_listspace[neighbor2], &to_buckets[dval], &to_buckets[dval + vwgt]);

                                        /*
                                         *                              printf("\n  After moving %d from bucket %d to bucket
                                         * %d\n", neighbor2, dval, dval + vwgt);
                                         *                              p1bucket(to_buckets, to_listspace, maxdval);
                                         */
                                        to_dvals[neighbor2] += vwgt;
                                        dval += vwgt;
                                        if (dval > *to_top)
                                        {
                                            *to_top = dval;
                                        }
                                    }
                                }
                                else if (group2 == from)
                                {
                                    gain -= graph[neighbor2]->vwgt;
                                    if (to_dvals[neighbor2] + maxdval < 0)
                                    {
                                        flag = true;
                                    }
                                }
                            }

                            if (flag)
                            {
                                /* Not allowed to move further. */
                                to_dvals[neighbor] = -maxdval - 1;
                            }
                            else
                            {
                                to_dvals[neighbor] = gain;
                                /* place in appropriate bucket */

                                gain += maxdval;
                                add2bilist(&to_listspace[neighbor], &to_buckets[gain]);

                                /*
                                 *                      printf("\nAfter adding %d to bucket %d\n", neighbor, gain -
                                 * maxdval);
                                 *                      p1bucket(to_buckets, to_listspace, maxdval);
                                 */

                                if (gain > *to_top)
                                {
                                    *to_top = gain;
                                }
                            }
                        }
                    }

                    if (beststep == step)
                    {
                        bestlength = list_length;
                    }

                    if (DEBUG_KL == DebugFlagKL.PrintBucket)
                    {
                        Console.WriteLine("\n-- After step, left buckets:");
                        p1bucket(lbuckets, llistspace, maxdval);
                        Console.WriteLine("             right buckets:");
                        p1bucket(rbuckets, rlistspace, maxdval);
                    }
                }

                /* Done with a pass; should we actually perform any swaps? */
                if (bestg > 0 || (bestg != bestg_min && !balanced && enforce_balance))
                {
                    improved += (int)bestg;
                }
                else
                {
                    if (enforce_balance_hard)
                    {
                        /* I've done the best I can, give up. */
                        done = true;
                    }

                    if (enforce_balance)
                    {
                        enforce_balance_hard = true;
                    }

                    enforce_balance = true;
                    nbad++;
                }

                /* Work backwards, undoing all the undesirable moves. */

                /* First reset vertices moved out of the separator. */
                if (out_list != null)
                {
                    if (beststep < 0)
                    {
                        beststep = 0;
                    }

                    for (i = step - 1; i > beststep; i--)
                    {
                        vtx = (int)(((long)out_list - (long)llistspace) / sizeof(bilist));
                        if (sets[vtx] != 2)
                        {
                            weightsum[sets[vtx]] -= graph[vtx]->vwgt;
                        }

                        sets[vtx] = 2;
                        out_list  = out_list->next;
                    }
                }

                for (i = list_length - 1; i >= bestlength; i--)
                {
                    vtx = bspace[i];
                    if (vtx < 0)
                    {
                        if (sets[-vtx] == 2)
                        {
                            weightsum[1] += graph[-vtx]->vwgt;
                        }

                        sets[-vtx] = 1;
                    }
                    else
                    {
                        if (sets[vtx] == 2)
                        {
                            weightsum[0] += graph[vtx]->vwgt;
                        }

                        sets[vtx] = 0;
                    }
                }

                partial_weight = weightsum[0] + weightsum[1];
                ratio          = partial_weight / total_weight;
                delta0         = Math.Abs(weightsum[0] - goal[0] * ratio);
                delta1         = Math.Abs(weightsum[1] - goal[1] * ratio);
                balanced       = (delta0 + delta1 <= max_dev) && weightsum[0] != total_weight &&
                                 weightsum[1] != total_weight;

                done = done || (nbad >= nbadtries && balanced);
                if (KL_MAX_PASS > 0)
                {
                    done = done || (npass == KL_MAX_PASS && balanced);
                }

                if (!done)
                {
                    /* Rezero dval values. */
                    clear_dvals(graph, nvtxs, ldvals, rdvals, bspace, list_length);
                }

                /* Construct list of separator vertices to pass to buckets or return */
                list_length = make_sep_list(bspace, list_length, sets);

                if (done)
                {
                    bspace[list_length] = 0;
                    bspace = (int *)Marshal.ReAllocHGlobal((IntPtr)bspace, new IntPtr((list_length + 1) * sizeof(int)));
                    *bndy_list = bspace;
                }

                gain = 0;
                j    = k = 0;
                for (i = 1; i <= nvtxs; i++)
                {
                    if (sets[i] == 0)
                    {
                        j += graph[i]->vwgt;
                    }
                    else if (sets[i] == 1)
                    {
                        k += graph[i]->vwgt;
                    }
                    else if (sets[i] == 2)
                    {
                        gain += graph[i]->vwgt;
                    }
                }

                /*
                 *      printf("\nAfter pass of KLV: sets = %d/%d, sep = %d  (bestg = %g)\n\n\n", j, k, gain, bestg);
                 */
            }

            if (DEBUG_KL != DebugFlagKL.NoDebugging)
            {
                Console.WriteLine("   KLV required {0:d} passes to improve by {1:d}.", npass, improved);
            }

            return(false);
        }
예제 #13
0
/* Perform KL between two sets. */
        private static bool kl_refine(vtx_data **graph,    /* graph data structure */
                                      vtx_data **subgraph, /* space for subgraph to refine */
                                      bilist *set_list,    /* lists of vtxs in each set */
                                      bilist *vtx_elems,   /* start of storage for lists */
                                      int *new_assign,     /* set assignments for all vertices */
                                      int set1, int set2,  /* two sets being refined */
                                      int *glob2loc,       /* maps vertices to subgraph vertices */
                                      int *loc2glob,       /* maps subgraph vertices to vertices */
                                      int *sub_assign,     /* new assignment for subgraphs */
                                      int *old_sub_assign, /* current assignment for subgraphs */
                                      int *degrees,        /* space for forming subgraphs */
                                      bool useEdgeWeights, /* are edge weights being used? */
                                      int[][] hops,        /* KL set preferences */
                                      double[] goal,       /* desired set sizes */
                                      int *sizes,          /* number of vertices in different sets */
                                      float *[] term_wgts, /* space for terminal propagation weights */
                                      int architecture,    /* 0 => hypercube, d => d-dimensional mesh */
                                      int[] mesh_dims      /*[3]*/ /* if mesh, how big is it? */
                                      )
        {
            bilist *ptr;                      /* element in set_list */

            double[] subgoal = new double[2]; /* goal within two subgraphs */
            double[] weights = { 0.0, 0.0 };  /* weights for each set */
            double   maxdeg;                  /* largest degree of a vertex */
            double   ratio;                   /* set sizes / goals */
            int *    null_ptr;                /* argument to klspiff */
            int      vwgt_max;                /* largest vertex weight */
            int      max_dev;                 /* largest set deviation allowed in KL */
            int      subnvtxs;                /* number of vtxs in subgraph */
            int      vwgt_sum1;               /* sum of vertex wgts in first set */
            int      vwgt_sum2;               /* sum of vertex wgts in second set */
            int      subnedges;               /* number of edges in subgraph */
            int      setA, setB;              /* two sets being refined */
            int      nsame;                   /* number of vertices not moved */
            int      vtx;                     /* vertex in subgraph */
            int      i;                       /* loop counter */

            /* Compute all the quantities I'll need. */
            null_ptr = null;
            make_maps_ref(graph, set_list, vtx_elems, new_assign, sub_assign, set1, set2, glob2loc, loc2glob,
                          &subnvtxs, &vwgt_max, &vwgt_sum1, &vwgt_sum2);

            for (i = 1; i <= subnvtxs; i++)
            {
                old_sub_assign[i] = sub_assign[i];
            }

            /* Set up goals for this KL invocation. */
            ratio      = (vwgt_sum1 + vwgt_sum2) / (goal[set1] + goal[set2]);
            subgoal[0] = ratio * goal[set1];
            subgoal[1] = ratio * goal[set2];

            if (TERM_PROP)
            {
                make_terms_ref(graph, useEdgeWeights, subnvtxs, loc2glob, set1, set2, new_assign, architecture,
                               mesh_dims, term_wgts);
            }

            /* New_assign has overwritten set2 with set1. */
            make_subgraph(graph, subgraph, subnvtxs, &subnedges, new_assign, set1, glob2loc, loc2glob,
                          degrees, useEdgeWeights);

            maxdeg = find_maxdeg(subgraph, subnvtxs, useEdgeWeights, (float *)null);

            count_weights(subgraph, subnvtxs, sub_assign, 2, weights, (vwgt_max != 1));

            max_dev = vwgt_max;
            ratio   = (subgoal[0] + subgoal[1]) * KL_IMBALANCE / 2;
            if (ratio > max_dev)
            {
                max_dev = (int)ratio;
            }

            klspiff(subgraph, subnvtxs, sub_assign, 2, hops, subgoal, term_wgts, max_dev, maxdeg, useEdgeWeights,
                    &null_ptr, weights);

            /* Figure out which modification leaves most vertices intact. */
            nsame = 0;
            for (i = 1; i <= subnvtxs; i++)
            {
                if (old_sub_assign[i] == sub_assign[i])
                {
                    nsame++;
                }
            }

            if (2 * nsame > subnvtxs)
            {
                setA = set1;
                setB = set2;
            }
            else
            {
                setA = set2;
                setB = set1;
            }

            /* Now update the assignments. */
            sizes[setA] = sizes[setB] = 0;
            for (i = 1; i <= subnvtxs; i++)
            {
                vtx = loc2glob[i];
                /* Update the set_lists. */
                ptr = &(vtx_elems[vtx]);
                if (ptr->next != null)
                {
                    ptr->next->prev = ptr->prev;
                }

                if (ptr->prev != null)
                {
                    ptr->prev->next = ptr->next;
                }

                if (sub_assign[i] == 0)
                {
                    new_assign[vtx] = setA;
                    ++sizes[setA];
                    ptr->next = set_list[setA].next;
                    if (ptr->next != null)
                    {
                        ptr->next->prev = ptr;
                    }

                    ptr->prev           = &(set_list[setA]);
                    set_list[setA].next = ptr;
                }
                else
                {
                    new_assign[vtx] = setB;
                    ++sizes[setB];
                    ptr->next = set_list[setB].next;
                    if (ptr->next != null)
                    {
                        ptr->next->prev = ptr;
                    }

                    ptr->prev           = &(set_list[setB]);
                    set_list[setB].next = ptr;
                }
            }

            remake_graph(subgraph, subnvtxs, loc2glob, degrees, useEdgeWeights);

            return(nsame != subnvtxs);
        }
예제 #14
0
        /* Construct a graph representing the inter-set communication. */
        public static bool refine_part(vtx_data **graph,    /* graph data structure */
                                       int nvtxs,           /* number of vertices in graph */
                                       bool useEdgeWeights, /* are edge weights being used? */
                                       int *assign,         /* current assignment */
                                       int architecture,    /* 0 => hypercube, d => d-dimensional mesh */
                                       int ndims_tot,       /* if hypercube, number of dimensions */
                                       int[] mesh_dims,     /* if mesh, size in each direction */
                                       double[] goal        /* desired set sizes */
                                       )
        {
            bilist *set_list  = null;                 /* lists of vtxs in each set */
            bilist *vtx_elems = null;                 /* space for all vtxs in set_lists */
            bilist *ptr       = null;                 /* loops through set_lists */
            ipairs *pairs     = null;                 /* ordered list of edges in comm graph */
            double *comm_vals = null;                 /* edge wgts of comm graph for sorting */

            float *[] term_wgts = new float *[2];     /* terminal propagation vector */
            int[][]   hops      = new int[MAXSETS][]; /* preference weighting */
            for (var i = 0; i < hops.Length; i++)
            {
                hops[i] = new int[MAXSETS];
            }

            IntPtr     temp;                  /* return argument from srealloc_ret() */
            int *      indices        = null; /* sorted order for communication edges */
            int *      space          = null; /* space for mergesort */
            int *      sizes          = null; /* sizes of the different sets */
            int *      sub_assign     = null; /* new assignment for subgraph */
            int *      old_sub_assign = null; /* room for current sub assignment */
            int **     edges_list     = null; /* lists of comm graph edges */
            int **     ewgts_list     = null; /* lists of comm graph edge wgts */
            int *      ewgts          = null; /* loops through ewgts_list */
            int *      edges          = null; /* edges in communication graph */
            int *      adj_sets       = null; /* weights connecting sets */
            int *      eptr           = null; /* loop through edges and edge weights */
            int *      ewptr          = null; /* loop through edges and edge weights */
            int        ewgt;                  /* weight of an edge */
            vtx_data **subgraph = null;       /* subgraph data structure */
            int *      nedges   = null;       /* space for saving graph data */
            int *      degrees  = null;       /* # neighbors of vertices */
            int *      glob2loc = null;       /* maps full to reduced numbering */
            int *      loc2glob = null;       /* maps reduced to full numbering */
            int        nmax;                  /* largest subgraph I expect to encounter */
            int        set, set1, set2;       /* sets vertices belong to */
            int        vertex;                /* vertex in graph */
            int        ncomm;                 /* # edges in communication graph */
            int        dist      = -1;        /* architectural distance between two sets */
            int        nsets_tot = 0;         /* total number of processors */
            bool       change;                /* did change occur in this pass? */
            bool       any_change = false;    /* has any change occurred? */
            int        error;                 /* out of space? */
            int        size;                  /* array spacing */

            error        = 1;
            term_wgts[1] = null;

            if (architecture == 0)
            {
                nsets_tot = 1 << ndims_tot;
            }
            else if (architecture > 0)
            {
                nsets_tot = mesh_dims[0] * mesh_dims[1] * mesh_dims[2];
            }

            hops[0][0] = hops[1][1] = 0;
            if (!TERM_PROP)
            {
                hops[0][1] = hops[1][0] = 1;
            }

            /* Set up convenient data structure for navigating through sets. */
            set_list  = (bilist *)Marshal.AllocHGlobal(nsets_tot * sizeof(bilist));
            vtx_elems = (bilist *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(bilist));
            sizes     = (int *)Marshal.AllocHGlobal(nsets_tot * sizeof(int));
            if (set_list == null || vtx_elems == null || sizes == null)
            {
                goto skip;
            }

            for (var i = 0; i < nsets_tot; i++)
            {
                set_list[i].next = null;
                sizes[i]         = 0;
            }

            for (var i = 1; i <= nvtxs; i++)
            {
                set = assign[i];
                ++sizes[set];
                vtx_elems[i].next = set_list[set].next;
                if (vtx_elems[i].next != null)
                {
                    vtx_elems[i].next->prev = &(vtx_elems[i]);
                }

                vtx_elems[i].prev  = &(set_list[set]);
                set_list[set].next = &(vtx_elems[i]);
            }

            /* For each set, find connections to all set neighbors. */
            edges_list = (int **)Marshal.AllocHGlobal(nsets_tot * sizeof(int *));
            if (edges_list == null)
            {
                goto skip;
            }

            for (set = 0; set < nsets_tot - 1; set++)
            {
                edges_list[set] = null;
            }

            ewgts_list = (int **)Marshal.AllocHGlobal(nsets_tot * sizeof(int *));
            if (ewgts_list == null)
            {
                goto skip;
            }

            for (set = 0; set < nsets_tot - 1; set++)
            {
                ewgts_list[set] = null;
            }

            nedges   = (int *)Marshal.AllocHGlobal(nsets_tot * sizeof(int));
            adj_sets = (int *)Marshal.AllocHGlobal(nsets_tot * sizeof(int));
            if (nedges == null || adj_sets == null)
            {
                goto skip;
            }

            size  = (int)(&(vtx_elems[1]) - &(vtx_elems[0]));
            ncomm = 0;
            ewgt  = 1;
            nmax  = 0;
            for (set = 0; set < nsets_tot - 1; set++)
            {
                if (sizes[set] > nmax)
                {
                    nmax = sizes[set];
                }

                for (var i = 0; i < nsets_tot; i++)
                {
                    adj_sets[i] = 0;
                }

                for (ptr = set_list[set].next; ptr != null; ptr = ptr->next)
                {
                    vertex = ((int)(ptr - vtx_elems)) / size;
                    for (var j = 1; j < graph[vertex]->nedges; j++)
                    {
                        set2 = assign[graph[vertex]->edges[j]];
                        if (useEdgeWeights)
                        {
                            ewgt = (int)graph[vertex]->ewgts[j];
                        }

                        adj_sets[set2] += ewgt;
                    }
                }

                /* Now save adj_sets data to later construct graph. */
                var t = 0;
                for (var i = set + 1; i < nsets_tot; i++)
                {
                    if (adj_sets[i] != 0)
                    {
                        t++;
                    }
                }

                nedges[set] = t;
                if (t != 0)
                {
                    edges_list[set] = edges = (int *)Marshal.AllocHGlobal(t * sizeof(int));
                    ewgts_list[set] = ewgts = (int *)Marshal.AllocHGlobal(t * sizeof(int));
                    if (edges == null || ewgts == null)
                    {
                        goto skip;
                    }
                }

                t = 0;
                for (var i = set + 1; i < nsets_tot; i++)
                {
                    if (adj_sets[i] != 0)
                    {
                        edges[t] = i;
                        ewgts[t] = adj_sets[i];
                        t++;
                    }
                }

                ncomm += t;
            }

            Marshal.FreeHGlobal((IntPtr)adj_sets);
            adj_sets = null;

            /* Now compact all communication weight information into single */
            /* vector for sorting. */

            pairs     = (ipairs *)Marshal.AllocHGlobal((ncomm + 1) * sizeof(ipairs));
            comm_vals = (double *)Marshal.AllocHGlobal((ncomm + 1) * sizeof(double));
            if (pairs == null || comm_vals == null)
            {
                goto skip;
            }

            var u = 0;

            for (set = 0; set < nsets_tot - 1; set++)
            {
                eptr  = edges_list[set];
                ewptr = ewgts_list[set];
                for (var k = 0; k < nedges[set]; k++)
                {
                    set2          = eptr[k];
                    pairs[u].val1 = set;
                    pairs[u].val2 = set2;
                    comm_vals[u]  = ewptr[k];
                    u++;
                }
            }

            Marshal.FreeHGlobal((IntPtr)nedges);
            nedges = null;

            indices = (int *)Marshal.AllocHGlobal((ncomm + 1) * sizeof(int));
            space   = (int *)Marshal.AllocHGlobal((ncomm + 1) * sizeof(int));
            if (indices == null || space == null)
            {
                goto skip;
            }

            ch_mergesort(comm_vals, ncomm, indices, space);
            Marshal.FreeHGlobal((IntPtr)space);
            Marshal.FreeHGlobal((IntPtr)comm_vals);
            space     = null;
            comm_vals = null;

            for (set = 0; set < nsets_tot - 1; set++)
            {
                if (edges_list[set] != null)
                {
                    Marshal.FreeHGlobal((IntPtr)edges_list[set]);
                }

                if (ewgts_list[set] != null)
                {
                    Marshal.FreeHGlobal((IntPtr)ewgts_list[set]);
                }
            }

            Marshal.FreeHGlobal((IntPtr)ewgts_list);
            Marshal.FreeHGlobal((IntPtr)edges_list);
            ewgts_list = null;
            edges_list = null;

            /* 2 for 2 subsets, 20 for safety margin. Should check this at run time. */
            nmax = 2 * nmax + 20;

            subgraph       = (vtx_data **)Marshal.AllocHGlobal((nmax + 1) * sizeof(vtx_data *));
            degrees        = (int *)Marshal.AllocHGlobal((nmax + 1) * sizeof(int));
            glob2loc       = (int *)Marshal.AllocHGlobal((nvtxs + 1) * sizeof(int));
            loc2glob       = (int *)Marshal.AllocHGlobal((nmax + 1) * sizeof(int));
            sub_assign     = (int *)Marshal.AllocHGlobal((nmax + 1) * sizeof(int));
            old_sub_assign = (int *)Marshal.AllocHGlobal((nmax + 1) * sizeof(int));

            if (subgraph == null || degrees == null || glob2loc == null || loc2glob == null ||
                sub_assign == null || old_sub_assign == null)
            {
                goto skip;
            }

            if (TERM_PROP)
            {
                term_wgts[1] = (float *)Marshal.AllocHGlobal((nmax + 1) * sizeof(float));
                if (term_wgts[1] == null)
                {
                    goto skip;
                }
            }
            else
            {
                term_wgts[1] = null;
            }

            /* Do large boundaries first to encourage convergence. */
            any_change = false;
            for (var i = ncomm - 1; i >= 0; i--)
            {
                var t = indices[i];
                set1 = pairs[t].val1;
                set2 = pairs[t].val2;

                /* Make sure subgraphs aren't too big. */
                if (sizes[set1] + sizes[set2] > nmax)
                {
                    nmax = sizes[set1] + sizes[set2];

                    temp = Marshal.ReAllocHGlobal((IntPtr)subgraph, new IntPtr((nmax + 1) * sizeof(vtx_data *)));
                    if (temp == null)
                    {
                        goto skip;
                    }
                    else
                    {
                        subgraph = (vtx_data **)temp;
                    }

                    temp = Marshal.ReAllocHGlobal((IntPtr)degrees, new IntPtr((nmax + 1) * sizeof(int)));
                    if (temp == null)
                    {
                        goto skip;
                    }
                    else
                    {
                        degrees = (int *)temp;
                    }

                    temp = Marshal.ReAllocHGlobal((IntPtr)loc2glob, new IntPtr((nmax + 1) * sizeof(int)));
                    if (temp == null)
                    {
                        goto skip;
                    }
                    else
                    {
                        loc2glob = (int *)temp;
                    }

                    temp = Marshal.ReAllocHGlobal((IntPtr)sub_assign, new IntPtr((nmax + 1) * sizeof(int)));
                    if (temp == null)
                    {
                        goto skip;
                    }
                    else
                    {
                        sub_assign = (int *)temp;
                    }

                    temp = Marshal.ReAllocHGlobal((IntPtr)old_sub_assign, new IntPtr((nmax + 1) * sizeof(int)));
                    if (temp == null)
                    {
                        goto skip;
                    }
                    else
                    {
                        old_sub_assign = (int *)temp;
                    }

                    if (TERM_PROP)
                    {
                        temp = Marshal.ReAllocHGlobal((IntPtr)term_wgts[1], new IntPtr((nmax + 1) * sizeof(float)));
                        if (temp == null)
                        {
                            goto skip;
                        }
                        else
                        {
                            term_wgts[1] = (float *)temp;
                        }
                    }
                }

                if (TERM_PROP)
                {
                    if (architecture == 0)
                    {
                        var j = set1 ^ set2;
                        dist = 0;
                        while (j != 0)
                        {
                            if ((j & 1) != 0)
                            {
                                dist++;
                            }

                            j >>= 1;
                        }
                    }
                    else if (architecture > 0)
                    {
                        dist  = Math.Abs((set1 % mesh_dims[0]) - (set2 % mesh_dims[0]));
                        dist +=
                            Math.Abs(((set1 / mesh_dims[0]) % mesh_dims[1]) - ((set2 / mesh_dims[0]) % mesh_dims[1]));
                        dist +=
                            Math.Abs((set1 / (mesh_dims[0] * mesh_dims[1])) - (set2 / (mesh_dims[0] * mesh_dims[1])));
                    }

                    hops[0][1] = hops[1][0] = dist;
                }

                change = kl_refine(graph, subgraph, set_list, vtx_elems, assign, set1, set2, glob2loc, loc2glob,
                                   sub_assign, old_sub_assign, degrees, useEdgeWeights, hops, goal, sizes,
                                   term_wgts, architecture, mesh_dims);

                any_change |= change;
            }

            error = 0;

skip:
            if (error != 0)
            {
                Trace.WriteLine("\nWARNING: No space to refine partition.");
                Trace.WriteLine("         NO PARTITION REFINEMENT PERFORMED.");
            }

            if (edges_list != null)
            {
                for (set = 0; set < nsets_tot - 1; set++)
                {
                    if (edges_list[set] != null)
                    {
                        Marshal.FreeHGlobal((IntPtr)edges_list[set]);
                    }
                }

                Marshal.FreeHGlobal((IntPtr)edges_list);
            }

            if (ewgts_list != null)
            {
                for (set = 0; set < nsets_tot - 1; set++)
                {
                    if (ewgts_list[set] != null)
                    {
                        Marshal.FreeHGlobal((IntPtr)ewgts_list[set]);
                    }
                }

                Marshal.FreeHGlobal((IntPtr)ewgts_list);
            }

            Marshal.FreeHGlobal((IntPtr)space);
            Marshal.FreeHGlobal((IntPtr)comm_vals);
            Marshal.FreeHGlobal((IntPtr)nedges);
            Marshal.FreeHGlobal((IntPtr)adj_sets);
            Marshal.FreeHGlobal((IntPtr)term_wgts[1]);
            Marshal.FreeHGlobal((IntPtr)old_sub_assign);
            Marshal.FreeHGlobal((IntPtr)sub_assign);
            Marshal.FreeHGlobal((IntPtr)loc2glob);
            Marshal.FreeHGlobal((IntPtr)glob2loc);
            Marshal.FreeHGlobal((IntPtr)degrees);
            Marshal.FreeHGlobal((IntPtr)subgraph);

            Marshal.FreeHGlobal((IntPtr)indices);
            Marshal.FreeHGlobal((IntPtr)pairs);

            Marshal.FreeHGlobal((IntPtr)sizes);
            Marshal.FreeHGlobal((IntPtr)vtx_elems);
            Marshal.FreeHGlobal((IntPtr)set_list);

            return(any_change);
        }
예제 #15
0
        private static int make_kl_list(vtx_data **graph,   /* data structure for graph */
                                        bilist *movelist,   /* list of vtxs to be moved */
                                        bilist ****buckets, /* array of lists for bucket sort */
                                        bilist **listspace, /* list data structure for each vertex */
                                        int *sets,          /* processor each vertex is assigned to */
                                        int nsets,          /* number of sets divided into */
                                        int *bspace,        /* list of active vertices for bucketsort */
                                        int **dvals,        /* d-values for each transition */
                                        int maxdval         /* maximum d-value for a vertex */
                                        )
        {
            bilist **list;        /* bucket to erase element from */
            bilist * vptr;        /* loops through movelist */
            int *    bptr;        /* loops through bspace */
            int *    iptr;        /* loops through edge list */
            int      vtx;         /* vertex that was moved */
            int      neighbor;    /* neighbor of a vertex */
            int      myset;       /* set a vertex is in */
            int      newset;      /* loops through other sets */
            int      list_length; /* number of values put in bspace */
            int      size;        /* array spacing */
            int      i, l;        /* loop counter */

            /* First push all the moved vertices onto list, so they can be flagged. */
            /* They've already been removed from buckets, so want to avoid them. */
            size        = (int)(&(listspace[0][1]) - &(listspace[0][0]));
            vptr        = movelist;
            bptr        = bspace;
            list_length = 0;
            while (vptr != null)
            {
                vtx = ((int)(vptr - listspace[0])) / size;
                *bptr++ = vtx;
                if (sets[vtx] >= 0)
                {
                    sets[vtx] = -sets[vtx] - 1;
                }
                ++list_length;
                vptr = vptr->next;
            }

            /* Now look at all the neighbors of moved vertices. */
            vptr = movelist;
            while (vptr != null)
            {
                vtx = ((int)(vptr - listspace[0])) / size;

                iptr = graph[vtx]->edges;
                for (i = graph[vtx]->nedges - 1; i != 0; i--)
                {
                    neighbor = *(++iptr);
                    if (sets[neighbor] >= 0)
                    {
                        *bptr++ = neighbor;
                        ++list_length;
                        myset          = sets[neighbor];
                        sets[neighbor] = -sets[neighbor] - 1;

                        /* Remove neighbor entry from all his buckets. */
                        /* Note: vertices in movelist already removed from buckets. */
                        l = 0;
                        for (newset = 0; newset < nsets; newset++)
                        {
                            if (newset != myset)
                            {
                                list = &buckets[myset][newset][dvals[neighbor][l] + maxdval];
                                removebilist(&listspace[l][neighbor], list);
                                l++;
                            }
                        }
                    }
                }
                vptr = vptr->next;
            }

            /* Now that list is constructed, go reconstruct all the set numbers. */
            bptr = bspace;
            for (i = list_length; i != 0; i--)
            {
                vtx       = *bptr++;
                sets[vtx] = -sets[vtx] - 1;
            }

            return(list_length);
        }