예제 #1
0
파일: cfg1.c 프로젝트: TakeScoop/node-glpk
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;
}
예제 #2
0
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;
}
예제 #3
0
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;
}
예제 #4
0
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;
}