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(); } } }
/* 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; }
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); }
/* 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; }
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); }
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; } }
/* 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; } } }
/* 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]); } }
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]); } } }
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; }
private static void p1bucket(bilist **a, bilist *b, int c) { throw new NotImplementedException("I couldn't find the implementation for this in Chaco source."); }
/* * 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 = <op; } 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); }
/* 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); }
/* 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); }
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); }