glpapi17.c 34 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049
  1. /* glpapi17.c (flow network problems) */
  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. #include "glpnet.h"
  25. /***********************************************************************
  26. * NAME
  27. *
  28. * glp_mincost_lp - convert minimum cost flow problem to LP
  29. *
  30. * SYNOPSIS
  31. *
  32. * void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names,
  33. * int v_rhs, int a_low, int a_cap, int a_cost);
  34. *
  35. * DESCRIPTION
  36. *
  37. * The routine glp_mincost_lp builds an LP problem, which corresponds
  38. * to the minimum cost flow problem on the specified network G. */
  39. void glp_mincost_lp(glp_prob *lp, glp_graph *G, int names, int v_rhs,
  40. int a_low, int a_cap, int a_cost)
  41. { glp_vertex *v;
  42. glp_arc *a;
  43. int i, j, type, ind[1+2];
  44. double rhs, low, cap, cost, val[1+2];
  45. if (!(names == GLP_ON || names == GLP_OFF))
  46. xerror("glp_mincost_lp: names = %d; invalid parameter\n",
  47. names);
  48. if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
  49. xerror("glp_mincost_lp: v_rhs = %d; invalid offset\n", v_rhs);
  50. if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
  51. xerror("glp_mincost_lp: a_low = %d; invalid offset\n", a_low);
  52. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  53. xerror("glp_mincost_lp: a_cap = %d; invalid offset\n", a_cap);
  54. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  55. xerror("glp_mincost_lp: a_cost = %d; invalid offset\n", a_cost)
  56. ;
  57. glp_erase_prob(lp);
  58. if (names) glp_set_prob_name(lp, G->name);
  59. if (G->nv > 0) glp_add_rows(lp, G->nv);
  60. for (i = 1; i <= G->nv; i++)
  61. { v = G->v[i];
  62. if (names) glp_set_row_name(lp, i, v->name);
  63. if (v_rhs >= 0)
  64. memcpy(&rhs, (char *)v->data + v_rhs, sizeof(double));
  65. else
  66. rhs = 0.0;
  67. glp_set_row_bnds(lp, i, GLP_FX, rhs, rhs);
  68. }
  69. if (G->na > 0) glp_add_cols(lp, G->na);
  70. for (i = 1, j = 0; i <= G->nv; i++)
  71. { v = G->v[i];
  72. for (a = v->out; a != NULL; a = a->t_next)
  73. { j++;
  74. if (names)
  75. { char name[50+1];
  76. sprintf(name, "x[%d,%d]", a->tail->i, a->head->i);
  77. xassert(strlen(name) < sizeof(name));
  78. glp_set_col_name(lp, j, name);
  79. }
  80. if (a->tail->i != a->head->i)
  81. { ind[1] = a->tail->i, val[1] = +1.0;
  82. ind[2] = a->head->i, val[2] = -1.0;
  83. glp_set_mat_col(lp, j, 2, ind, val);
  84. }
  85. if (a_low >= 0)
  86. memcpy(&low, (char *)a->data + a_low, sizeof(double));
  87. else
  88. low = 0.0;
  89. if (a_cap >= 0)
  90. memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
  91. else
  92. cap = 1.0;
  93. if (cap == DBL_MAX)
  94. type = GLP_LO;
  95. else if (low != cap)
  96. type = GLP_DB;
  97. else
  98. type = GLP_FX;
  99. glp_set_col_bnds(lp, j, type, low, cap);
  100. if (a_cost >= 0)
  101. memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
  102. else
  103. cost = 0.0;
  104. glp_set_obj_coef(lp, j, cost);
  105. }
  106. }
  107. xassert(j == G->na);
  108. return;
  109. }
  110. /**********************************************************************/
  111. int glp_mincost_okalg(glp_graph *G, int v_rhs, int a_low, int a_cap,
  112. int a_cost, double *sol, int a_x, int v_pi)
  113. { /* find minimum-cost flow with out-of-kilter algorithm */
  114. glp_vertex *v;
  115. glp_arc *a;
  116. int nv, na, i, k, s, t, *tail, *head, *low, *cap, *cost, *x, *pi,
  117. ret;
  118. double sum, temp;
  119. if (v_rhs >= 0 && v_rhs > G->v_size - (int)sizeof(double))
  120. xerror("glp_mincost_okalg: v_rhs = %d; invalid offset\n",
  121. v_rhs);
  122. if (a_low >= 0 && a_low > G->a_size - (int)sizeof(double))
  123. xerror("glp_mincost_okalg: a_low = %d; invalid offset\n",
  124. a_low);
  125. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  126. xerror("glp_mincost_okalg: a_cap = %d; invalid offset\n",
  127. a_cap);
  128. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  129. xerror("glp_mincost_okalg: a_cost = %d; invalid offset\n",
  130. a_cost);
  131. if (a_x >= 0 && a_x > G->a_size - (int)sizeof(double))
  132. xerror("glp_mincost_okalg: a_x = %d; invalid offset\n", a_x);
  133. if (v_pi >= 0 && v_pi > G->v_size - (int)sizeof(double))
  134. xerror("glp_mincost_okalg: v_pi = %d; invalid offset\n", v_pi);
  135. /* s is artificial source node */
  136. s = G->nv + 1;
  137. /* t is artificial sink node */
  138. t = s + 1;
  139. /* nv is the total number of nodes in the resulting network */
  140. nv = t;
  141. /* na is the total number of arcs in the resulting network */
  142. na = G->na + 1;
  143. for (i = 1; i <= G->nv; i++)
  144. { v = G->v[i];
  145. if (v_rhs >= 0)
  146. memcpy(&temp, (char *)v->data + v_rhs, sizeof(double));
  147. else
  148. temp = 0.0;
  149. if (temp != 0.0) na++;
  150. }
  151. /* allocate working arrays */
  152. tail = xcalloc(1+na, sizeof(int));
  153. head = xcalloc(1+na, sizeof(int));
  154. low = xcalloc(1+na, sizeof(int));
  155. cap = xcalloc(1+na, sizeof(int));
  156. cost = xcalloc(1+na, sizeof(int));
  157. x = xcalloc(1+na, sizeof(int));
  158. pi = xcalloc(1+nv, sizeof(int));
  159. /* construct the resulting network */
  160. k = 0;
  161. /* (original arcs) */
  162. for (i = 1; i <= G->nv; i++)
  163. { v = G->v[i];
  164. for (a = v->out; a != NULL; a = a->t_next)
  165. { k++;
  166. tail[k] = a->tail->i;
  167. head[k] = a->head->i;
  168. if (tail[k] == head[k])
  169. { ret = GLP_EDATA;
  170. goto done;
  171. }
  172. if (a_low >= 0)
  173. memcpy(&temp, (char *)a->data + a_low, sizeof(double));
  174. else
  175. temp = 0.0;
  176. if (!(0.0 <= temp && temp <= (double)INT_MAX &&
  177. temp == floor(temp)))
  178. { ret = GLP_EDATA;
  179. goto done;
  180. }
  181. low[k] = (int)temp;
  182. if (a_cap >= 0)
  183. memcpy(&temp, (char *)a->data + a_cap, sizeof(double));
  184. else
  185. temp = 1.0;
  186. if (!((double)low[k] <= temp && temp <= (double)INT_MAX &&
  187. temp == floor(temp)))
  188. { ret = GLP_EDATA;
  189. goto done;
  190. }
  191. cap[k] = (int)temp;
  192. if (a_cost >= 0)
  193. memcpy(&temp, (char *)a->data + a_cost, sizeof(double));
  194. else
  195. temp = 0.0;
  196. if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp)))
  197. { ret = GLP_EDATA;
  198. goto done;
  199. }
  200. cost[k] = (int)temp;
  201. }
  202. }
  203. /* (artificial arcs) */
  204. sum = 0.0;
  205. for (i = 1; i <= G->nv; i++)
  206. { v = G->v[i];
  207. if (v_rhs >= 0)
  208. memcpy(&temp, (char *)v->data + v_rhs, sizeof(double));
  209. else
  210. temp = 0.0;
  211. if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp)))
  212. { ret = GLP_EDATA;
  213. goto done;
  214. }
  215. if (temp > 0.0)
  216. { /* artificial arc from s to original source i */
  217. k++;
  218. tail[k] = s;
  219. head[k] = i;
  220. low[k] = cap[k] = (int)(+temp); /* supply */
  221. cost[k] = 0;
  222. sum += (double)temp;
  223. }
  224. else if (temp < 0.0)
  225. { /* artificial arc from original sink i to t */
  226. k++;
  227. tail[k] = i;
  228. head[k] = t;
  229. low[k] = cap[k] = (int)(-temp); /* demand */
  230. cost[k] = 0;
  231. }
  232. }
  233. /* (feedback arc from t to s) */
  234. k++;
  235. xassert(k == na);
  236. tail[k] = t;
  237. head[k] = s;
  238. if (sum > (double)INT_MAX)
  239. { ret = GLP_EDATA;
  240. goto done;
  241. }
  242. low[k] = cap[k] = (int)sum; /* total supply/demand */
  243. cost[k] = 0;
  244. /* find minimal-cost circulation in the resulting network */
  245. ret = okalg(nv, na, tail, head, low, cap, cost, x, pi);
  246. switch (ret)
  247. { case 0:
  248. /* optimal circulation found */
  249. ret = 0;
  250. break;
  251. case 1:
  252. /* no feasible circulation exists */
  253. ret = GLP_ENOPFS;
  254. break;
  255. case 2:
  256. /* integer overflow occured */
  257. ret = GLP_ERANGE;
  258. goto done;
  259. case 3:
  260. /* optimality test failed (logic error) */
  261. ret = GLP_EFAIL;
  262. goto done;
  263. default:
  264. xassert(ret != ret);
  265. }
  266. /* store solution components */
  267. /* (objective function = the total cost) */
  268. if (sol != NULL)
  269. { temp = 0.0;
  270. for (k = 1; k <= na; k++)
  271. temp += (double)cost[k] * (double)x[k];
  272. *sol = temp;
  273. }
  274. /* (arc flows) */
  275. if (a_x >= 0)
  276. { k = 0;
  277. for (i = 1; i <= G->nv; i++)
  278. { v = G->v[i];
  279. for (a = v->out; a != NULL; a = a->t_next)
  280. { temp = (double)x[++k];
  281. memcpy((char *)a->data + a_x, &temp, sizeof(double));
  282. }
  283. }
  284. }
  285. /* (node potentials = Lagrange multipliers) */
  286. if (v_pi >= 0)
  287. { for (i = 1; i <= G->nv; i++)
  288. { v = G->v[i];
  289. temp = - (double)pi[i];
  290. memcpy((char *)v->data + v_pi, &temp, sizeof(double));
  291. }
  292. }
  293. done: /* free working arrays */
  294. xfree(tail);
  295. xfree(head);
  296. xfree(low);
  297. xfree(cap);
  298. xfree(cost);
  299. xfree(x);
  300. xfree(pi);
  301. return ret;
  302. }
  303. /***********************************************************************
  304. * NAME
  305. *
  306. * glp_maxflow_lp - convert maximum flow problem to LP
  307. *
  308. * SYNOPSIS
  309. *
  310. * void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s,
  311. * int t, int a_cap);
  312. *
  313. * DESCRIPTION
  314. *
  315. * The routine glp_maxflow_lp builds an LP problem, which corresponds
  316. * to the maximum flow problem on the specified network G. */
  317. void glp_maxflow_lp(glp_prob *lp, glp_graph *G, int names, int s,
  318. int t, int a_cap)
  319. { glp_vertex *v;
  320. glp_arc *a;
  321. int i, j, type, ind[1+2];
  322. double cap, val[1+2];
  323. if (!(names == GLP_ON || names == GLP_OFF))
  324. xerror("glp_maxflow_lp: names = %d; invalid parameter\n",
  325. names);
  326. if (!(1 <= s && s <= G->nv))
  327. xerror("glp_maxflow_lp: s = %d; source node number out of rang"
  328. "e\n", s);
  329. if (!(1 <= t && t <= G->nv))
  330. xerror("glp_maxflow_lp: t = %d: sink node number out of range "
  331. "\n", t);
  332. if (s == t)
  333. xerror("glp_maxflow_lp: s = t = %d; source and sink nodes must"
  334. " be distinct\n", s);
  335. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  336. xerror("glp_maxflow_lp: a_cap = %d; invalid offset\n", a_cap);
  337. glp_erase_prob(lp);
  338. if (names) glp_set_prob_name(lp, G->name);
  339. glp_set_obj_dir(lp, GLP_MAX);
  340. glp_add_rows(lp, G->nv);
  341. for (i = 1; i <= G->nv; i++)
  342. { v = G->v[i];
  343. if (names) glp_set_row_name(lp, i, v->name);
  344. if (i == s)
  345. type = GLP_LO;
  346. else if (i == t)
  347. type = GLP_UP;
  348. else
  349. type = GLP_FX;
  350. glp_set_row_bnds(lp, i, type, 0.0, 0.0);
  351. }
  352. if (G->na > 0) glp_add_cols(lp, G->na);
  353. for (i = 1, j = 0; i <= G->nv; i++)
  354. { v = G->v[i];
  355. for (a = v->out; a != NULL; a = a->t_next)
  356. { j++;
  357. if (names)
  358. { char name[50+1];
  359. sprintf(name, "x[%d,%d]", a->tail->i, a->head->i);
  360. xassert(strlen(name) < sizeof(name));
  361. glp_set_col_name(lp, j, name);
  362. }
  363. if (a->tail->i != a->head->i)
  364. { ind[1] = a->tail->i, val[1] = +1.0;
  365. ind[2] = a->head->i, val[2] = -1.0;
  366. glp_set_mat_col(lp, j, 2, ind, val);
  367. }
  368. if (a_cap >= 0)
  369. memcpy(&cap, (char *)a->data + a_cap, sizeof(double));
  370. else
  371. cap = 1.0;
  372. if (cap == DBL_MAX)
  373. type = GLP_LO;
  374. else if (cap != 0.0)
  375. type = GLP_DB;
  376. else
  377. type = GLP_FX;
  378. glp_set_col_bnds(lp, j, type, 0.0, cap);
  379. if (a->tail->i == s)
  380. glp_set_obj_coef(lp, j, +1.0);
  381. else if (a->head->i == s)
  382. glp_set_obj_coef(lp, j, -1.0);
  383. }
  384. }
  385. xassert(j == G->na);
  386. return;
  387. }
  388. int glp_maxflow_ffalg(glp_graph *G, int s, int t, int a_cap,
  389. double *sol, int a_x, int v_cut)
  390. { /* find maximal flow with Ford-Fulkerson algorithm */
  391. glp_vertex *v;
  392. glp_arc *a;
  393. int nv, na, i, k, flag, *tail, *head, *cap, *x, ret;
  394. char *cut;
  395. double temp;
  396. if (!(1 <= s && s <= G->nv))
  397. xerror("glp_maxflow_ffalg: s = %d; source node number out of r"
  398. "ange\n", s);
  399. if (!(1 <= t && t <= G->nv))
  400. xerror("glp_maxflow_ffalg: t = %d: sink node number out of ran"
  401. "ge\n", t);
  402. if (s == t)
  403. xerror("glp_maxflow_ffalg: s = t = %d; source and sink nodes m"
  404. "ust be distinct\n", s);
  405. if (a_cap >= 0 && a_cap > G->a_size - (int)sizeof(double))
  406. xerror("glp_maxflow_ffalg: a_cap = %d; invalid offset\n",
  407. a_cap);
  408. if (v_cut >= 0 && v_cut > G->v_size - (int)sizeof(int))
  409. xerror("glp_maxflow_ffalg: v_cut = %d; invalid offset\n",
  410. v_cut);
  411. /* allocate working arrays */
  412. nv = G->nv;
  413. na = G->na;
  414. tail = xcalloc(1+na, sizeof(int));
  415. head = xcalloc(1+na, sizeof(int));
  416. cap = xcalloc(1+na, sizeof(int));
  417. x = xcalloc(1+na, sizeof(int));
  418. if (v_cut < 0)
  419. cut = NULL;
  420. else
  421. cut = xcalloc(1+nv, sizeof(char));
  422. /* copy the flow network */
  423. k = 0;
  424. for (i = 1; i <= G->nv; i++)
  425. { v = G->v[i];
  426. for (a = v->out; a != NULL; a = a->t_next)
  427. { k++;
  428. tail[k] = a->tail->i;
  429. head[k] = a->head->i;
  430. if (tail[k] == head[k])
  431. { ret = GLP_EDATA;
  432. goto done;
  433. }
  434. if (a_cap >= 0)
  435. memcpy(&temp, (char *)a->data + a_cap, sizeof(double));
  436. else
  437. temp = 1.0;
  438. if (!(0.0 <= temp && temp <= (double)INT_MAX &&
  439. temp == floor(temp)))
  440. { ret = GLP_EDATA;
  441. goto done;
  442. }
  443. cap[k] = (int)temp;
  444. }
  445. }
  446. xassert(k == na);
  447. /* find maximal flow in the flow network */
  448. ffalg(nv, na, tail, head, s, t, cap, x, cut);
  449. ret = 0;
  450. /* store solution components */
  451. /* (objective function = total flow through the network) */
  452. if (sol != NULL)
  453. { temp = 0.0;
  454. for (k = 1; k <= na; k++)
  455. { if (tail[k] == s)
  456. temp += (double)x[k];
  457. else if (head[k] == s)
  458. temp -= (double)x[k];
  459. }
  460. *sol = temp;
  461. }
  462. /* (arc flows) */
  463. if (a_x >= 0)
  464. { k = 0;
  465. for (i = 1; i <= G->nv; i++)
  466. { v = G->v[i];
  467. for (a = v->out; a != NULL; a = a->t_next)
  468. { temp = (double)x[++k];
  469. memcpy((char *)a->data + a_x, &temp, sizeof(double));
  470. }
  471. }
  472. }
  473. /* (node flags) */
  474. if (v_cut >= 0)
  475. { for (i = 1; i <= G->nv; i++)
  476. { v = G->v[i];
  477. flag = cut[i];
  478. memcpy((char *)v->data + v_cut, &flag, sizeof(int));
  479. }
  480. }
  481. done: /* free working arrays */
  482. xfree(tail);
  483. xfree(head);
  484. xfree(cap);
  485. xfree(x);
  486. if (cut != NULL) xfree(cut);
  487. return ret;
  488. }
  489. /***********************************************************************
  490. * NAME
  491. *
  492. * glp_check_asnprob - check correctness of assignment problem data
  493. *
  494. * SYNOPSIS
  495. *
  496. * int glp_check_asnprob(glp_graph *G, int v_set);
  497. *
  498. * RETURNS
  499. *
  500. * If the specified assignment problem data are correct, the routine
  501. * glp_check_asnprob returns zero, otherwise, non-zero. */
  502. int glp_check_asnprob(glp_graph *G, int v_set)
  503. { glp_vertex *v;
  504. int i, k, ret = 0;
  505. if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
  506. xerror("glp_check_asnprob: v_set = %d; invalid offset\n",
  507. v_set);
  508. for (i = 1; i <= G->nv; i++)
  509. { v = G->v[i];
  510. if (v_set >= 0)
  511. { memcpy(&k, (char *)v->data + v_set, sizeof(int));
  512. if (k == 0)
  513. { if (v->in != NULL)
  514. { ret = 1;
  515. break;
  516. }
  517. }
  518. else if (k == 1)
  519. { if (v->out != NULL)
  520. { ret = 2;
  521. break;
  522. }
  523. }
  524. else
  525. { ret = 3;
  526. break;
  527. }
  528. }
  529. else
  530. { if (v->in != NULL && v->out != NULL)
  531. { ret = 4;
  532. break;
  533. }
  534. }
  535. }
  536. return ret;
  537. }
  538. /***********************************************************************
  539. * NAME
  540. *
  541. * glp_asnprob_lp - convert assignment problem to LP
  542. *
  543. * SYNOPSIS
  544. *
  545. * int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names,
  546. * int v_set, int a_cost);
  547. *
  548. * DESCRIPTION
  549. *
  550. * The routine glp_asnprob_lp builds an LP problem, which corresponds
  551. * to the assignment problem on the specified graph G.
  552. *
  553. * RETURNS
  554. *
  555. * If the LP problem has been successfully built, the routine returns
  556. * zero, otherwise, non-zero. */
  557. int glp_asnprob_lp(glp_prob *P, int form, glp_graph *G, int names,
  558. int v_set, int a_cost)
  559. { glp_vertex *v;
  560. glp_arc *a;
  561. int i, j, ret, ind[1+2];
  562. double cost, val[1+2];
  563. if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX ||
  564. form == GLP_ASN_MMP))
  565. xerror("glp_asnprob_lp: form = %d; invalid parameter\n",
  566. form);
  567. if (!(names == GLP_ON || names == GLP_OFF))
  568. xerror("glp_asnprob_lp: names = %d; invalid parameter\n",
  569. names);
  570. if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
  571. xerror("glp_asnprob_lp: v_set = %d; invalid offset\n",
  572. v_set);
  573. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  574. xerror("glp_asnprob_lp: a_cost = %d; invalid offset\n",
  575. a_cost);
  576. ret = glp_check_asnprob(G, v_set);
  577. if (ret != 0) goto done;
  578. glp_erase_prob(P);
  579. if (names) glp_set_prob_name(P, G->name);
  580. glp_set_obj_dir(P, form == GLP_ASN_MIN ? GLP_MIN : GLP_MAX);
  581. if (G->nv > 0) glp_add_rows(P, G->nv);
  582. for (i = 1; i <= G->nv; i++)
  583. { v = G->v[i];
  584. if (names) glp_set_row_name(P, i, v->name);
  585. glp_set_row_bnds(P, i, form == GLP_ASN_MMP ? GLP_UP : GLP_FX,
  586. 1.0, 1.0);
  587. }
  588. if (G->na > 0) glp_add_cols(P, G->na);
  589. for (i = 1, j = 0; i <= G->nv; i++)
  590. { v = G->v[i];
  591. for (a = v->out; a != NULL; a = a->t_next)
  592. { j++;
  593. if (names)
  594. { char name[50+1];
  595. sprintf(name, "x[%d,%d]", a->tail->i, a->head->i);
  596. xassert(strlen(name) < sizeof(name));
  597. glp_set_col_name(P, j, name);
  598. }
  599. ind[1] = a->tail->i, val[1] = +1.0;
  600. ind[2] = a->head->i, val[2] = +1.0;
  601. glp_set_mat_col(P, j, 2, ind, val);
  602. glp_set_col_bnds(P, j, GLP_DB, 0.0, 1.0);
  603. if (a_cost >= 0)
  604. memcpy(&cost, (char *)a->data + a_cost, sizeof(double));
  605. else
  606. cost = 1.0;
  607. glp_set_obj_coef(P, j, cost);
  608. }
  609. }
  610. xassert(j == G->na);
  611. done: return ret;
  612. }
  613. /**********************************************************************/
  614. int glp_asnprob_okalg(int form, glp_graph *G, int v_set, int a_cost,
  615. double *sol, int a_x)
  616. { /* solve assignment problem with out-of-kilter algorithm */
  617. glp_vertex *v;
  618. glp_arc *a;
  619. int nv, na, i, k, *tail, *head, *low, *cap, *cost, *x, *pi, ret;
  620. double temp;
  621. if (!(form == GLP_ASN_MIN || form == GLP_ASN_MAX ||
  622. form == GLP_ASN_MMP))
  623. xerror("glp_asnprob_okalg: form = %d; invalid parameter\n",
  624. form);
  625. if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
  626. xerror("glp_asnprob_okalg: v_set = %d; invalid offset\n",
  627. v_set);
  628. if (a_cost >= 0 && a_cost > G->a_size - (int)sizeof(double))
  629. xerror("glp_asnprob_okalg: a_cost = %d; invalid offset\n",
  630. a_cost);
  631. if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int))
  632. xerror("glp_asnprob_okalg: a_x = %d; invalid offset\n", a_x);
  633. if (glp_check_asnprob(G, v_set))
  634. return GLP_EDATA;
  635. /* nv is the total number of nodes in the resulting network */
  636. nv = G->nv + 1;
  637. /* na is the total number of arcs in the resulting network */
  638. na = G->na + G->nv;
  639. /* allocate working arrays */
  640. tail = xcalloc(1+na, sizeof(int));
  641. head = xcalloc(1+na, sizeof(int));
  642. low = xcalloc(1+na, sizeof(int));
  643. cap = xcalloc(1+na, sizeof(int));
  644. cost = xcalloc(1+na, sizeof(int));
  645. x = xcalloc(1+na, sizeof(int));
  646. pi = xcalloc(1+nv, sizeof(int));
  647. /* construct the resulting network */
  648. k = 0;
  649. /* (original arcs) */
  650. for (i = 1; i <= G->nv; i++)
  651. { v = G->v[i];
  652. for (a = v->out; a != NULL; a = a->t_next)
  653. { k++;
  654. tail[k] = a->tail->i;
  655. head[k] = a->head->i;
  656. low[k] = 0;
  657. cap[k] = 1;
  658. if (a_cost >= 0)
  659. memcpy(&temp, (char *)a->data + a_cost, sizeof(double));
  660. else
  661. temp = 1.0;
  662. if (!(fabs(temp) <= (double)INT_MAX && temp == floor(temp)))
  663. { ret = GLP_EDATA;
  664. goto done;
  665. }
  666. cost[k] = (int)temp;
  667. if (form != GLP_ASN_MIN) cost[k] = - cost[k];
  668. }
  669. }
  670. /* (artificial arcs) */
  671. for (i = 1; i <= G->nv; i++)
  672. { v = G->v[i];
  673. k++;
  674. if (v->out == NULL)
  675. tail[k] = i, head[k] = nv;
  676. else if (v->in == NULL)
  677. tail[k] = nv, head[k] = i;
  678. else
  679. xassert(v != v);
  680. low[k] = (form == GLP_ASN_MMP ? 0 : 1);
  681. cap[k] = 1;
  682. cost[k] = 0;
  683. }
  684. xassert(k == na);
  685. /* find minimal-cost circulation in the resulting network */
  686. ret = okalg(nv, na, tail, head, low, cap, cost, x, pi);
  687. switch (ret)
  688. { case 0:
  689. /* optimal circulation found */
  690. ret = 0;
  691. break;
  692. case 1:
  693. /* no feasible circulation exists */
  694. ret = GLP_ENOPFS;
  695. break;
  696. case 2:
  697. /* integer overflow occured */
  698. ret = GLP_ERANGE;
  699. goto done;
  700. case 3:
  701. /* optimality test failed (logic error) */
  702. ret = GLP_EFAIL;
  703. goto done;
  704. default:
  705. xassert(ret != ret);
  706. }
  707. /* store solution components */
  708. /* (objective function = the total cost) */
  709. if (sol != NULL)
  710. { temp = 0.0;
  711. for (k = 1; k <= na; k++)
  712. temp += (double)cost[k] * (double)x[k];
  713. if (form != GLP_ASN_MIN) temp = - temp;
  714. *sol = temp;
  715. }
  716. /* (arc flows) */
  717. if (a_x >= 0)
  718. { k = 0;
  719. for (i = 1; i <= G->nv; i++)
  720. { v = G->v[i];
  721. for (a = v->out; a != NULL; a = a->t_next)
  722. { k++;
  723. if (ret == 0)
  724. xassert(x[k] == 0 || x[k] == 1);
  725. memcpy((char *)a->data + a_x, &x[k], sizeof(int));
  726. }
  727. }
  728. }
  729. done: /* free working arrays */
  730. xfree(tail);
  731. xfree(head);
  732. xfree(low);
  733. xfree(cap);
  734. xfree(cost);
  735. xfree(x);
  736. xfree(pi);
  737. return ret;
  738. }
  739. /***********************************************************************
  740. * NAME
  741. *
  742. * glp_asnprob_hall - find bipartite matching of maximum cardinality
  743. *
  744. * SYNOPSIS
  745. *
  746. * int glp_asnprob_hall(glp_graph *G, int v_set, int a_x);
  747. *
  748. * DESCRIPTION
  749. *
  750. * The routine glp_asnprob_hall finds a matching of maximal cardinality
  751. * in the specified bipartite graph G. It uses a version of the Fortran
  752. * routine MC21A developed by I.S.Duff [1], which implements Hall's
  753. * algorithm [2].
  754. *
  755. * RETURNS
  756. *
  757. * The routine glp_asnprob_hall returns the cardinality of the matching
  758. * found. However, if the specified graph is incorrect (as detected by
  759. * the routine glp_check_asnprob), the routine returns negative value.
  760. *
  761. * REFERENCES
  762. *
  763. * 1. I.S.Duff, Algorithm 575: Permutations for zero-free diagonal, ACM
  764. * Trans. on Math. Softw. 7 (1981), 387-390.
  765. *
  766. * 2. M.Hall, "An Algorithm for distinct representatives," Amer. Math.
  767. * Monthly 63 (1956), 716-717. */
  768. int glp_asnprob_hall(glp_graph *G, int v_set, int a_x)
  769. { glp_vertex *v;
  770. glp_arc *a;
  771. int card, i, k, loc, n, n1, n2, xij;
  772. int *num, *icn, *ip, *lenr, *iperm, *pr, *arp, *cv, *out;
  773. if (v_set >= 0 && v_set > G->v_size - (int)sizeof(int))
  774. xerror("glp_asnprob_hall: v_set = %d; invalid offset\n",
  775. v_set);
  776. if (a_x >= 0 && a_x > G->a_size - (int)sizeof(int))
  777. xerror("glp_asnprob_hall: a_x = %d; invalid offset\n", a_x);
  778. if (glp_check_asnprob(G, v_set))
  779. return -1;
  780. /* determine the number of vertices in sets R and S and renumber
  781. vertices in S which correspond to columns of the matrix; skip
  782. all isolated vertices */
  783. num = xcalloc(1+G->nv, sizeof(int));
  784. n1 = n2 = 0;
  785. for (i = 1; i <= G->nv; i++)
  786. { v = G->v[i];
  787. if (v->in == NULL && v->out != NULL)
  788. n1++, num[i] = 0; /* vertex in R */
  789. else if (v->in != NULL && v->out == NULL)
  790. n2++, num[i] = n2; /* vertex in S */
  791. else
  792. { xassert(v->in == NULL && v->out == NULL);
  793. num[i] = -1; /* isolated vertex */
  794. }
  795. }
  796. /* the matrix must be square, thus, if it has more columns than
  797. rows, extra rows will be just empty, and vice versa */
  798. n = (n1 >= n2 ? n1 : n2);
  799. /* allocate working arrays */
  800. icn = xcalloc(1+G->na, sizeof(int));
  801. ip = xcalloc(1+n, sizeof(int));
  802. lenr = xcalloc(1+n, sizeof(int));
  803. iperm = xcalloc(1+n, sizeof(int));
  804. pr = xcalloc(1+n, sizeof(int));
  805. arp = xcalloc(1+n, sizeof(int));
  806. cv = xcalloc(1+n, sizeof(int));
  807. out = xcalloc(1+n, sizeof(int));
  808. /* build the adjacency matrix of the bipartite graph in row-wise
  809. format (rows are vertices in R, columns are vertices in S) */
  810. k = 0, loc = 1;
  811. for (i = 1; i <= G->nv; i++)
  812. { if (num[i] != 0) continue;
  813. /* vertex i in R */
  814. ip[++k] = loc;
  815. v = G->v[i];
  816. for (a = v->out; a != NULL; a = a->t_next)
  817. { xassert(num[a->head->i] != 0);
  818. icn[loc++] = num[a->head->i];
  819. }
  820. lenr[k] = loc - ip[k];
  821. }
  822. xassert(loc-1 == G->na);
  823. /* make all extra rows empty (all extra columns are empty due to
  824. the row-wise format used) */
  825. for (k++; k <= n; k++)
  826. ip[k] = loc, lenr[k] = 0;
  827. /* find a row permutation that maximizes the number of non-zeros
  828. on the main diagonal */
  829. card = mc21a(n, icn, ip, lenr, iperm, pr, arp, cv, out);
  830. #if 1 /* 18/II-2010 */
  831. /* FIXED: if card = n, arp remains clobbered on exit */
  832. for (i = 1; i <= n; i++)
  833. arp[i] = 0;
  834. for (i = 1; i <= card; i++)
  835. { k = iperm[i];
  836. xassert(1 <= k && k <= n);
  837. xassert(arp[k] == 0);
  838. arp[k] = i;
  839. }
  840. #endif
  841. /* store solution, if necessary */
  842. if (a_x < 0) goto skip;
  843. k = 0;
  844. for (i = 1; i <= G->nv; i++)
  845. { if (num[i] != 0) continue;
  846. /* vertex i in R */
  847. k++;
  848. v = G->v[i];
  849. for (a = v->out; a != NULL; a = a->t_next)
  850. { /* arp[k] is the number of matched column or zero */
  851. if (arp[k] == num[a->head->i])
  852. { xassert(arp[k] != 0);
  853. xij = 1;
  854. }
  855. else
  856. xij = 0;
  857. memcpy((char *)a->data + a_x, &xij, sizeof(int));
  858. }
  859. }
  860. skip: /* free working arrays */
  861. xfree(num);
  862. xfree(icn);
  863. xfree(ip);
  864. xfree(lenr);
  865. xfree(iperm);
  866. xfree(pr);
  867. xfree(arp);
  868. xfree(cv);
  869. xfree(out);
  870. return card;
  871. }
  872. /***********************************************************************
  873. * NAME
  874. *
  875. * glp_cpp - solve critical path problem
  876. *
  877. * SYNOPSIS
  878. *
  879. * double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls);
  880. *
  881. * DESCRIPTION
  882. *
  883. * The routine glp_cpp solves the critical path problem represented in
  884. * the form of the project network.
  885. *
  886. * The parameter G is a pointer to the graph object, which specifies
  887. * the project network. This graph must be acyclic. Multiple arcs are
  888. * allowed being considered as single arcs.
  889. *
  890. * The parameter v_t specifies an offset of the field of type double
  891. * in the vertex data block, which contains time t[i] >= 0 needed to
  892. * perform corresponding job j. If v_t < 0, it is assumed that t[i] = 1
  893. * for all jobs.
  894. *
  895. * The parameter v_es specifies an offset of the field of type double
  896. * in the vertex data block, to which the routine stores earliest start
  897. * time for corresponding job. If v_es < 0, this time is not stored.
  898. *
  899. * The parameter v_ls specifies an offset of the field of type double
  900. * in the vertex data block, to which the routine stores latest start
  901. * time for corresponding job. If v_ls < 0, this time is not stored.
  902. *
  903. * RETURNS
  904. *
  905. * The routine glp_cpp returns the minimal project duration, that is,
  906. * minimal time needed to perform all jobs in the project. */
  907. static void sorting(glp_graph *G, int list[]);
  908. double glp_cpp(glp_graph *G, int v_t, int v_es, int v_ls)
  909. { glp_vertex *v;
  910. glp_arc *a;
  911. int i, j, k, nv, *list;
  912. double temp, total, *t, *es, *ls;
  913. if (v_t >= 0 && v_t > G->v_size - (int)sizeof(double))
  914. xerror("glp_cpp: v_t = %d; invalid offset\n", v_t);
  915. if (v_es >= 0 && v_es > G->v_size - (int)sizeof(double))
  916. xerror("glp_cpp: v_es = %d; invalid offset\n", v_es);
  917. if (v_ls >= 0 && v_ls > G->v_size - (int)sizeof(double))
  918. xerror("glp_cpp: v_ls = %d; invalid offset\n", v_ls);
  919. nv = G->nv;
  920. if (nv == 0)
  921. { total = 0.0;
  922. goto done;
  923. }
  924. /* allocate working arrays */
  925. t = xcalloc(1+nv, sizeof(double));
  926. es = xcalloc(1+nv, sizeof(double));
  927. ls = xcalloc(1+nv, sizeof(double));
  928. list = xcalloc(1+nv, sizeof(int));
  929. /* retrieve job times */
  930. for (i = 1; i <= nv; i++)
  931. { v = G->v[i];
  932. if (v_t >= 0)
  933. { memcpy(&t[i], (char *)v->data + v_t, sizeof(double));
  934. if (t[i] < 0.0)
  935. xerror("glp_cpp: t[%d] = %g; invalid time\n", i, t[i]);
  936. }
  937. else
  938. t[i] = 1.0;
  939. }
  940. /* perform topological sorting to determine the list of nodes
  941. (jobs) such that if list[k] = i and list[kk] = j and there
  942. exists arc (i->j), then k < kk */
  943. sorting(G, list);
  944. /* FORWARD PASS */
  945. /* determine earliest start times */
  946. for (k = 1; k <= nv; k++)
  947. { j = list[k];
  948. es[j] = 0.0;
  949. for (a = G->v[j]->in; a != NULL; a = a->h_next)
  950. { i = a->tail->i;
  951. /* there exists arc (i->j) in the project network */
  952. temp = es[i] + t[i];
  953. if (es[j] < temp) es[j] = temp;
  954. }
  955. }
  956. /* determine the minimal project duration */
  957. total = 0.0;
  958. for (i = 1; i <= nv; i++)
  959. { temp = es[i] + t[i];
  960. if (total < temp) total = temp;
  961. }
  962. /* BACKWARD PASS */
  963. /* determine latest start times */
  964. for (k = nv; k >= 1; k--)
  965. { i = list[k];
  966. ls[i] = total - t[i];
  967. for (a = G->v[i]->out; a != NULL; a = a->t_next)
  968. { j = a->head->i;
  969. /* there exists arc (i->j) in the project network */
  970. temp = ls[j] - t[i];
  971. if (ls[i] > temp) ls[i] = temp;
  972. }
  973. /* avoid possible round-off errors */
  974. if (ls[i] < es[i]) ls[i] = es[i];
  975. }
  976. /* store results, if necessary */
  977. if (v_es >= 0)
  978. { for (i = 1; i <= nv; i++)
  979. { v = G->v[i];
  980. memcpy((char *)v->data + v_es, &es[i], sizeof(double));
  981. }
  982. }
  983. if (v_ls >= 0)
  984. { for (i = 1; i <= nv; i++)
  985. { v = G->v[i];
  986. memcpy((char *)v->data + v_ls, &ls[i], sizeof(double));
  987. }
  988. }
  989. /* free working arrays */
  990. xfree(t);
  991. xfree(es);
  992. xfree(ls);
  993. xfree(list);
  994. done: return total;
  995. }
  996. static void sorting(glp_graph *G, int list[])
  997. { /* perform topological sorting to determine the list of nodes
  998. (jobs) such that if list[k] = i and list[kk] = j and there
  999. exists arc (i->j), then k < kk */
  1000. int i, k, nv, v_size, *num;
  1001. void **save;
  1002. nv = G->nv;
  1003. v_size = G->v_size;
  1004. save = xcalloc(1+nv, sizeof(void *));
  1005. num = xcalloc(1+nv, sizeof(int));
  1006. G->v_size = sizeof(int);
  1007. for (i = 1; i <= nv; i++)
  1008. { save[i] = G->v[i]->data;
  1009. G->v[i]->data = &num[i];
  1010. list[i] = 0;
  1011. }
  1012. if (glp_top_sort(G, 0) != 0)
  1013. xerror("glp_cpp: project network is not acyclic\n");
  1014. G->v_size = v_size;
  1015. for (i = 1; i <= nv; i++)
  1016. { G->v[i]->data = save[i];
  1017. k = num[i];
  1018. xassert(1 <= k && k <= nv);
  1019. xassert(list[k] == 0);
  1020. list[k] = i;
  1021. }
  1022. xfree(save);
  1023. xfree(num);
  1024. return;
  1025. }
  1026. /* eof */