static int find_clique(struct csa *csa, int c_ind[]) { /* find maximum weight clique in induced subgraph with exact * Ostergard's algorithm */ int nn = csa->nn; double *wgt = csa->wgt; int i, j, k, p, q, t, ne, nb, len, *iwt, *ind; unsigned char *a; xassert(nn >= 2); /* allocate working array */ ind = talloc(1+nn, int); /* calculate the number of elements in lower triangle (without * diagonal) of adjacency matrix of induced subgraph */ ne = (nn * (nn - 1)) / 2; /* calculate the number of bytes needed to store lower triangle * of adjacency matrix */ nb = (ne + (CHAR_BIT - 1)) / CHAR_BIT; /* allocate lower triangle of adjacency matrix */ a = talloc(nb, unsigned char); /* fill lower triangle of adjacency matrix */ memset(a, 0, nb); for (p = 1; p <= nn; p++) { /* retrieve vertices adjacent to vertex p */ len = sub_adjacent(csa, p, ind); for (k = 1; k <= len; k++) { /* there exists edge (p, q) in induced subgraph */ q = ind[k]; xassert(1 <= q && q <= nn && q != p); /* determine row and column indices of this edge in lower * triangle of adjacency matrix */ if (p > q) i = p, j = q; else /* p < q */ i = q, j = p; /* set bit a[i,j] to 1, i > j */ t = ((i - 1) * (i - 2)) / 2 + (j - 1); a[t / CHAR_BIT] |= (unsigned char)(1 << ((CHAR_BIT - 1) - t % CHAR_BIT)); } } /* scale vertex weights by 1000 and convert them to integers as * required by Ostergard's algorithm */ iwt = ind; for (i = 1; i <= nn; i++) { /* it is assumed that 0 <= wgt[i] <= 1 */ t = (int)(1000.0 * wgt[i] + 0.5); if (t < 0) t = 0; else if (t > 1000) t = 1000; iwt[i] = t; } /* find maximum weight clique */ len = wclique(nn, iwt, a, c_ind); /* free working arrays */ tfree(ind); tfree(a); /* return clique size to calling routine */ return len; }
int scg_max_clique(SCG *g, const int w[], int list[]) { int size; if (g->n == 0) size = 0; else size = wclique(g, w, list); return size; }
int glp_wclique_exact(glp_graph *G, int v_wgt, double *sol, int v_set) { /* find maximum weight clique with exact algorithm */ glp_arc *e; int i, j, k, len, x, *w, *ind, ret = 0; unsigned char *a; double s, t; if (v_wgt >= 0 && v_wgt > G->v_size - (int)sizeof(double)) xerror("glp_wclique_exact: v_wgt = %d; invalid parameter\n", v_wgt); if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int)) xerror("glp_wclique_exact: v_set = %d; invalid parameter\n", v_set); if (G->nv == 0) { /* empty graph has only empty clique */ if (sol != NULL) *sol = 0.0; return 0; } /* allocate working arrays */ w = xcalloc(1+G->nv, sizeof(int)); ind = xcalloc(1+G->nv, sizeof(int)); len = G->nv; /* # vertices */ len = len * (len - 1) / 2; /* # entries in lower triangle */ len = (len + (CHAR_BIT - 1)) / CHAR_BIT; /* # bytes needed */ a = xcalloc(len, sizeof(char)); memset(a, 0, len * sizeof(char)); /* determine vertex weights */ s = 0.0; for (i = 1; i <= G->nv; i++) { if (v_wgt >= 0) { memcpy(&t, (char *)G->v[i]->data + v_wgt, sizeof(double)); if (!(0.0 <= t && t <= (double)INT_MAX && t == floor(t))) { ret = GLP_EDATA; goto done; } w[i] = (int)t; } else w[i] = 1; s += (double)w[i]; } if (s > (double)INT_MAX) { ret = GLP_EDATA; goto done; } /* build the adjacency matrix */ for (i = 1; i <= G->nv; i++) { for (e = G->v[i]->in; e != NULL; e = e->h_next) { j = e->tail->i; /* there exists edge (j,i) in the graph */ if (i > j) set_edge(G->nv, a, i, j); } for (e = G->v[i]->out; e != NULL; e = e->t_next) { j = e->head->i; /* there exists edge (i,j) in the graph */ if (i > j) set_edge(G->nv, a, i, j); } } /* find maximum weight clique in the graph */ len = wclique(G->nv, w, a, ind); /* compute the clique weight */ s = 0.0; for (k = 1; k <= len; k++) { i = ind[k]; xassert(1 <= i && i <= G->nv); s += (double)w[i]; } if (sol != NULL) *sol = s; /* mark vertices included in the clique */ if (v_set >= 0) { x = 0; for (i = 1; i <= G->nv; i++) memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); x = 1; for (k = 1; k <= len; k++) { i = ind[k]; memcpy((char *)G->v[i]->data + v_set, &x, sizeof(int)); } } done: /* free working arrays */ xfree(w); xfree(ind); xfree(a); return ret; }
int lpx_clique_cut(LPX *lp, void *_cog, int ind[], double val[]) { struct COG *cog = _cog; int n = lpx_get_num_cols(lp); int j, t, v, card, temp, len = 0, *w, *sol; double x, sum, b, *vec; /* allocate working arrays */ w = xcalloc(1 + 2 * cog->nb, sizeof(int)); sol = xcalloc(1 + 2 * cog->nb, sizeof(int)); vec = xcalloc(1+n, sizeof(double)); /* assign weights to vertices of the conflict graph */ for (t = 1; t <= cog->nb; t++) { j = cog->orig[t]; x = lpx_get_col_prim(lp, j); temp = (int)(100.0 * x + 0.5); if (temp < 0) temp = 0; if (temp > 100) temp = 100; w[t] = temp; w[cog->nb + t] = 100 - temp; } /* find a clique of maximum weight */ card = wclique(2 * cog->nb, w, cog->a, sol); /* compute the clique weight for unscaled values */ sum = 0.0; for ( t = 1; t <= card; t++) { v = sol[t]; xassert(1 <= v && v <= 2 * cog->nb); if (v <= cog->nb) { /* vertex v corresponds to binary variable x[j] */ j = cog->orig[v]; x = lpx_get_col_prim(lp, j); sum += x; } else { /* vertex v corresponds to the complement of x[j] */ j = cog->orig[v - cog->nb]; x = lpx_get_col_prim(lp, j); sum += 1.0 - x; } } /* if the sum of binary variables and their complements in the clique greater than 1, the clique cut is violated */ if (sum >= 1.01) { /* construct the inquality */ for (j = 1; j <= n; j++) vec[j] = 0; b = 1.0; for (t = 1; t <= card; t++) { v = sol[t]; if (v <= cog->nb) { /* vertex v corresponds to binary variable x[j] */ j = cog->orig[v]; xassert(1 <= j && j <= n); vec[j] += 1.0; } else { /* vertex v corresponds to the complement of x[j] */ j = cog->orig[v - cog->nb]; xassert(1 <= j && j <= n); vec[j] -= 1.0; b -= 1.0; } } xassert(len == 0); for (j = 1; j <= n; j++) { if (vec[j] != 0.0) { len++; ind[len] = j, val[len] = vec[j]; } } ind[0] = 0, val[0] = b; } /* free working arrays */ xfree(w); xfree(sol); xfree(vec); /* return to the calling program */ return len; }