norm[1] /= nz;
}
-static void update_pmin_pmax_aband(int n, int u, int *ia, int *ja, int *p, int *pmin, int *pmax, int *aband_local){
- int j, aband_u;
- pmin[u] = n; pmax[u] = -1; aband_u = n;
- for (j = ia[u]; j < ia[u+1]; j++) {
- if (ja[j] == u) continue;
- pmin[u] = MIN(pmin[u], abs(p[u] - p[ja[j]]));
- pmax[u] = MIN(pmax[u], abs(p[u] - p[ja[j]]));
- aband_u = MIN(aband_u, abs(p[u] - p[ja[j]]));
- }
- aband_local[u] = aband_u;
-}
-
-
-static bool check_swap(int n, int *ia, int *ja,
- int u, int p_u, int v, int p_v, int *aband_local, int *p, int *p_inv, int aband, int *pmax, int *pmin, real lambda){
- /* check if u should swap with v to improve u, without demaging v. Return TRUE if swap is successful. FALSE otherwise. */
-
- int j, aband_v, aband_v1, aband_u, aband_u1;
-
- aband_v = aband_local[v];
- aband_u = aband_local[u];
-
- /* if swaping u and v makes v worse & becomes/remains critical, don't do. We first quick check using the max/min neighbor indices.
- No need to check the other way around since the calling function have ensured that.
- */
- if (abs(p_u - pmin[v]) < aband_v && abs(p_u - pmin[v]) <= lambda*aband) return false;
- if (abs(p_u - pmax[v]) < aband_v && abs(p_u - pmax[v]) <= lambda*aband) return false;
-
- /* now check in details whether v should swap to u. Do not accept if this makes the antiband width of u worse */
- aband_u1 = n;
- for (j = ja[u]; j < ja[u+1]; j++){
- if (ja[j] == u) continue;
- if (abs(p_v - p[ja[j]]) < aband_u) {
- return false;
- }
- aband_u1 = MIN(aband_u1, abs(p_v - p[ja[j]]));
- }
-
- /* now check in details whether u should swap to v. Do not accept if this makes antibandwidth of v worse && make/keep v in the critical group */
- aband_v1 = n;
- for (j = ja[v]; j < ja[v+1]; j++){
- if (ja[j] == v) continue;
- if (abs(p_u - p[ja[j]]) < aband_v && abs(p_u - p[ja[j]]) <= lambda*aband) {
- return false;
- }
- aband_v1 = MIN(aband_v1, abs(p_u - p[ja[j]]));
- }
-
- /* now check if local antiband width has been improved. By that we mean u is improved, or u unchanged, but v improved. */
- assert(aband_u1 >= aband_u);
- if (aband_u1 > aband_u || (aband_u1 == aband_u && aband_v1 > aband_v)){
- p[u] = p_v;
- p[v] = p[u];
- p_inv[p[u]] = u;
- p_inv[p[v]] = v;
-
- update_pmin_pmax_aband(n, u, ia, ja, p, pmin, pmax, aband_local);
- update_pmin_pmax_aband(n, v, ia, ja, p, pmin, pmax, aband_local);
-
- /* this may be expensive, but I see no way to keep pmin/pmax/aband_local consistent other than this update of u/v's neighbors */
- for (j = ia[u]; j < ia[u+1]; j++) {
- update_pmin_pmax_aband(n, ja[j], ia, ja, p, pmin, pmax, aband_local);
- }
-
- for (j = ia[u]; j < ia[u+1]; j++) {
- update_pmin_pmax_aband(n, ja[j], ia, ja, p, pmin, pmax, aband_local);
- }
- return true;
- }
-
-
- return false;
-}
-
-static void improve_antibandwidth_by_swapping_cheap(SparseMatrix A, int *p){
- /*on entry:
- A: the graph, must be symmetric matrix
- p: a permutation array of length n
- lambda: threshold for deciding critical vertices.*/
- real lambda = 1.2;
- int n = A->m;
- int *p_inv;
- int i, j;
- int *pmax, *pmin;/* max and min index of neighbors */
- int *ia = A->ia, *ja = A->ja;
- int aband = n;/* global antibandwidth*/
- int *aband_local;/* antibandwidth for each node */
- PriorityQueue pq = NULL;
- bool progress = true, swapped;
- int u, v, gain, aband_u, p_u, p_v;
-
- pq = PriorityQueue_new(n, n);
- p_inv = MALLOC(sizeof(int)*n);
- pmax = MALLOC(sizeof(int)*n);
- pmin = MALLOC(sizeof(int)*n);
- aband_local = MALLOC(sizeof(int)*n);
-
- while (progress) {
- progress = false;
- for (i = 0; i < n; i++){
- pmax[i] = -1; pmin[i] = n+1;
- assert(p[i] >= 0 && p[i] < n);
- p_inv[p[i]] = i;
- aband_local[i] = n;
- for (j = ia[i]; j < ia[i+1]; j++){
- if (ja[j] == i) continue;
- pmax[i] = MAX(pmax[i], p[ja[j]]);
- pmin[i] = MIN(pmin[i], p[ja[j]]);
- aband_local[i] = MIN(aband_local[i], abs(p[i] - p[ja[j]]));
- }
- aband = MIN(aband, aband_local[i]);
- }
- fprintf(stderr," antibandwidth = %d", aband);
-
- /* find critical vertices */
- for (i = 0; i < n; i++){
- if (aband_local[i] <= lambda*aband){
- PriorityQueue_push(pq, i, n - aband_local[i]);
- }
- }
-
- /* check critcal nodes u to see if any swaps with v are possible */
- while (PriorityQueue_pop(pq, &u, &gain)){
- aband_u = n - gain;
- p_u = p[u];
- assert(aband_u <= lambda*aband);
- assert(aband_u == aband_local[u]);
- swapped = false;
- for (p_v = 0; p_v <= pmin[u] - aband_u; p_v++){
- v = p_inv[p_v];
- if (check_swap(n, ia, ja, u, p_u, v, p_v, aband_local, p, p_inv, aband, pmax, pmin, lambda)){
- swapped = true; progress = true;
- break;
- }
- }
- if (swapped) continue;
-
- for (p_v = pmax[u] + aband_u; p_v < n; p_v++){
- v = p_inv[p_v];
- if (check_swap(n, ia, ja, u, p_u, v, p_v, aband_local, p, p_inv, aband, pmax, pmin, lambda)){
- swapped = true; progress = true;
- break;
- }
- }
- if (swapped) continue;
-
- for (p_v = pmin[u] + aband_u; p_v <= pmax[u] - aband_u; p_v++) {
- v = p_inv[p_v];
- if (check_swap(n, ia, ja, u, p_u, v, p_v, aband_local, p, p_inv, aband, pmax, pmin, lambda)){
- progress = true;
- break;
- }
- }
-
-
- }
- }
-
-
- FREE(p_inv);
- FREE(pmax);
- FREE(pmin);
- FREE(aband_local);
- PriorityQueue_delete(pq);
-
-}
-
void improve_antibandwidth_by_swapping(SparseMatrix A, int *p){
bool improved = true;
int cnt = 1, n = A->m, i, j, *ia = A->ia, *ja = A->ja;