/farmR/src/glpscg.c

https://code.google.com/p/javawfm/ · C · 442 lines · 299 code · 21 blank · 122 comment · 76 complexity · 143dd13eb693d4d05aae1d0ff8fc51c1 MD5 · raw file

  1. /* glpscg.c */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000,01,02,03,04,05,06,07,08,2009 Andrew Makhorin,
  6. * Department for Applied Informatics, Moscow Aviation Institute,
  7. * Moscow, Russia. All rights reserved. E-mail: <mao@mai2.rcnet.ru>.
  8. *
  9. * GLPK is free software: you can redistribute it and/or modify it
  10. * under the terms of the GNU General Public License as published by
  11. * the Free Software Foundation, either version 3 of the License, or
  12. * (at your option) any later version.
  13. *
  14. * GLPK is distributed in the hope that it will be useful, but WITHOUT
  15. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  16. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  17. * License for more details.
  18. *
  19. * You should have received a copy of the GNU General Public License
  20. * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
  21. ***********************************************************************/
  22. #include "glpscg.h"
  23. #define _GLPSCG_DEBUG 0
  24. /**********************************************************************/
  25. SCG *scg_create_graph(int n)
  26. { /* create cliqued graph */
  27. SCG *g;
  28. xassert(n >= 0);
  29. g = xmalloc(sizeof(SCG));
  30. g->pool = dmp_create_pool();
  31. g->n_max = 50;
  32. g->nc_max = 10;
  33. g->n = g->nc = 0;
  34. g->i_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));
  35. g->j_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));
  36. g->c_ptr = xcalloc(1+g->nc_max, sizeof(SCGCQE *));
  37. g->v_ptr = xcalloc(1+g->n_max, sizeof(SCGCQE *));
  38. g->flag = xcalloc(1+g->n_max, sizeof(char));
  39. if (n > 0) scg_add_nodes(g, n);
  40. return g;
  41. }
  42. /**********************************************************************/
  43. int scg_add_nodes(SCG *g, int num)
  44. { /* add new nodes to cliqued graph */
  45. int n_new, i;
  46. xassert(num > 0);
  47. /* determine new number of nodes */
  48. n_new = g->n + num;
  49. xassert(n_new > 0);
  50. /* enlarge the room, if necessary */
  51. if (g->n_max < n_new)
  52. { void **save;
  53. while (g->n_max < n_new)
  54. { g->n_max += g->n_max;
  55. xassert(g->n_max > 0);
  56. }
  57. save = (void **)g->i_ptr;
  58. g->i_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));
  59. memcpy(&g->i_ptr[1], &save[1], g->n * sizeof(SCGRIB *));
  60. xfree(save);
  61. save = (void **)g->j_ptr;
  62. g->j_ptr = xcalloc(1+g->n_max, sizeof(SCGRIB *));
  63. memcpy(&g->j_ptr[1], &save[1], g->n * sizeof(SCGRIB *));
  64. xfree(save);
  65. save = (void **)g->v_ptr;
  66. g->v_ptr = xcalloc(1+g->n_max, sizeof(SCGCQE *));
  67. memcpy(&g->v_ptr[1], &save[1], g->n * sizeof(SCGCQE *));
  68. xfree(save);
  69. xfree(g->flag);
  70. g->flag = xcalloc(1+g->n_max, sizeof(char));
  71. memset(&g->flag[1], 0, g->n);
  72. }
  73. /* add new nodes to the end of the node list */
  74. for (i = g->n+1; i <= n_new; i++)
  75. { g->i_ptr[i] = NULL;
  76. g->j_ptr[i] = NULL;
  77. g->v_ptr[i] = NULL;
  78. g->flag[i] = 0;
  79. }
  80. /* set new number of nodes */
  81. g->n = n_new;
  82. /* return number of first node added */
  83. return n_new - num + 1;
  84. }
  85. /**********************************************************************/
  86. SCGRIB *scg_add_edge(SCG *g, int i, int j)
  87. { /* add new edge (i,j) to cliqued graph */
  88. SCGRIB *e;
  89. int t;
  90. xassert(1 <= i && i <= g->n);
  91. xassert(1 <= j && j <= g->n);
  92. if (i > j) t = i, i = j, j = t;
  93. xassert(i < j);
  94. e = dmp_get_atom(g->pool, sizeof(SCGRIB));
  95. e->i = i;
  96. e->j = j;
  97. e->i_prev = NULL;
  98. e->i_next = g->i_ptr[i];
  99. e->j_prev = NULL;
  100. e->j_next = g->j_ptr[j];
  101. if (e->i_next != NULL) e->i_next->i_prev = e;
  102. if (e->j_next != NULL) e->j_next->j_prev = e;
  103. g->i_ptr[i] = g->j_ptr[j] = e;
  104. return e;
  105. }
  106. /***********************************************************************
  107. * NAME
  108. *
  109. * scg_adj_list - get adjacency list for a node of cliqued graph
  110. *
  111. * SYNOPSIS
  112. *
  113. * #include "glpscg.h"
  114. * int scg_adj_list(SCG *g, int i, int adj[]);
  115. *
  116. * DESCRIPTION
  117. *
  118. * For a given node i of the graph g the routine scg_adj_list stores
  119. * numbers of adjacent nodes to locations adj[1], ..., adj[nadj], where
  120. * 0 <= nadj <= n-1 is the number of adjacent nodes, n is the number of
  121. * nodes in the graph. Note that the list of adjacent nodes does not
  122. * include node i.
  123. *
  124. * RETURNS
  125. *
  126. * The routine scg_adj_list returns nadj, which is the number of nodes
  127. * adjacent to node i. */
  128. int scg_adj_list(SCG *g, int i, int adj[])
  129. { int n = g->n;
  130. char *flag = g->flag;
  131. SCGRIB *e;
  132. SCGCQE *p, *q;
  133. int j, c, nadj = 0;
  134. xassert(1 <= i && i <= n);
  135. #if _GLPSCG_DEBUG
  136. for (j = 1; j <= n; j++) xassert(!flag[j]);
  137. #endif
  138. /* go through the list of edges (i,j) and add node j to the
  139. adjacency list */
  140. for (e = g->i_ptr[i]; e != NULL; e = e->i_next)
  141. { j = e->j;
  142. #if _GLPSCG_DEBUG
  143. xassert(i < j && j <= n);
  144. #endif
  145. if (!flag[j]) adj[++nadj] = j, flag[j] = 1;
  146. }
  147. /* go through the list of edges (j,i) and add node j to the
  148. adjacency list */
  149. for (e = g->j_ptr[i]; e != NULL; e = e->j_next)
  150. { j = e->i;
  151. #if _GLPSCG_DEBUG
  152. xassert(1 <= j && j < i);
  153. #endif
  154. if (!flag[j]) adj[++nadj] = j, flag[j] = 1;
  155. }
  156. #if 1
  157. /* not tested yet */
  158. xassert(g->v_ptr[i] == NULL);
  159. #endif
  160. /* go through the list of cliques containing node i */
  161. for (p = g->v_ptr[i]; p != NULL; p = p->v_next)
  162. { c = p->c;
  163. /* clique c contains node i */
  164. #if _GLPSCG_DEBUG
  165. xassert(1 <= c && c <= g->nc);
  166. #endif
  167. /* go through the list of nodes of clique c and add them
  168. (except node i) to the adjacency list */
  169. for (q = g->c_ptr[c]; q != NULL; q = q->c_next)
  170. { j = q->i;
  171. /* clique c contains node j */
  172. #if _GLPSCG_DEBUG
  173. xassert(1 <= j && j <= n);
  174. #endif
  175. if (j != i && !flag[j]) adj[++nadj] = j, flag[j] = 1;
  176. }
  177. }
  178. /* reset the working array */
  179. for (j = 1; j <= nadj; j++) flag[adj[j]] = 0;
  180. #if _GLPSCG_DEBUG
  181. for (j = 1; j <= n; j++) xassert(!flag[j]);
  182. #endif
  183. return nadj;
  184. }
  185. /***********************************************************************
  186. * MAXIMUM WEIGHT CLIQUE
  187. *
  188. * Two subroutines sub and wclique below are used to find a maximum
  189. * weight clique in a given undirected graph. These subroutines are
  190. * slightly modified version of the program WCLIQUE developed by Patric
  191. * Ostergard <http://www.tcs.hut.fi/~pat/wclique.html> and based on
  192. * ideas from the article "P. R. J. Ostergard, A new algorithm for the
  193. * maximum-weight clique problem, submitted for publication", which, in
  194. * turn, is a generalization of the algorithm for unweighted graphs
  195. * presented in "P. R. J. Ostergard, A fast algorithm for the maximum
  196. * clique problem, submitted for publication".
  197. *
  198. * USED WITH PERMISSION OF THE AUTHOR OF THE ORIGINAL CODE. */
  199. struct dsa
  200. { /* dynamic storage area */
  201. SCG *g;
  202. /* given (cliqued) graph */
  203. int i;
  204. /* node number, for which the adjacency list is built and stored
  205. in the arrays adj and flag */
  206. int nadj;
  207. /* size of the adjacency list, 0 <= nadj <= n-1 */
  208. int *adj; /* int list[1+n]; */
  209. /* the adjacency list: adj[1], ..., adj[nadj] are nodes adjacent
  210. to node i */
  211. char *flag; /* int flag[1+n]; */
  212. /* flag[j] means that there is edge (i,j) in the graph */
  213. const int *wt; /* int wt[0:n-1]; */
  214. /* weights */
  215. int record;
  216. /* weight of best clique */
  217. int rec_level;
  218. /* number of vertices in best clique */
  219. int *rec; /* int rec[0:n-1]; */
  220. /* best clique so far */
  221. int *clique; /* int clique[0:n-1]; */
  222. /* table for pruning */
  223. int *set; /* int set[0:n-1]; */
  224. /* current clique */
  225. };
  226. static int is_edge(struct dsa *dsa, int i, int j)
  227. { /* returns non-zero if there is edge (i,j) in the graph */
  228. SCG *g = dsa->g;
  229. int n = g->n;
  230. int *adj = dsa->adj;
  231. char *flag = dsa->flag;
  232. int k;
  233. i++, j++;
  234. xassert(1 <= i && i <= n);
  235. xassert(1 <= j && j <= n);
  236. /* build the adjacency list, if necessary */
  237. if (dsa->i != i)
  238. { for (k = dsa->nadj; k >= 1; k--) flag[adj[k]] = 0;
  239. dsa->i = i;
  240. dsa->nadj = scg_adj_list(g, i, adj);
  241. for (k = dsa->nadj; k >= 1; k--) flag[adj[k]] = 1;
  242. }
  243. return flag[j];
  244. }
  245. static void sub(struct dsa *dsa, int ct, int table[], int level,
  246. int weight, int l_weight)
  247. { int n = dsa->g->n;
  248. const int *wt = dsa->wt;
  249. int *rec = dsa->rec;
  250. int *clique = dsa->clique;
  251. int *set = dsa->set;
  252. int i, j, k, curr_weight, left_weight, *p1, *p2, *newtable;
  253. newtable = xcalloc(n, sizeof(int));
  254. if (ct <= 0)
  255. { /* 0 or 1 elements left; include these */
  256. if (ct == 0)
  257. { set[level++] = table[0];
  258. weight += l_weight;
  259. }
  260. if (weight > dsa->record)
  261. { dsa->record = weight;
  262. dsa->rec_level = level;
  263. for (i = 0; i < level; i++) rec[i] = set[i];
  264. }
  265. goto done;
  266. }
  267. for (i = ct; i >= 0; i--)
  268. { if ((level == 0) && (i < ct)) goto done;
  269. k = table[i];
  270. if ((level > 0) && (clique[k] <= (dsa->record - weight)))
  271. goto done; /* prune */
  272. set[level] = k;
  273. curr_weight = weight + wt[k];
  274. l_weight -= wt[k];
  275. if (l_weight <= (dsa->record - curr_weight))
  276. goto done; /* prune */
  277. p1 = newtable;
  278. p2 = table;
  279. left_weight = 0;
  280. while (p2 < table + i)
  281. { j = *p2++;
  282. #if 0
  283. if (is_edge(dsa, j, k))
  284. #else
  285. /* to minimize building adjacency lists (by mao) */
  286. if (is_edge(dsa, k, j))
  287. #endif
  288. { *p1++ = j;
  289. left_weight += wt[j];
  290. }
  291. }
  292. if (left_weight <= (dsa->record - curr_weight)) continue;
  293. sub(dsa, p1 - newtable - 1, newtable, level + 1, curr_weight,
  294. left_weight);
  295. }
  296. done: xfree(newtable);
  297. return;
  298. }
  299. static int wclique(SCG *g, const int w[], int sol[])
  300. { int n = g->n;
  301. const *wt = &w[1];
  302. struct dsa _dsa, *dsa = &_dsa;
  303. int i, j, p, max_wt, max_nwt, wth, *used, *nwt, *pos;
  304. xlong_t timer;
  305. xassert(n > 0);
  306. dsa->g = g;
  307. dsa->i = 0;
  308. dsa->nadj = 0;
  309. dsa->adj = xcalloc(1+n, sizeof(int));
  310. dsa->flag = xcalloc(1+n, sizeof(char));
  311. memset(&dsa->flag[1], 0, n);
  312. dsa->wt = wt;
  313. dsa->record = 0;
  314. dsa->rec_level = 0;
  315. dsa->rec = &sol[1];
  316. dsa->clique = xcalloc(n, sizeof(int));
  317. dsa->set = xcalloc(n, sizeof(int));
  318. used = xcalloc(n, sizeof(int));
  319. nwt = xcalloc(n, sizeof(int));
  320. pos = xcalloc(n, sizeof(int));
  321. /* start timer */
  322. timer = xtime();
  323. /* order vertices */
  324. for (i = 0; i < n; i++)
  325. { nwt[i] = 0;
  326. for (j = 0; j < n; j++)
  327. if (is_edge(dsa, i, j)) nwt[i] += wt[j];
  328. }
  329. for (i = 0; i < n; i++)
  330. used[i] = 0;
  331. for (i = n-1; i >= 0; i--)
  332. { max_wt = -1;
  333. max_nwt = -1;
  334. for (j = 0; j < n; j++)
  335. { if ((!used[j]) && ((wt[j] > max_wt) || (wt[j] == max_wt
  336. && nwt[j] > max_nwt)))
  337. { max_wt = wt[j];
  338. max_nwt = nwt[j];
  339. p = j;
  340. }
  341. }
  342. pos[i] = p;
  343. used[p] = 1;
  344. for (j = 0; j < n; j++)
  345. if ((!used[j]) && (j != p) && (is_edge(dsa, p, j)))
  346. nwt[j] -= wt[p];
  347. }
  348. /* main routine */
  349. wth = 0;
  350. for (i = 0; i < n; i++)
  351. { wth += wt[pos[i]];
  352. sub(dsa, i, pos, 0, 0, wth);
  353. dsa->clique[pos[i]] = dsa->record;
  354. #if _GLPSCG_DEBUG
  355. ;
  356. #else
  357. if (xdifftime(xtime(), timer) >= 5.0 - 0.001)
  358. #endif
  359. { /* print current record and reset timer */
  360. xprintf("level = %d (%d); best = %d\n", i+1, n,
  361. dsa->record);
  362. timer = xtime();
  363. }
  364. }
  365. xfree(dsa->adj);
  366. xfree(dsa->flag);
  367. xfree(dsa->clique);
  368. xfree(dsa->set);
  369. xfree(used);
  370. xfree(nwt);
  371. xfree(pos);
  372. /* return the solution found */
  373. for (i = 1; i <= dsa->rec_level; i++) sol[i]++;
  374. return dsa->rec_level;
  375. }
  376. /***********************************************************************
  377. * NAME
  378. *
  379. * scg_max_clique - find maximum weight clique in given graph
  380. *
  381. * SYNOPSIS
  382. *
  383. * #include "glpscg.h"
  384. * int scg_max_clique(SCG *g, const int w[], int list[]);
  385. *
  386. * DESCRIPTION
  387. *
  388. * The routine scg_max_clique finds an exact maximum weight clique in
  389. * the given (cliqued) graph.
  390. *
  391. * On entry the array w specifies node weights in locations w[1], ...
  392. * w[n], where n is the number of nodes in the graph.
  393. *
  394. * On exit the routine stores numbers of nodes included in the clique
  395. * in locations list[1], ..., list[size], where 0 <= size <= n is the
  396. * clique size.
  397. *
  398. * RETURNS
  399. *
  400. * The routine scg_max_clique returns the size of the clique found. */
  401. int scg_max_clique(SCG *g, const int w[], int list[])
  402. { int size;
  403. if (g->n == 0)
  404. size = 0;
  405. else
  406. size = wclique(g, w, list);
  407. return size;
  408. }
  409. /**********************************************************************/
  410. void scg_delete_graph(SCG *g)
  411. { /* delete cliqued graph */
  412. dmp_delete_pool(g->pool);
  413. xfree(g->i_ptr);
  414. xfree(g->j_ptr);
  415. xfree(g->c_ptr);
  416. xfree(g->v_ptr);
  417. xfree(g->flag);
  418. xfree(g);
  419. return;
  420. }
  421. /* eof */