glpapi15.c 18 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610
  1. /* glpapi15.c (basic graph and network routines) */
  2. /***********************************************************************
  3. * This code is part of GLPK (GNU Linear Programming Kit).
  4. *
  5. * Copyright (C) 2000, 2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008,
  6. * 2009, 2010 Andrew Makhorin, Department for Applied Informatics,
  7. * Moscow Aviation Institute, Moscow, Russia. All rights reserved.
  8. * E-mail: <mao@gnu.org>.
  9. *
  10. * GLPK is free software: you can redistribute it and/or modify it
  11. * under the terms of the GNU General Public License as published by
  12. * the Free Software Foundation, either version 3 of the License, or
  13. * (at your option) any later version.
  14. *
  15. * GLPK is distributed in the hope that it will be useful, but WITHOUT
  16. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
  17. * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public
  18. * License for more details.
  19. *
  20. * You should have received a copy of the GNU General Public License
  21. * along with GLPK. If not, see <http://www.gnu.org/licenses/>.
  22. ***********************************************************************/
  23. #include "glpapi.h"
  24. /* CAUTION: DO NOT CHANGE THE LIMITS BELOW */
  25. #define NV_MAX 100000000 /* = 100*10^6 */
  26. /* maximal number of vertices in the graph */
  27. #define NA_MAX 500000000 /* = 500*10^6 */
  28. /* maximal number of arcs in the graph */
  29. /***********************************************************************
  30. * NAME
  31. *
  32. * glp_create_graph - create graph
  33. *
  34. * SYNOPSIS
  35. *
  36. * glp_graph *glp_create_graph(int v_size, int a_size);
  37. *
  38. * DESCRIPTION
  39. *
  40. * The routine creates a new graph, which initially is empty, i.e. has
  41. * no vertices and arcs.
  42. *
  43. * The parameter v_size specifies the size of data associated with each
  44. * vertex of the graph (0 to 256 bytes).
  45. *
  46. * The parameter a_size specifies the size of data associated with each
  47. * arc of the graph (0 to 256 bytes).
  48. *
  49. * RETURNS
  50. *
  51. * The routine returns a pointer to the graph created. */
  52. static void create_graph(glp_graph *G, int v_size, int a_size)
  53. { G->pool = dmp_create_pool();
  54. G->name = NULL;
  55. G->nv_max = 50;
  56. G->nv = G->na = 0;
  57. G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *));
  58. G->index = NULL;
  59. G->v_size = v_size;
  60. G->a_size = a_size;
  61. return;
  62. }
  63. glp_graph *glp_create_graph(int v_size, int a_size)
  64. { glp_graph *G;
  65. if (!(0 <= v_size && v_size <= 256))
  66. xerror("glp_create_graph: v_size = %d; invalid size of vertex "
  67. "data\n", v_size);
  68. if (!(0 <= a_size && a_size <= 256))
  69. xerror("glp_create_graph: a_size = %d; invalid size of arc dat"
  70. "a\n", a_size);
  71. G = xmalloc(sizeof(glp_graph));
  72. create_graph(G, v_size, a_size);
  73. return G;
  74. }
  75. /***********************************************************************
  76. * NAME
  77. *
  78. * glp_set_graph_name - assign (change) graph name
  79. *
  80. * SYNOPSIS
  81. *
  82. * void glp_set_graph_name(glp_graph *G, const char *name);
  83. *
  84. * DESCRIPTION
  85. *
  86. * The routine glp_set_graph_name assigns a symbolic name specified by
  87. * the character string name (1 to 255 chars) to the graph.
  88. *
  89. * If the parameter name is NULL or an empty string, the routine erases
  90. * the existing symbolic name of the graph. */
  91. void glp_set_graph_name(glp_graph *G, const char *name)
  92. { if (G->name != NULL)
  93. { dmp_free_atom(G->pool, G->name, strlen(G->name)+1);
  94. G->name = NULL;
  95. }
  96. if (!(name == NULL || name[0] == '\0'))
  97. { int j;
  98. for (j = 0; name[j] != '\0'; j++)
  99. { if (j == 256)
  100. xerror("glp_set_graph_name: graph name too long\n");
  101. if (iscntrl((unsigned char)name[j]))
  102. xerror("glp_set_graph_name: graph name contains invalid "
  103. "character(s)\n");
  104. }
  105. G->name = dmp_get_atom(G->pool, strlen(name)+1);
  106. strcpy(G->name, name);
  107. }
  108. return;
  109. }
  110. /***********************************************************************
  111. * NAME
  112. *
  113. * glp_add_vertices - add new vertices to graph
  114. *
  115. * SYNOPSIS
  116. *
  117. * int glp_add_vertices(glp_graph *G, int nadd);
  118. *
  119. * DESCRIPTION
  120. *
  121. * The routine glp_add_vertices adds nadd vertices to the specified
  122. * graph. New vertices are always added to the end of the vertex list,
  123. * so ordinal numbers of existing vertices remain unchanged.
  124. *
  125. * Being added each new vertex is isolated (has no incident arcs).
  126. *
  127. * RETURNS
  128. *
  129. * The routine glp_add_vertices returns an ordinal number of the first
  130. * new vertex added to the graph. */
  131. int glp_add_vertices(glp_graph *G, int nadd)
  132. { int i, nv_new;
  133. if (nadd < 1)
  134. xerror("glp_add_vertices: nadd = %d; invalid number of vertice"
  135. "s\n", nadd);
  136. if (nadd > NV_MAX - G->nv)
  137. xerror("glp_add_vertices: nadd = %d; too many vertices\n",
  138. nadd);
  139. /* determine new number of vertices */
  140. nv_new = G->nv + nadd;
  141. /* increase the room, if necessary */
  142. if (G->nv_max < nv_new)
  143. { glp_vertex **save = G->v;
  144. while (G->nv_max < nv_new)
  145. { G->nv_max += G->nv_max;
  146. xassert(G->nv_max > 0);
  147. }
  148. G->v = xcalloc(1+G->nv_max, sizeof(glp_vertex *));
  149. memcpy(&G->v[1], &save[1], G->nv * sizeof(glp_vertex *));
  150. xfree(save);
  151. }
  152. /* add new vertices to the end of the vertex list */
  153. for (i = G->nv+1; i <= nv_new; i++)
  154. { glp_vertex *v;
  155. G->v[i] = v = dmp_get_atom(G->pool, sizeof(glp_vertex));
  156. v->i = i;
  157. v->name = NULL;
  158. v->entry = NULL;
  159. if (G->v_size == 0)
  160. v->data = NULL;
  161. else
  162. { v->data = dmp_get_atom(G->pool, G->v_size);
  163. memset(v->data, 0, G->v_size);
  164. }
  165. v->temp = NULL;
  166. v->in = v->out = NULL;
  167. }
  168. /* set new number of vertices */
  169. G->nv = nv_new;
  170. /* return the ordinal number of the first vertex added */
  171. return nv_new - nadd + 1;
  172. }
  173. /**********************************************************************/
  174. void glp_set_vertex_name(glp_graph *G, int i, const char *name)
  175. { /* assign (change) vertex name */
  176. glp_vertex *v;
  177. if (!(1 <= i && i <= G->nv))
  178. xerror("glp_set_vertex_name: i = %d; vertex number out of rang"
  179. "e\n", i);
  180. v = G->v[i];
  181. if (v->name != NULL)
  182. { if (v->entry != NULL)
  183. { xassert(G->index != NULL);
  184. avl_delete_node(G->index, v->entry);
  185. v->entry = NULL;
  186. }
  187. dmp_free_atom(G->pool, v->name, strlen(v->name)+1);
  188. v->name = NULL;
  189. }
  190. if (!(name == NULL || name[0] == '\0'))
  191. { int k;
  192. for (k = 0; name[k] != '\0'; k++)
  193. { if (k == 256)
  194. xerror("glp_set_vertex_name: i = %d; vertex name too lon"
  195. "g\n", i);
  196. if (iscntrl((unsigned char)name[k]))
  197. xerror("glp_set_vertex_name: i = %d; vertex name contain"
  198. "s invalid character(s)\n", i);
  199. }
  200. v->name = dmp_get_atom(G->pool, strlen(name)+1);
  201. strcpy(v->name, name);
  202. if (G->index != NULL)
  203. { xassert(v->entry == NULL);
  204. v->entry = avl_insert_node(G->index, v->name);
  205. avl_set_node_link(v->entry, v);
  206. }
  207. }
  208. return;
  209. }
  210. /***********************************************************************
  211. * NAME
  212. *
  213. * glp_add_arc - add new arc to graph
  214. *
  215. * SYNOPSIS
  216. *
  217. * glp_arc *glp_add_arc(glp_graph *G, int i, int j);
  218. *
  219. * DESCRIPTION
  220. *
  221. * The routine glp_add_arc adds a new arc to the specified graph.
  222. *
  223. * The parameters i and j specify the ordinal numbers of, resp., tail
  224. * and head vertices of the arc. Note that self-loops and multiple arcs
  225. * are allowed.
  226. *
  227. * RETURNS
  228. *
  229. * The routine glp_add_arc returns a pointer to the arc added. */
  230. glp_arc *glp_add_arc(glp_graph *G, int i, int j)
  231. { glp_arc *a;
  232. if (!(1 <= i && i <= G->nv))
  233. xerror("glp_add_arc: i = %d; tail vertex number out of range\n"
  234. , i);
  235. if (!(1 <= j && j <= G->nv))
  236. xerror("glp_add_arc: j = %d; head vertex number out of range\n"
  237. , j);
  238. if (G->na == NA_MAX)
  239. xerror("glp_add_arc: too many arcs\n");
  240. a = dmp_get_atom(G->pool, sizeof(glp_arc));
  241. a->tail = G->v[i];
  242. a->head = G->v[j];
  243. if (G->a_size == 0)
  244. a->data = NULL;
  245. else
  246. { a->data = dmp_get_atom(G->pool, G->a_size);
  247. memset(a->data, 0, G->a_size);
  248. }
  249. a->temp = NULL;
  250. a->t_prev = NULL;
  251. a->t_next = G->v[i]->out;
  252. if (a->t_next != NULL) a->t_next->t_prev = a;
  253. a->h_prev = NULL;
  254. a->h_next = G->v[j]->in;
  255. if (a->h_next != NULL) a->h_next->h_prev = a;
  256. G->v[i]->out = G->v[j]->in = a;
  257. G->na++;
  258. return a;
  259. }
  260. /***********************************************************************
  261. * NAME
  262. *
  263. * glp_del_vertices - delete vertices from graph
  264. *
  265. * SYNOPSIS
  266. *
  267. * void glp_del_vertices(glp_graph *G, int ndel, const int num[]);
  268. *
  269. * DESCRIPTION
  270. *
  271. * The routine glp_del_vertices deletes vertices along with all
  272. * incident arcs from the specified graph. Ordinal numbers of vertices
  273. * to be deleted should be placed in locations num[1], ..., num[ndel],
  274. * ndel > 0.
  275. *
  276. * Note that deleting vertices involves changing ordinal numbers of
  277. * other vertices remaining in the graph. New ordinal numbers of the
  278. * remaining vertices are assigned under the assumption that the
  279. * original order of vertices is not changed. */
  280. void glp_del_vertices(glp_graph *G, int ndel, const int num[])
  281. { glp_vertex *v;
  282. int i, k, nv_new;
  283. /* scan the list of vertices to be deleted */
  284. if (!(1 <= ndel && ndel <= G->nv))
  285. xerror("glp_del_vertices: ndel = %d; invalid number of vertice"
  286. "s\n", ndel);
  287. for (k = 1; k <= ndel; k++)
  288. { /* take the number of vertex to be deleted */
  289. i = num[k];
  290. /* obtain pointer to i-th vertex */
  291. if (!(1 <= i && i <= G->nv))
  292. xerror("glp_del_vertices: num[%d] = %d; vertex number out o"
  293. "f range\n", k, i);
  294. v = G->v[i];
  295. /* check that the vertex is not marked yet */
  296. if (v->i == 0)
  297. xerror("glp_del_vertices: num[%d] = %d; duplicate vertex nu"
  298. "mbers not allowed\n", k, i);
  299. /* erase symbolic name assigned to the vertex */
  300. glp_set_vertex_name(G, i, NULL);
  301. xassert(v->name == NULL);
  302. xassert(v->entry == NULL);
  303. /* free vertex data, if allocated */
  304. if (v->data != NULL)
  305. dmp_free_atom(G->pool, v->data, G->v_size);
  306. /* delete all incoming arcs */
  307. while (v->in != NULL)
  308. glp_del_arc(G, v->in);
  309. /* delete all outgoing arcs */
  310. while (v->out != NULL)
  311. glp_del_arc(G, v->out);
  312. /* mark the vertex to be deleted */
  313. v->i = 0;
  314. }
  315. /* delete all marked vertices from the vertex list */
  316. nv_new = 0;
  317. for (i = 1; i <= G->nv; i++)
  318. { /* obtain pointer to i-th vertex */
  319. v = G->v[i];
  320. /* check if the vertex is marked */
  321. if (v->i == 0)
  322. { /* it is marked, delete it */
  323. dmp_free_atom(G->pool, v, sizeof(glp_vertex));
  324. }
  325. else
  326. { /* it is not marked, keep it */
  327. v->i = ++nv_new;
  328. G->v[v->i] = v;
  329. }
  330. }
  331. /* set new number of vertices in the graph */
  332. G->nv = nv_new;
  333. return;
  334. }
  335. /***********************************************************************
  336. * NAME
  337. *
  338. * glp_del_arc - delete arc from graph
  339. *
  340. * SYNOPSIS
  341. *
  342. * void glp_del_arc(glp_graph *G, glp_arc *a);
  343. *
  344. * DESCRIPTION
  345. *
  346. * The routine glp_del_arc deletes an arc from the specified graph.
  347. * The arc to be deleted must exist. */
  348. void glp_del_arc(glp_graph *G, glp_arc *a)
  349. { /* some sanity checks */
  350. xassert(G->na > 0);
  351. xassert(1 <= a->tail->i && a->tail->i <= G->nv);
  352. xassert(a->tail == G->v[a->tail->i]);
  353. xassert(1 <= a->head->i && a->head->i <= G->nv);
  354. xassert(a->head == G->v[a->head->i]);
  355. /* remove the arc from the list of incoming arcs */
  356. if (a->h_prev == NULL)
  357. a->head->in = a->h_next;
  358. else
  359. a->h_prev->h_next = a->h_next;
  360. if (a->h_next == NULL)
  361. ;
  362. else
  363. a->h_next->h_prev = a->h_prev;
  364. /* remove the arc from the list of outgoing arcs */
  365. if (a->t_prev == NULL)
  366. a->tail->out = a->t_next;
  367. else
  368. a->t_prev->t_next = a->t_next;
  369. if (a->t_next == NULL)
  370. ;
  371. else
  372. a->t_next->t_prev = a->t_prev;
  373. /* free arc data, if allocated */
  374. if (a->data != NULL)
  375. dmp_free_atom(G->pool, a->data, G->a_size);
  376. /* delete the arc from the graph */
  377. dmp_free_atom(G->pool, a, sizeof(glp_arc));
  378. G->na--;
  379. return;
  380. }
  381. /***********************************************************************
  382. * NAME
  383. *
  384. * glp_erase_graph - erase graph content
  385. *
  386. * SYNOPSIS
  387. *
  388. * void glp_erase_graph(glp_graph *G, int v_size, int a_size);
  389. *
  390. * DESCRIPTION
  391. *
  392. * The routine glp_erase_graph erases the content of the specified
  393. * graph. The effect of this operation is the same as if the graph
  394. * would be deleted with the routine glp_delete_graph and then created
  395. * anew with the routine glp_create_graph, with exception that the
  396. * handle (pointer) to the graph remains valid. */
  397. static void delete_graph(glp_graph *G)
  398. { dmp_delete_pool(G->pool);
  399. xfree(G->v);
  400. if (G->index != NULL) avl_delete_tree(G->index);
  401. return;
  402. }
  403. void glp_erase_graph(glp_graph *G, int v_size, int a_size)
  404. { if (!(0 <= v_size && v_size <= 256))
  405. xerror("glp_erase_graph: v_size = %d; invalid size of vertex d"
  406. "ata\n", v_size);
  407. if (!(0 <= a_size && a_size <= 256))
  408. xerror("glp_erase_graph: a_size = %d; invalid size of arc data"
  409. "\n", a_size);
  410. delete_graph(G);
  411. create_graph(G, v_size, a_size);
  412. return;
  413. }
  414. /***********************************************************************
  415. * NAME
  416. *
  417. * glp_delete_graph - delete graph
  418. *
  419. * SYNOPSIS
  420. *
  421. * void glp_delete_graph(glp_graph *G);
  422. *
  423. * DESCRIPTION
  424. *
  425. * The routine glp_delete_graph deletes the specified graph and frees
  426. * all the memory allocated to this program object. */
  427. void glp_delete_graph(glp_graph *G)
  428. { delete_graph(G);
  429. xfree(G);
  430. return;
  431. }
  432. /**********************************************************************/
  433. void glp_create_v_index(glp_graph *G)
  434. { /* create vertex name index */
  435. glp_vertex *v;
  436. int i;
  437. if (G->index == NULL)
  438. { G->index = avl_create_tree(avl_strcmp, NULL);
  439. for (i = 1; i <= G->nv; i++)
  440. { v = G->v[i];
  441. xassert(v->entry == NULL);
  442. if (v->name != NULL)
  443. { v->entry = avl_insert_node(G->index, v->name);
  444. avl_set_node_link(v->entry, v);
  445. }
  446. }
  447. }
  448. return;
  449. }
  450. int glp_find_vertex(glp_graph *G, const char *name)
  451. { /* find vertex by its name */
  452. AVLNODE *node;
  453. int i = 0;
  454. if (G->index == NULL)
  455. xerror("glp_find_vertex: vertex name index does not exist\n");
  456. if (!(name == NULL || name[0] == '\0' || strlen(name) > 255))
  457. { node = avl_find_node(G->index, name);
  458. if (node != NULL)
  459. i = ((glp_vertex *)avl_get_node_link(node))->i;
  460. }
  461. return i;
  462. }
  463. void glp_delete_v_index(glp_graph *G)
  464. { /* delete vertex name index */
  465. int i;
  466. if (G->index != NULL)
  467. { avl_delete_tree(G->index), G->index = NULL;
  468. for (i = 1; i <= G->nv; i++) G->v[i]->entry = NULL;
  469. }
  470. return;
  471. }
  472. /***********************************************************************
  473. * NAME
  474. *
  475. * glp_read_graph - read graph from plain text file
  476. *
  477. * SYNOPSIS
  478. *
  479. * int glp_read_graph(glp_graph *G, const char *fname);
  480. *
  481. * DESCRIPTION
  482. *
  483. * The routine glp_read_graph reads a graph from a plain text file.
  484. *
  485. * RETURNS
  486. *
  487. * If the operation was successful, the routine returns zero. Otherwise
  488. * it prints an error message and returns non-zero. */
  489. int glp_read_graph(glp_graph *G, const char *fname)
  490. { glp_data *data;
  491. jmp_buf jump;
  492. int nv, na, i, j, k, ret;
  493. glp_erase_graph(G, G->v_size, G->a_size);
  494. xprintf("Reading graph from `%s'...\n", fname);
  495. data = glp_sdf_open_file(fname);
  496. if (data == NULL)
  497. { ret = 1;
  498. goto done;
  499. }
  500. if (setjmp(jump))
  501. { ret = 1;
  502. goto done;
  503. }
  504. glp_sdf_set_jump(data, jump);
  505. nv = glp_sdf_read_int(data);
  506. if (nv < 0)
  507. glp_sdf_error(data, "invalid number of vertices\n");
  508. na = glp_sdf_read_int(data);
  509. if (na < 0)
  510. glp_sdf_error(data, "invalid number of arcs\n");
  511. xprintf("Graph has %d vert%s and %d arc%s\n",
  512. nv, nv == 1 ? "ex" : "ices", na, na == 1 ? "" : "s");
  513. if (nv > 0) glp_add_vertices(G, nv);
  514. for (k = 1; k <= na; k++)
  515. { i = glp_sdf_read_int(data);
  516. if (!(1 <= i && i <= nv))
  517. glp_sdf_error(data, "tail vertex number out of range\n");
  518. j = glp_sdf_read_int(data);
  519. if (!(1 <= j && j <= nv))
  520. glp_sdf_error(data, "head vertex number out of range\n");
  521. glp_add_arc(G, i, j);
  522. }
  523. xprintf("%d lines were read\n", glp_sdf_line(data));
  524. ret = 0;
  525. done: if (data != NULL) glp_sdf_close_file(data);
  526. return ret;
  527. }
  528. /***********************************************************************
  529. * NAME
  530. *
  531. * glp_write_graph - write graph to plain text file
  532. *
  533. * SYNOPSIS
  534. *
  535. * int glp_write_graph(glp_graph *G, const char *fname).
  536. *
  537. * DESCRIPTION
  538. *
  539. * The routine glp_write_graph writes the specified graph to a plain
  540. * text file.
  541. *
  542. * RETURNS
  543. *
  544. * If the operation was successful, the routine returns zero. Otherwise
  545. * it prints an error message and returns non-zero. */
  546. int glp_write_graph(glp_graph *G, const char *fname)
  547. { XFILE *fp;
  548. glp_vertex *v;
  549. glp_arc *a;
  550. int i, count, ret;
  551. xprintf("Writing graph to `%s'...\n", fname);
  552. fp = xfopen(fname, "w"), count = 0;
  553. if (fp == NULL)
  554. { xprintf("Unable to create `%s' - %s\n", fname, xerrmsg());
  555. ret = 1;
  556. goto done;
  557. }
  558. xfprintf(fp, "%d %d\n", G->nv, G->na), count++;
  559. for (i = 1; i <= G->nv; i++)
  560. { v = G->v[i];
  561. for (a = v->out; a != NULL; a = a->t_next)
  562. xfprintf(fp, "%d %d\n", a->tail->i, a->head->i), count++;
  563. }
  564. xfflush(fp);
  565. if (xferror(fp))
  566. { xprintf("Write error on `%s' - %s\n", fname, xerrmsg());
  567. ret = 1;
  568. goto done;
  569. }
  570. xprintf("%d lines were written\n", count);
  571. ret = 0;
  572. done: if (fp != NULL) xfclose(fp);
  573. return ret;
  574. }
  575. /* eof */