⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 glpscg.c

📁 著名的大规模线性规划求解器源码GLPK.C语言版本,可以修剪.内有详细帮助文档.
💻 C
字号:
/* glpscg.c *//************************************************************************  This code is part of GLPK (GNU Linear Programming Kit).**  Copyright (C) 2000,01,02,03,04,05,06,07,08,2009 Andrew Makhorin,*  Department for Applied Informatics, Moscow Aviation Institute,*  Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.**  GLPK is free software: you can redistribute it and/or modify it*  under the terms of the GNU General Public License as published by*  the Free Software Foundation, either version 3 of the License, or*  (at your option) any later version.**  GLPK is distributed in the hope that it will be useful, but WITHOUT*  ANY WARRANTY; without even the implied warranty of MERCHANTABILITY*  or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public*  License for more details.**  You should have received a copy of the GNU General Public License*  along with GLPK. If not, see <http://www.gnu.org/licenses/>.***********************************************************************/#include "glpscg.h"#define _GLPSCG_DEBUG 0/**********************************************************************/SCG *scg_create_graph(int n){     /* create cliqued graph */      SCG *g;      xassert(n >= 0);      g = xmalloc(sizeof(SCG));      g->pool = dmp_create_pool();      g->n_max = 50;      g->nc_max = 10;      g->n = g->nc = 0;      g->i_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));      g->j_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));      g->c_ptr = xcalloc(1+g->nc_max, sizeof(SCGCQE *));      g->v_ptr = xcalloc(1+g->n_max, sizeof(SCGCQE *));      g->flag = xcalloc(1+g->n_max, sizeof(char));      if (n > 0) scg_add_nodes(g, n);      return g;}/**********************************************************************/int scg_add_nodes(SCG *g, int num){     /* add new nodes to cliqued graph */      int n_new, i;      xassert(num > 0);      /* determine new number of nodes */      n_new = g->n + num;      xassert(n_new > 0);      /* enlarge the room, if necessary */      if (g->n_max < n_new)      {  void **save;         while (g->n_max < n_new)         {  g->n_max += g->n_max;            xassert(g->n_max > 0);         }         save = (void **)g->i_ptr;         g->i_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));         memcpy(&g->i_ptr[1], &save[1], g->n * sizeof(SCGRIB *));         xfree(save);         save = (void **)g->j_ptr;         g->j_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));         memcpy(&g->j_ptr[1], &save[1], g->n * sizeof(SCGRIB *));         xfree(save);         save = (void **)g->v_ptr;         g->v_ptr = xcalloc(1+g->n_max, sizeof(SCGCQE *));         memcpy(&g->v_ptr[1], &save[1], g->n * sizeof(SCGCQE *));         xfree(save);         xfree(g->flag);         g->flag = xcalloc(1+g->n_max, sizeof(char));         memset(&g->flag[1], 0, g->n);      }      /* add new nodes to the end of the node list */      for (i = g->n+1; i <= n_new; i++)      {  g->i_ptr[i] = NULL;         g->j_ptr[i] = NULL;         g->v_ptr[i] = NULL;         g->flag[i] = 0;      }      /* set new number of nodes */      g->n = n_new;      /* return number of first node added */      return n_new - num + 1;}/**********************************************************************/SCGRIB *scg_add_edge(SCG *g, int i, int j){     /* add new edge (i,j) to cliqued graph */      SCGRIB *e;      int t;      xassert(1 <= i && i <= g->n);      xassert(1 <= j && j <= g->n);      if (i > j) t = i, i = j, j = t;      xassert(i < j);      e = dmp_get_atom(g->pool, sizeof(SCGRIB));      e->i = i;      e->j = j;      e->i_prev = NULL;      e->i_next = g->i_ptr[i];      e->j_prev = NULL;      e->j_next = g->j_ptr[j];      if (e->i_next != NULL) e->i_next->i_prev = e;      if (e->j_next != NULL) e->j_next->j_prev = e;      g->i_ptr[i] = g->j_ptr[j] = e;      return e;}/************************************************************************  NAME**  scg_adj_list - get adjacency list for a node of cliqued graph**  SYNOPSIS**  #include "glpscg.h"*  int scg_adj_list(SCG *g, int i, int adj[]);**  DESCRIPTION**  For a given node i of the graph g the routine scg_adj_list stores*  numbers of adjacent nodes to locations adj[1], ..., adj[nadj], where*  0 <= nadj <= n-1 is the number of adjacent nodes, n is the number of*  nodes in the graph. Note that the list of adjacent nodes does not*  include node i.**  RETURNS**  The routine scg_adj_list returns nadj, which is the number of nodes*  adjacent to node i. */int scg_adj_list(SCG *g, int i, int adj[]){     int n = g->n;      char *flag = g->flag;      SCGRIB *e;      SCGCQE *p, *q;      int j, c, nadj = 0;      xassert(1 <= i && i <= n);#if _GLPSCG_DEBUG      for (j = 1; j <= n; j++) xassert(!flag[j]);#endif      /* go through the list of edges (i,j) and add node j to the         adjacency list */      for (e = g->i_ptr[i]; e != NULL; e = e->i_next)      {  j = e->j;#if _GLPSCG_DEBUG         xassert(i < j && j <= n);#endif         if (!flag[j]) adj[++nadj] = j, flag[j] = 1;      }      /* go through the list of edges (j,i) and add node j to the         adjacency list */      for (e = g->j_ptr[i]; e != NULL; e = e->j_next)      {  j = e->i;#if _GLPSCG_DEBUG         xassert(1 <= j && j < i);#endif         if (!flag[j]) adj[++nadj] = j, flag[j] = 1;      }#if 1      /* not tested yet */      xassert(g->v_ptr[i] == NULL);#endif      /* go through the list of cliques containing node i */      for (p = g->v_ptr[i]; p != NULL; p = p->v_next)      {  c = p->c;         /* clique c contains node i */#if _GLPSCG_DEBUG         xassert(1 <= c && c <= g->nc);#endif         /* go through the list of nodes of clique c and add them            (except node i) to the adjacency list */         for (q = g->c_ptr[c]; q != NULL; q = q->c_next)         {  j = q->i;            /* clique c contains node j */#if _GLPSCG_DEBUG            xassert(1 <= j && j <= n);#endif            if (j != i && !flag[j]) adj[++nadj] = j, flag[j] = 1;         }      }      /* reset the working array */      for (j = 1; j <= nadj; j++) flag[adj[j]] = 0;#if _GLPSCG_DEBUG      for (j = 1; j <= n; j++) xassert(!flag[j]);#endif      return nadj;}/************************************************************************  MAXIMUM WEIGHT CLIQUE**  Two subroutines sub and wclique below are used to find a maximum*  weight clique in a given undirected graph. These subroutines are*  slightly modified version of the program WCLIQUE developed by Patric*  Ostergard <http://www.tcs.hut.fi/~pat/wclique.html> and based on*  ideas from the article "P. R. J. Ostergard, A new algorithm for the*  maximum-weight clique problem, submitted for publication", which, in*  turn, is a generalization of the algorithm for unweighted graphs*  presented in "P. R. J. Ostergard, A fast algorithm for the maximum*  clique problem, submitted for publication".**  USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE. */struct dsa{     /* dynamic storage area */      SCG *g;      /* given (cliqued) graph */      int i;      /* node number, for which the adjacency list is built and stored         in the arrays adj and flag */      int nadj;      /* size of the adjacency list, 0 <= nadj <= n-1 */      int *adj; /* int list[1+n]; */      /* the adjacency list: adj[1], ..., adj[nadj] are nodes adjacent         to node i */      char *flag; /* int flag[1+n]; */      /* flag[j] means that there is edge (i,j) in the graph */      const int *wt; /* int wt[0:n-1]; */      /* weights */      int record;      /* weight of best clique */      int rec_level;      /* number of vertices in best clique */      int *rec; /* int rec[0:n-1]; */      /* best clique so far */      int *clique; /* int clique[0:n-1]; */      /* table for pruning */      int *set; /* int set[0:n-1]; */      /* current clique */};static int is_edge(struct dsa *dsa, int i, int j){     /* returns non-zero if there is edge (i,j) in the graph */      SCG *g = dsa->g;      int n = g->n;      int *adj = dsa->adj;      char *flag = dsa->flag;      int k;      i++, j++;      xassert(1 <= i && i <= n);      xassert(1 <= j && j <= n);      /* build the adjacency list, if necessary */      if (dsa->i != i)      {  for (k = dsa->nadj; k >= 1; k--) flag[adj[k]] = 0;         dsa->i = i;         dsa->nadj = scg_adj_list(g, i, adj);         for (k = dsa->nadj; k >= 1; k--) flag[adj[k]] = 1;      }      return flag[j];}static void sub(struct dsa *dsa, int ct, int table[], int level,      int weight, int l_weight){     int n = dsa->g->n;      const int *wt = dsa->wt;      int *rec = dsa->rec;      int *clique = dsa->clique;      int *set = dsa->set;      int i, j, k, curr_weight, left_weight, *p1, *p2, *newtable;      newtable = xcalloc(n, sizeof(int));      if (ct <= 0)      {  /* 0 or 1 elements left; include these */         if (ct == 0)         {  set[level++] = table[0];            weight += l_weight;         }         if (weight > dsa->record)         {  dsa->record = weight;            dsa->rec_level = level;            for (i = 0; i < level; i++) rec[i] = set[i];         }         goto done;      }      for (i = ct; i >= 0; i--)      {  if ((level == 0) && (i < ct)) goto done;         k = table[i];         if ((level > 0) && (clique[k] <= (dsa->record - weight)))            goto done; /* prune */         set[level] = k;         curr_weight = weight + wt[k];         l_weight -= wt[k];         if (l_weight <= (dsa->record - curr_weight))            goto done; /* prune */         p1 = newtable;         p2 = table;         left_weight = 0;         while (p2 < table + i)         {  j = *p2++;#if 0            if (is_edge(dsa, j, k))#else            /* to minimize building adjacency lists (by mao) */            if (is_edge(dsa, k, j))#endif            {  *p1++ = j;               left_weight += wt[j];            }         }         if (left_weight <= (dsa->record - curr_weight)) continue;         sub(dsa, p1 - newtable - 1, newtable, level + 1, curr_weight,            left_weight);      }done: xfree(newtable);      return;}static int wclique(SCG *g, const int w[], int sol[]){     int n = g->n;      const *wt = &w[1];      struct dsa _dsa, *dsa = &_dsa;      int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos;      xlong_t timer;      xassert(n > 0);      dsa->g = g;      dsa->i = 0;      dsa->nadj = 0;      dsa->adj = xcalloc(1+n, sizeof(int));      dsa->flag = xcalloc(1+n, sizeof(char));      memset(&dsa->flag[1], 0, n);      dsa->wt = wt;      dsa->record = 0;      dsa->rec_level = 0;      dsa->rec = &sol[1];      dsa->clique = xcalloc(n, sizeof(int));      dsa->set = xcalloc(n, sizeof(int));      used = xcalloc(n, sizeof(int));      nwt = xcalloc(n, sizeof(int));      pos = xcalloc(n, sizeof(int));      /* start timer */      timer = xtime();      /* order vertices */      for (i = 0; i < n; i++)      {  nwt[i] = 0;         for (j = 0; j < n; j++)            if (is_edge(dsa, i, j)) nwt[i] += wt[j];      }      for (i = 0; i < n; i++)         used[i] = 0;      for (i = n-1; i >= 0; i--)      {  max_wt = -1;         max_nwt = -1;         for (j = 0; j < n; j++)         {  if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt               && nwt[j] > max_nwt)))            {  max_wt = wt[j];               max_nwt = nwt[j];               p = j;            }         }         pos[i] = p;         used[p] = 1;         for (j = 0; j < n; j++)            if ((!used[j]) && (j != p) && (is_edge(dsa, p, j)))               nwt[j] -= wt[p];      }      /* main routine */      wth = 0;      for (i = 0; i < n; i++)      {  wth += wt[pos[i]];         sub(dsa, i, pos, 0, 0, wth);         dsa->clique[pos[i]] = dsa->record;#if _GLPSCG_DEBUG         ;#else         if (xdifftime(xtime(), timer) >= 5.0 - 0.001)#endif         {  /* print current record and reset timer */            xprintf("level = %d (%d); best = %d\n", i+1, n,               dsa->record);            timer = xtime();         }      }      xfree(dsa->adj);      xfree(dsa->flag);      xfree(dsa->clique);      xfree(dsa->set);      xfree(used);      xfree(nwt);      xfree(pos);      /* return the solution found */      for (i = 1; i <= dsa->rec_level; i++) sol[i]++;      return dsa->rec_level;}/************************************************************************  NAME**  scg_max_clique - find maximum weight clique in given graph**  SYNOPSIS**  #include "glpscg.h"*  int scg_max_clique(SCG *g, const int w[], int list[]);**  DESCRIPTION**  The routine scg_max_clique finds an exact maximum weight clique in*  the given (cliqued) graph.**  On entry the array w specifies node weights in locations w[1], ...*  w[n], where n is the number of nodes in the graph.**  On exit the routine stores numbers of nodes included in the clique*  in locations list[1], ..., list[size], where 0 <= size <= n is the*  clique size.**  RETURNS**  The routine scg_max_clique returns the size of the clique found. */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;}/**********************************************************************/void scg_delete_graph(SCG *g){     /* delete cliqued graph */      dmp_delete_pool(g->pool);      xfree(g->i_ptr);      xfree(g->j_ptr);      xfree(g->c_ptr);      xfree(g->v_ptr);      xfree(g->flag);      xfree(g);      return;}/* eof */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -