glpapi01.c 52 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571
  1. /* glpapi01.c (problem creating and modifying 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 "glpios.h"
  24. /* CAUTION: DO NOT CHANGE THE LIMITS BELOW */
  25. #define M_MAX 100000000 /* = 100*10^6 */
  26. /* maximal number of rows in the problem object */
  27. #define N_MAX 100000000 /* = 100*10^6 */
  28. /* maximal number of columns in the problem object */
  29. #define NNZ_MAX 500000000 /* = 500*10^6 */
  30. /* maximal number of constraint coefficients in the problem object */
  31. /***********************************************************************
  32. * NAME
  33. *
  34. * glp_create_prob - create problem object
  35. *
  36. * SYNOPSIS
  37. *
  38. * glp_prob *glp_create_prob(void);
  39. *
  40. * DESCRIPTION
  41. *
  42. * The routine glp_create_prob creates a new problem object, which is
  43. * initially "empty", i.e. has no rows and columns.
  44. *
  45. * RETURNS
  46. *
  47. * The routine returns a pointer to the object created, which should be
  48. * used in any subsequent operations on this object. */
  49. static void create_prob(glp_prob *lp)
  50. { lp->magic = GLP_PROB_MAGIC;
  51. lp->pool = dmp_create_pool();
  52. #if 0 /* 17/XI-2009 */
  53. lp->cps = xmalloc(sizeof(struct LPXCPS));
  54. lpx_reset_parms(lp);
  55. #else
  56. lp->parms = NULL;
  57. #endif
  58. lp->tree = NULL;
  59. #if 0
  60. lp->lwa = 0;
  61. lp->cwa = NULL;
  62. #endif
  63. /* LP/MIP data */
  64. lp->name = NULL;
  65. lp->obj = NULL;
  66. lp->dir = GLP_MIN;
  67. lp->c0 = 0.0;
  68. lp->m_max = 100;
  69. lp->n_max = 200;
  70. lp->m = lp->n = 0;
  71. lp->nnz = 0;
  72. lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *));
  73. lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *));
  74. lp->r_tree = lp->c_tree = NULL;
  75. /* basis factorization */
  76. lp->valid = 0;
  77. lp->head = xcalloc(1+lp->m_max, sizeof(int));
  78. lp->bfcp = NULL;
  79. lp->bfd = NULL;
  80. /* basic solution (LP) */
  81. lp->pbs_stat = lp->dbs_stat = GLP_UNDEF;
  82. lp->obj_val = 0.0;
  83. lp->it_cnt = 0;
  84. lp->some = 0;
  85. /* interior-point solution (LP) */
  86. lp->ipt_stat = GLP_UNDEF;
  87. lp->ipt_obj = 0.0;
  88. /* integer solution (MIP) */
  89. lp->mip_stat = GLP_UNDEF;
  90. lp->mip_obj = 0.0;
  91. return;
  92. }
  93. glp_prob *glp_create_prob(void)
  94. { glp_prob *lp;
  95. lp = xmalloc(sizeof(glp_prob));
  96. create_prob(lp);
  97. return lp;
  98. }
  99. /***********************************************************************
  100. * NAME
  101. *
  102. * glp_set_prob_name - assign (change) problem name
  103. *
  104. * SYNOPSIS
  105. *
  106. * void glp_set_prob_name(glp_prob *lp, const char *name);
  107. *
  108. * DESCRIPTION
  109. *
  110. * The routine glp_set_prob_name assigns a given symbolic name (1 up to
  111. * 255 characters) to the specified problem object.
  112. *
  113. * If the parameter name is NULL or empty string, the routine erases an
  114. * existing symbolic name of the problem object. */
  115. void glp_set_prob_name(glp_prob *lp, const char *name)
  116. { glp_tree *tree = lp->tree;
  117. if (tree != NULL && tree->reason != 0)
  118. xerror("glp_set_prob_name: operation not allowed\n");
  119. if (lp->name != NULL)
  120. { dmp_free_atom(lp->pool, lp->name, strlen(lp->name)+1);
  121. lp->name = NULL;
  122. }
  123. if (!(name == NULL || name[0] == '\0'))
  124. { int k;
  125. for (k = 0; name[k] != '\0'; k++)
  126. { if (k == 256)
  127. xerror("glp_set_prob_name: problem name too long\n");
  128. if (iscntrl((unsigned char)name[k]))
  129. xerror("glp_set_prob_name: problem name contains invalid"
  130. " character(s)\n");
  131. }
  132. lp->name = dmp_get_atom(lp->pool, strlen(name)+1);
  133. strcpy(lp->name, name);
  134. }
  135. return;
  136. }
  137. /***********************************************************************
  138. * NAME
  139. *
  140. * glp_set_obj_name - assign (change) objective function name
  141. *
  142. * SYNOPSIS
  143. *
  144. * void glp_set_obj_name(glp_prob *lp, const char *name);
  145. *
  146. * DESCRIPTION
  147. *
  148. * The routine glp_set_obj_name assigns a given symbolic name (1 up to
  149. * 255 characters) to the objective function of the specified problem
  150. * object.
  151. *
  152. * If the parameter name is NULL or empty string, the routine erases an
  153. * existing name of the objective function. */
  154. void glp_set_obj_name(glp_prob *lp, const char *name)
  155. { glp_tree *tree = lp->tree;
  156. if (tree != NULL && tree->reason != 0)
  157. xerror("glp_set_obj_name: operation not allowed\n");
  158. if (lp->obj != NULL)
  159. { dmp_free_atom(lp->pool, lp->obj, strlen(lp->obj)+1);
  160. lp->obj = NULL;
  161. }
  162. if (!(name == NULL || name[0] == '\0'))
  163. { int k;
  164. for (k = 0; name[k] != '\0'; k++)
  165. { if (k == 256)
  166. xerror("glp_set_obj_name: objective name too long\n");
  167. if (iscntrl((unsigned char)name[k]))
  168. xerror("glp_set_obj_name: objective name contains invali"
  169. "d character(s)\n");
  170. }
  171. lp->obj = dmp_get_atom(lp->pool, strlen(name)+1);
  172. strcpy(lp->obj, name);
  173. }
  174. return;
  175. }
  176. /***********************************************************************
  177. * NAME
  178. *
  179. * glp_set_obj_dir - set (change) optimization direction flag
  180. *
  181. * SYNOPSIS
  182. *
  183. * void glp_set_obj_dir(glp_prob *lp, int dir);
  184. *
  185. * DESCRIPTION
  186. *
  187. * The routine glp_set_obj_dir sets (changes) optimization direction
  188. * flag (i.e. "sense" of the objective function) as specified by the
  189. * parameter dir:
  190. *
  191. * GLP_MIN - minimization;
  192. * GLP_MAX - maximization. */
  193. void glp_set_obj_dir(glp_prob *lp, int dir)
  194. { glp_tree *tree = lp->tree;
  195. if (tree != NULL && tree->reason != 0)
  196. xerror("glp_set_obj_dir: operation not allowed\n");
  197. if (!(dir == GLP_MIN || dir == GLP_MAX))
  198. xerror("glp_set_obj_dir: dir = %d; invalid direction flag\n",
  199. dir);
  200. lp->dir = dir;
  201. return;
  202. }
  203. /***********************************************************************
  204. * NAME
  205. *
  206. * glp_add_rows - add new rows to problem object
  207. *
  208. * SYNOPSIS
  209. *
  210. * int glp_add_rows(glp_prob *lp, int nrs);
  211. *
  212. * DESCRIPTION
  213. *
  214. * The routine glp_add_rows adds nrs rows (constraints) to the specified
  215. * problem object. New rows are always added to the end of the row list,
  216. * so the ordinal numbers of existing rows remain unchanged.
  217. *
  218. * Being added each new row is initially free (unbounded) and has empty
  219. * list of the constraint coefficients.
  220. *
  221. * RETURNS
  222. *
  223. * The routine glp_add_rows returns the ordinal number of the first new
  224. * row added to the problem object. */
  225. int glp_add_rows(glp_prob *lp, int nrs)
  226. { glp_tree *tree = lp->tree;
  227. GLPROW *row;
  228. int m_new, i;
  229. /* determine new number of rows */
  230. if (nrs < 1)
  231. xerror("glp_add_rows: nrs = %d; invalid number of rows\n",
  232. nrs);
  233. if (nrs > M_MAX - lp->m)
  234. xerror("glp_add_rows: nrs = %d; too many rows\n", nrs);
  235. m_new = lp->m + nrs;
  236. /* increase the room, if necessary */
  237. if (lp->m_max < m_new)
  238. { GLPROW **save = lp->row;
  239. while (lp->m_max < m_new)
  240. { lp->m_max += lp->m_max;
  241. xassert(lp->m_max > 0);
  242. }
  243. lp->row = xcalloc(1+lp->m_max, sizeof(GLPROW *));
  244. memcpy(&lp->row[1], &save[1], lp->m * sizeof(GLPROW *));
  245. xfree(save);
  246. /* do not forget about the basis header */
  247. xfree(lp->head);
  248. lp->head = xcalloc(1+lp->m_max, sizeof(int));
  249. }
  250. /* add new rows to the end of the row list */
  251. for (i = lp->m+1; i <= m_new; i++)
  252. { /* create row descriptor */
  253. lp->row[i] = row = dmp_get_atom(lp->pool, sizeof(GLPROW));
  254. row->i = i;
  255. row->name = NULL;
  256. row->node = NULL;
  257. #if 1 /* 20/IX-2008 */
  258. row->level = 0;
  259. row->origin = 0;
  260. row->klass = 0;
  261. if (tree != NULL)
  262. { switch (tree->reason)
  263. { case 0:
  264. break;
  265. case GLP_IROWGEN:
  266. xassert(tree->curr != NULL);
  267. row->level = tree->curr->level;
  268. row->origin = GLP_RF_LAZY;
  269. break;
  270. case GLP_ICUTGEN:
  271. xassert(tree->curr != NULL);
  272. row->level = tree->curr->level;
  273. row->origin = GLP_RF_CUT;
  274. break;
  275. default:
  276. xassert(tree != tree);
  277. }
  278. }
  279. #endif
  280. row->type = GLP_FR;
  281. row->lb = row->ub = 0.0;
  282. row->ptr = NULL;
  283. row->rii = 1.0;
  284. row->stat = GLP_BS;
  285. #if 0
  286. row->bind = -1;
  287. #else
  288. row->bind = 0;
  289. #endif
  290. row->prim = row->dual = 0.0;
  291. row->pval = row->dval = 0.0;
  292. row->mipx = 0.0;
  293. }
  294. /* set new number of rows */
  295. lp->m = m_new;
  296. /* invalidate the basis factorization */
  297. lp->valid = 0;
  298. #if 1
  299. if (tree != NULL && tree->reason != 0) tree->reopt = 1;
  300. #endif
  301. /* return the ordinal number of the first row added */
  302. return m_new - nrs + 1;
  303. }
  304. /***********************************************************************
  305. * NAME
  306. *
  307. * glp_add_cols - add new columns to problem object
  308. *
  309. * SYNOPSIS
  310. *
  311. * int glp_add_cols(glp_prob *lp, int ncs);
  312. *
  313. * DESCRIPTION
  314. *
  315. * The routine glp_add_cols adds ncs columns (structural variables) to
  316. * the specified problem object. New columns are always added to the end
  317. * of the column list, so the ordinal numbers of existing columns remain
  318. * unchanged.
  319. *
  320. * Being added each new column is initially fixed at zero and has empty
  321. * list of the constraint coefficients.
  322. *
  323. * RETURNS
  324. *
  325. * The routine glp_add_cols returns the ordinal number of the first new
  326. * column added to the problem object. */
  327. int glp_add_cols(glp_prob *lp, int ncs)
  328. { glp_tree *tree = lp->tree;
  329. GLPCOL *col;
  330. int n_new, j;
  331. if (tree != NULL && tree->reason != 0)
  332. xerror("glp_add_cols: operation not allowed\n");
  333. /* determine new number of columns */
  334. if (ncs < 1)
  335. xerror("glp_add_cols: ncs = %d; invalid number of columns\n",
  336. ncs);
  337. if (ncs > N_MAX - lp->n)
  338. xerror("glp_add_cols: ncs = %d; too many columns\n", ncs);
  339. n_new = lp->n + ncs;
  340. /* increase the room, if necessary */
  341. if (lp->n_max < n_new)
  342. { GLPCOL **save = lp->col;
  343. while (lp->n_max < n_new)
  344. { lp->n_max += lp->n_max;
  345. xassert(lp->n_max > 0);
  346. }
  347. lp->col = xcalloc(1+lp->n_max, sizeof(GLPCOL *));
  348. memcpy(&lp->col[1], &save[1], lp->n * sizeof(GLPCOL *));
  349. xfree(save);
  350. }
  351. /* add new columns to the end of the column list */
  352. for (j = lp->n+1; j <= n_new; j++)
  353. { /* create column descriptor */
  354. lp->col[j] = col = dmp_get_atom(lp->pool, sizeof(GLPCOL));
  355. col->j = j;
  356. col->name = NULL;
  357. col->node = NULL;
  358. col->kind = GLP_CV;
  359. col->type = GLP_FX;
  360. col->lb = col->ub = 0.0;
  361. col->coef = 0.0;
  362. col->ptr = NULL;
  363. col->sjj = 1.0;
  364. col->stat = GLP_NS;
  365. #if 0
  366. col->bind = -1;
  367. #else
  368. col->bind = 0; /* the basis may remain valid */
  369. #endif
  370. col->prim = col->dual = 0.0;
  371. col->pval = col->dval = 0.0;
  372. col->mipx = 0.0;
  373. }
  374. /* set new number of columns */
  375. lp->n = n_new;
  376. /* return the ordinal number of the first column added */
  377. return n_new - ncs + 1;
  378. }
  379. /***********************************************************************
  380. * NAME
  381. *
  382. * glp_set_row_name - assign (change) row name
  383. *
  384. * SYNOPSIS
  385. *
  386. * void glp_set_row_name(glp_prob *lp, int i, const char *name);
  387. *
  388. * DESCRIPTION
  389. *
  390. * The routine glp_set_row_name assigns a given symbolic name (1 up to
  391. * 255 characters) to i-th row (auxiliary variable) of the specified
  392. * problem object.
  393. *
  394. * If the parameter name is NULL or empty string, the routine erases an
  395. * existing name of i-th row. */
  396. void glp_set_row_name(glp_prob *lp, int i, const char *name)
  397. { glp_tree *tree = lp->tree;
  398. GLPROW *row;
  399. if (!(1 <= i && i <= lp->m))
  400. xerror("glp_set_row_name: i = %d; row number out of range\n",
  401. i);
  402. row = lp->row[i];
  403. if (tree != NULL && tree->reason != 0)
  404. { xassert(tree->curr != NULL);
  405. xassert(row->level == tree->curr->level);
  406. }
  407. if (row->name != NULL)
  408. { if (row->node != NULL)
  409. { xassert(lp->r_tree != NULL);
  410. avl_delete_node(lp->r_tree, row->node);
  411. row->node = NULL;
  412. }
  413. dmp_free_atom(lp->pool, row->name, strlen(row->name)+1);
  414. row->name = NULL;
  415. }
  416. if (!(name == NULL || name[0] == '\0'))
  417. { int k;
  418. for (k = 0; name[k] != '\0'; k++)
  419. { if (k == 256)
  420. xerror("glp_set_row_name: i = %d; row name too long\n",
  421. i);
  422. if (iscntrl((unsigned char)name[k]))
  423. xerror("glp_set_row_name: i = %d: row name contains inva"
  424. "lid character(s)\n", i);
  425. }
  426. row->name = dmp_get_atom(lp->pool, strlen(name)+1);
  427. strcpy(row->name, name);
  428. if (lp->r_tree != NULL)
  429. { xassert(row->node == NULL);
  430. row->node = avl_insert_node(lp->r_tree, row->name);
  431. avl_set_node_link(row->node, row);
  432. }
  433. }
  434. return;
  435. }
  436. /***********************************************************************
  437. * NAME
  438. *
  439. * glp_set_col_name - assign (change) column name
  440. *
  441. * SYNOPSIS
  442. *
  443. * void glp_set_col_name(glp_prob *lp, int j, const char *name);
  444. *
  445. * DESCRIPTION
  446. *
  447. * The routine glp_set_col_name assigns a given symbolic name (1 up to
  448. * 255 characters) to j-th column (structural variable) of the specified
  449. * problem object.
  450. *
  451. * If the parameter name is NULL or empty string, the routine erases an
  452. * existing name of j-th column. */
  453. void glp_set_col_name(glp_prob *lp, int j, const char *name)
  454. { glp_tree *tree = lp->tree;
  455. GLPCOL *col;
  456. if (tree != NULL && tree->reason != 0)
  457. xerror("glp_set_col_name: operation not allowed\n");
  458. if (!(1 <= j && j <= lp->n))
  459. xerror("glp_set_col_name: j = %d; column number out of range\n"
  460. , j);
  461. col = lp->col[j];
  462. if (col->name != NULL)
  463. { if (col->node != NULL)
  464. { xassert(lp->c_tree != NULL);
  465. avl_delete_node(lp->c_tree, col->node);
  466. col->node = NULL;
  467. }
  468. dmp_free_atom(lp->pool, col->name, strlen(col->name)+1);
  469. col->name = NULL;
  470. }
  471. if (!(name == NULL || name[0] == '\0'))
  472. { int k;
  473. for (k = 0; name[k] != '\0'; k++)
  474. { if (k == 256)
  475. xerror("glp_set_col_name: j = %d; column name too long\n"
  476. , j);
  477. if (iscntrl((unsigned char)name[k]))
  478. xerror("glp_set_col_name: j = %d: column name contains i"
  479. "nvalid character(s)\n", j);
  480. }
  481. col->name = dmp_get_atom(lp->pool, strlen(name)+1);
  482. strcpy(col->name, name);
  483. if (lp->c_tree != NULL && col->name != NULL)
  484. { xassert(col->node == NULL);
  485. col->node = avl_insert_node(lp->c_tree, col->name);
  486. avl_set_node_link(col->node, col);
  487. }
  488. }
  489. return;
  490. }
  491. /***********************************************************************
  492. * NAME
  493. *
  494. * glp_set_row_bnds - set (change) row bounds
  495. *
  496. * SYNOPSIS
  497. *
  498. * void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb,
  499. * double ub);
  500. *
  501. * DESCRIPTION
  502. *
  503. * The routine glp_set_row_bnds sets (changes) the type and bounds of
  504. * i-th row (auxiliary variable) of the specified problem object.
  505. *
  506. * Parameters type, lb, and ub specify the type, lower bound, and upper
  507. * bound, respectively, as follows:
  508. *
  509. * Type Bounds Comments
  510. * ------------------------------------------------------
  511. * GLP_FR -inf < x < +inf Free variable
  512. * GLP_LO lb <= x < +inf Variable with lower bound
  513. * GLP_UP -inf < x <= ub Variable with upper bound
  514. * GLP_DB lb <= x <= ub Double-bounded variable
  515. * GLP_FX x = lb Fixed variable
  516. *
  517. * where x is the auxiliary variable associated with i-th row.
  518. *
  519. * If the row has no lower bound, the parameter lb is ignored. If the
  520. * row has no upper bound, the parameter ub is ignored. If the row is
  521. * an equality constraint (i.e. the corresponding auxiliary variable is
  522. * of fixed type), only the parameter lb is used while the parameter ub
  523. * is ignored. */
  524. void glp_set_row_bnds(glp_prob *lp, int i, int type, double lb,
  525. double ub)
  526. { GLPROW *row;
  527. if (!(1 <= i && i <= lp->m))
  528. xerror("glp_set_row_bnds: i = %d; row number out of range\n",
  529. i);
  530. row = lp->row[i];
  531. row->type = type;
  532. switch (type)
  533. { case GLP_FR:
  534. row->lb = row->ub = 0.0;
  535. if (row->stat != GLP_BS) row->stat = GLP_NF;
  536. break;
  537. case GLP_LO:
  538. row->lb = lb, row->ub = 0.0;
  539. if (row->stat != GLP_BS) row->stat = GLP_NL;
  540. break;
  541. case GLP_UP:
  542. row->lb = 0.0, row->ub = ub;
  543. if (row->stat != GLP_BS) row->stat = GLP_NU;
  544. break;
  545. case GLP_DB:
  546. row->lb = lb, row->ub = ub;
  547. if (!(row->stat == GLP_BS ||
  548. row->stat == GLP_NL || row->stat == GLP_NU))
  549. row->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU);
  550. break;
  551. case GLP_FX:
  552. row->lb = row->ub = lb;
  553. if (row->stat != GLP_BS) row->stat = GLP_NS;
  554. break;
  555. default:
  556. xerror("glp_set_row_bnds: i = %d; type = %d; invalid row ty"
  557. "pe\n", i, type);
  558. }
  559. return;
  560. }
  561. /***********************************************************************
  562. * NAME
  563. *
  564. * glp_set_col_bnds - set (change) column bounds
  565. *
  566. * SYNOPSIS
  567. *
  568. * void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb,
  569. * double ub);
  570. *
  571. * DESCRIPTION
  572. *
  573. * The routine glp_set_col_bnds sets (changes) the type and bounds of
  574. * j-th column (structural variable) of the specified problem object.
  575. *
  576. * Parameters type, lb, and ub specify the type, lower bound, and upper
  577. * bound, respectively, as follows:
  578. *
  579. * Type Bounds Comments
  580. * ------------------------------------------------------
  581. * GLP_FR -inf < x < +inf Free variable
  582. * GLP_LO lb <= x < +inf Variable with lower bound
  583. * GLP_UP -inf < x <= ub Variable with upper bound
  584. * GLP_DB lb <= x <= ub Double-bounded variable
  585. * GLP_FX x = lb Fixed variable
  586. *
  587. * where x is the structural variable associated with j-th column.
  588. *
  589. * If the column has no lower bound, the parameter lb is ignored. If the
  590. * column has no upper bound, the parameter ub is ignored. If the column
  591. * is of fixed type, only the parameter lb is used while the parameter
  592. * ub is ignored. */
  593. void glp_set_col_bnds(glp_prob *lp, int j, int type, double lb,
  594. double ub)
  595. { GLPCOL *col;
  596. if (!(1 <= j && j <= lp->n))
  597. xerror("glp_set_col_bnds: j = %d; column number out of range\n"
  598. , j);
  599. col = lp->col[j];
  600. col->type = type;
  601. switch (type)
  602. { case GLP_FR:
  603. col->lb = col->ub = 0.0;
  604. if (col->stat != GLP_BS) col->stat = GLP_NF;
  605. break;
  606. case GLP_LO:
  607. col->lb = lb, col->ub = 0.0;
  608. if (col->stat != GLP_BS) col->stat = GLP_NL;
  609. break;
  610. case GLP_UP:
  611. col->lb = 0.0, col->ub = ub;
  612. if (col->stat != GLP_BS) col->stat = GLP_NU;
  613. break;
  614. case GLP_DB:
  615. col->lb = lb, col->ub = ub;
  616. if (!(col->stat == GLP_BS ||
  617. col->stat == GLP_NL || col->stat == GLP_NU))
  618. col->stat = (fabs(lb) <= fabs(ub) ? GLP_NL : GLP_NU);
  619. break;
  620. case GLP_FX:
  621. col->lb = col->ub = lb;
  622. if (col->stat != GLP_BS) col->stat = GLP_NS;
  623. break;
  624. default:
  625. xerror("glp_set_col_bnds: j = %d; type = %d; invalid column"
  626. " type\n", j, type);
  627. }
  628. return;
  629. }
  630. /***********************************************************************
  631. * NAME
  632. *
  633. * glp_set_obj_coef - set (change) obj. coefficient or constant term
  634. *
  635. * SYNOPSIS
  636. *
  637. * void glp_set_obj_coef(glp_prob *lp, int j, double coef);
  638. *
  639. * DESCRIPTION
  640. *
  641. * The routine glp_set_obj_coef sets (changes) objective coefficient at
  642. * j-th column (structural variable) of the specified problem object.
  643. *
  644. * If the parameter j is 0, the routine sets (changes) the constant term
  645. * ("shift") of the objective function. */
  646. void glp_set_obj_coef(glp_prob *lp, int j, double coef)
  647. { glp_tree *tree = lp->tree;
  648. if (tree != NULL && tree->reason != 0)
  649. xerror("glp_set_obj_coef: operation not allowed\n");
  650. if (!(0 <= j && j <= lp->n))
  651. xerror("glp_set_obj_coef: j = %d; column number out of range\n"
  652. , j);
  653. if (j == 0)
  654. lp->c0 = coef;
  655. else
  656. lp->col[j]->coef = coef;
  657. return;
  658. }
  659. /***********************************************************************
  660. * NAME
  661. *
  662. * glp_set_mat_row - set (replace) row of the constraint matrix
  663. *
  664. * SYNOPSIS
  665. *
  666. * void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[],
  667. * const double val[]);
  668. *
  669. * DESCRIPTION
  670. *
  671. * The routine glp_set_mat_row stores (replaces) the contents of i-th
  672. * row of the constraint matrix of the specified problem object.
  673. *
  674. * Column indices and numeric values of new row elements must be placed
  675. * in locations ind[1], ..., ind[len] and val[1], ..., val[len], where
  676. * 0 <= len <= n is the new length of i-th row, n is the current number
  677. * of columns in the problem object. Elements with identical column
  678. * indices are not allowed. Zero elements are allowed, but they are not
  679. * stored in the constraint matrix.
  680. *
  681. * If the parameter len is zero, the parameters ind and/or val can be
  682. * specified as NULL. */
  683. void glp_set_mat_row(glp_prob *lp, int i, int len, const int ind[],
  684. const double val[])
  685. { glp_tree *tree = lp->tree;
  686. GLPROW *row;
  687. GLPCOL *col;
  688. GLPAIJ *aij, *next;
  689. int j, k;
  690. /* obtain pointer to i-th row */
  691. if (!(1 <= i && i <= lp->m))
  692. xerror("glp_set_mat_row: i = %d; row number out of range\n",
  693. i);
  694. row = lp->row[i];
  695. if (tree != NULL && tree->reason != 0)
  696. { xassert(tree->curr != NULL);
  697. xassert(row->level == tree->curr->level);
  698. }
  699. /* remove all existing elements from i-th row */
  700. while (row->ptr != NULL)
  701. { /* take next element in the row */
  702. aij = row->ptr;
  703. /* remove the element from the row list */
  704. row->ptr = aij->r_next;
  705. /* obtain pointer to corresponding column */
  706. col = aij->col;
  707. /* remove the element from the column list */
  708. if (aij->c_prev == NULL)
  709. col->ptr = aij->c_next;
  710. else
  711. aij->c_prev->c_next = aij->c_next;
  712. if (aij->c_next == NULL)
  713. ;
  714. else
  715. aij->c_next->c_prev = aij->c_prev;
  716. /* return the element to the memory pool */
  717. dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
  718. /* if the corresponding column is basic, invalidate the basis
  719. factorization */
  720. if (col->stat == GLP_BS) lp->valid = 0;
  721. }
  722. /* store new contents of i-th row */
  723. if (!(0 <= len && len <= lp->n))
  724. xerror("glp_set_mat_row: i = %d; len = %d; invalid row length "
  725. "\n", i, len);
  726. if (len > NNZ_MAX - lp->nnz)
  727. xerror("glp_set_mat_row: i = %d; len = %d; too many constraint"
  728. " coefficients\n", i, len);
  729. for (k = 1; k <= len; k++)
  730. { /* take number j of corresponding column */
  731. j = ind[k];
  732. /* obtain pointer to j-th column */
  733. if (!(1 <= j && j <= lp->n))
  734. xerror("glp_set_mat_row: i = %d; ind[%d] = %d; column index"
  735. " out of range\n", i, k, j);
  736. col = lp->col[j];
  737. /* if there is element with the same column index, it can only
  738. be found in the beginning of j-th column list */
  739. if (col->ptr != NULL && col->ptr->row->i == i)
  740. xerror("glp_set_mat_row: i = %d; ind[%d] = %d; duplicate co"
  741. "lumn indices not allowed\n", i, k, j);
  742. /* create new element */
  743. aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
  744. aij->row = row;
  745. aij->col = col;
  746. aij->val = val[k];
  747. /* add the new element to the beginning of i-th row and j-th
  748. column lists */
  749. aij->r_prev = NULL;
  750. aij->r_next = row->ptr;
  751. aij->c_prev = NULL;
  752. aij->c_next = col->ptr;
  753. if (aij->r_next != NULL) aij->r_next->r_prev = aij;
  754. if (aij->c_next != NULL) aij->c_next->c_prev = aij;
  755. row->ptr = col->ptr = aij;
  756. /* if the corresponding column is basic, invalidate the basis
  757. factorization */
  758. if (col->stat == GLP_BS && aij->val != 0.0) lp->valid = 0;
  759. }
  760. /* remove zero elements from i-th row */
  761. for (aij = row->ptr; aij != NULL; aij = next)
  762. { next = aij->r_next;
  763. if (aij->val == 0.0)
  764. { /* remove the element from the row list */
  765. if (aij->r_prev == NULL)
  766. row->ptr = next;
  767. else
  768. aij->r_prev->r_next = next;
  769. if (next == NULL)
  770. ;
  771. else
  772. next->r_prev = aij->r_prev;
  773. /* remove the element from the column list */
  774. xassert(aij->c_prev == NULL);
  775. aij->col->ptr = aij->c_next;
  776. if (aij->c_next != NULL) aij->c_next->c_prev = NULL;
  777. /* return the element to the memory pool */
  778. dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
  779. }
  780. }
  781. return;
  782. }
  783. /***********************************************************************
  784. * NAME
  785. *
  786. * glp_set_mat_col - set (replace) column of the constraint matrix
  787. *
  788. * SYNOPSIS
  789. *
  790. * void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[],
  791. * const double val[]);
  792. *
  793. * DESCRIPTION
  794. *
  795. * The routine glp_set_mat_col stores (replaces) the contents of j-th
  796. * column of the constraint matrix of the specified problem object.
  797. *
  798. * Row indices and numeric values of new column elements must be placed
  799. * in locations ind[1], ..., ind[len] and val[1], ..., val[len], where
  800. * 0 <= len <= m is the new length of j-th column, m is the current
  801. * number of rows in the problem object. Elements with identical column
  802. * indices are not allowed. Zero elements are allowed, but they are not
  803. * stored in the constraint matrix.
  804. *
  805. * If the parameter len is zero, the parameters ind and/or val can be
  806. * specified as NULL. */
  807. void glp_set_mat_col(glp_prob *lp, int j, int len, const int ind[],
  808. const double val[])
  809. { glp_tree *tree = lp->tree;
  810. GLPROW *row;
  811. GLPCOL *col;
  812. GLPAIJ *aij, *next;
  813. int i, k;
  814. if (tree != NULL && tree->reason != 0)
  815. xerror("glp_set_mat_col: operation not allowed\n");
  816. /* obtain pointer to j-th column */
  817. if (!(1 <= j && j <= lp->n))
  818. xerror("glp_set_mat_col: j = %d; column number out of range\n",
  819. j);
  820. col = lp->col[j];
  821. /* remove all existing elements from j-th column */
  822. while (col->ptr != NULL)
  823. { /* take next element in the column */
  824. aij = col->ptr;
  825. /* remove the element from the column list */
  826. col->ptr = aij->c_next;
  827. /* obtain pointer to corresponding row */
  828. row = aij->row;
  829. /* remove the element from the row list */
  830. if (aij->r_prev == NULL)
  831. row->ptr = aij->r_next;
  832. else
  833. aij->r_prev->r_next = aij->r_next;
  834. if (aij->r_next == NULL)
  835. ;
  836. else
  837. aij->r_next->r_prev = aij->r_prev;
  838. /* return the element to the memory pool */
  839. dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
  840. }
  841. /* store new contents of j-th column */
  842. if (!(0 <= len && len <= lp->m))
  843. xerror("glp_set_mat_col: j = %d; len = %d; invalid column leng"
  844. "th\n", j, len);
  845. if (len > NNZ_MAX - lp->nnz)
  846. xerror("glp_set_mat_col: j = %d; len = %d; too many constraint"
  847. " coefficients\n", j, len);
  848. for (k = 1; k <= len; k++)
  849. { /* take number i of corresponding row */
  850. i = ind[k];
  851. /* obtain pointer to i-th row */
  852. if (!(1 <= i && i <= lp->m))
  853. xerror("glp_set_mat_col: j = %d; ind[%d] = %d; row index ou"
  854. "t of range\n", j, k, i);
  855. row = lp->row[i];
  856. /* if there is element with the same row index, it can only be
  857. found in the beginning of i-th row list */
  858. if (row->ptr != NULL && row->ptr->col->j == j)
  859. xerror("glp_set_mat_col: j = %d; ind[%d] = %d; duplicate ro"
  860. "w indices not allowed\n", j, k, i);
  861. /* create new element */
  862. aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
  863. aij->row = row;
  864. aij->col = col;
  865. aij->val = val[k];
  866. /* add the new element to the beginning of i-th row and j-th
  867. column lists */
  868. aij->r_prev = NULL;
  869. aij->r_next = row->ptr;
  870. aij->c_prev = NULL;
  871. aij->c_next = col->ptr;
  872. if (aij->r_next != NULL) aij->r_next->r_prev = aij;
  873. if (aij->c_next != NULL) aij->c_next->c_prev = aij;
  874. row->ptr = col->ptr = aij;
  875. }
  876. /* remove zero elements from j-th column */
  877. for (aij = col->ptr; aij != NULL; aij = next)
  878. { next = aij->c_next;
  879. if (aij->val == 0.0)
  880. { /* remove the element from the row list */
  881. xassert(aij->r_prev == NULL);
  882. aij->row->ptr = aij->r_next;
  883. if (aij->r_next != NULL) aij->r_next->r_prev = NULL;
  884. /* remove the element from the column list */
  885. if (aij->c_prev == NULL)
  886. col->ptr = next;
  887. else
  888. aij->c_prev->c_next = next;
  889. if (next == NULL)
  890. ;
  891. else
  892. next->c_prev = aij->c_prev;
  893. /* return the element to the memory pool */
  894. dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
  895. }
  896. }
  897. /* if j-th column is basic, invalidate the basis factorization */
  898. if (col->stat == GLP_BS) lp->valid = 0;
  899. return;
  900. }
  901. /***********************************************************************
  902. * NAME
  903. *
  904. * glp_load_matrix - load (replace) the whole constraint matrix
  905. *
  906. * SYNOPSIS
  907. *
  908. * void glp_load_matrix(glp_prob *lp, int ne, const int ia[],
  909. * const int ja[], const double ar[]);
  910. *
  911. * DESCRIPTION
  912. *
  913. * The routine glp_load_matrix loads the constraint matrix passed in
  914. * the arrays ia, ja, and ar into the specified problem object. Before
  915. * loading the current contents of the constraint matrix is destroyed.
  916. *
  917. * Constraint coefficients (elements of the constraint matrix) must be
  918. * specified as triplets (ia[k], ja[k], ar[k]) for k = 1, ..., ne,
  919. * where ia[k] is the row index, ja[k] is the column index, ar[k] is a
  920. * numeric value of corresponding constraint coefficient. The parameter
  921. * ne specifies the total number of (non-zero) elements in the matrix
  922. * to be loaded. Coefficients with identical indices are not allowed.
  923. * Zero coefficients are allowed, however, they are not stored in the
  924. * constraint matrix.
  925. *
  926. * If the parameter ne is zero, the parameters ia, ja, and ar can be
  927. * specified as NULL. */
  928. void glp_load_matrix(glp_prob *lp, int ne, const int ia[],
  929. const int ja[], const double ar[])
  930. { glp_tree *tree = lp->tree;
  931. GLPROW *row;
  932. GLPCOL *col;
  933. GLPAIJ *aij, *next;
  934. int i, j, k;
  935. if (tree != NULL && tree->reason != 0)
  936. xerror("glp_load_matrix: operation not allowed\n");
  937. /* clear the constraint matrix */
  938. for (i = 1; i <= lp->m; i++)
  939. { row = lp->row[i];
  940. while (row->ptr != NULL)
  941. { aij = row->ptr;
  942. row->ptr = aij->r_next;
  943. dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
  944. }
  945. }
  946. xassert(lp->nnz == 0);
  947. for (j = 1; j <= lp->n; j++) lp->col[j]->ptr = NULL;
  948. /* load the new contents of the constraint matrix and build its
  949. row lists */
  950. if (ne < 0)
  951. xerror("glp_load_matrix: ne = %d; invalid number of constraint"
  952. " coefficients\n", ne);
  953. if (ne > NNZ_MAX)
  954. xerror("glp_load_matrix: ne = %d; too many constraint coeffici"
  955. "ents\n", ne);
  956. for (k = 1; k <= ne; k++)
  957. { /* take indices of new element */
  958. i = ia[k], j = ja[k];
  959. /* obtain pointer to i-th row */
  960. if (!(1 <= i && i <= lp->m))
  961. xerror("glp_load_matrix: ia[%d] = %d; row index out of rang"
  962. "e\n", k, i);
  963. row = lp->row[i];
  964. /* obtain pointer to j-th column */
  965. if (!(1 <= j && j <= lp->n))
  966. xerror("glp_load_matrix: ja[%d] = %d; column index out of r"
  967. "ange\n", k, j);
  968. col = lp->col[j];
  969. /* create new element */
  970. aij = dmp_get_atom(lp->pool, sizeof(GLPAIJ)), lp->nnz++;
  971. aij->row = row;
  972. aij->col = col;
  973. aij->val = ar[k];
  974. /* add the new element to the beginning of i-th row list */
  975. aij->r_prev = NULL;
  976. aij->r_next = row->ptr;
  977. if (aij->r_next != NULL) aij->r_next->r_prev = aij;
  978. row->ptr = aij;
  979. }
  980. xassert(lp->nnz == ne);
  981. /* build column lists of the constraint matrix and check elements
  982. with identical indices */
  983. for (i = 1; i <= lp->m; i++)
  984. { for (aij = lp->row[i]->ptr; aij != NULL; aij = aij->r_next)
  985. { /* obtain pointer to corresponding column */
  986. col = aij->col;
  987. /* if there is element with identical indices, it can only
  988. be found in the beginning of j-th column list */
  989. if (col->ptr != NULL && col->ptr->row->i == i)
  990. { for (k = 1; k <= ne; k++)
  991. if (ia[k] == i && ja[k] == col->j) break;
  992. xerror("glp_load_mat: ia[%d] = %d; ja[%d] = %d; duplicat"
  993. "e indices not allowed\n", k, i, k, col->j);
  994. }
  995. /* add the element to the beginning of j-th column list */
  996. aij->c_prev = NULL;
  997. aij->c_next = col->ptr;
  998. if (aij->c_next != NULL) aij->c_next->c_prev = aij;
  999. col->ptr = aij;
  1000. }
  1001. }
  1002. /* remove zero elements from the constraint matrix */
  1003. for (i = 1; i <= lp->m; i++)
  1004. { row = lp->row[i];
  1005. for (aij = row->ptr; aij != NULL; aij = next)
  1006. { next = aij->r_next;
  1007. if (aij->val == 0.0)
  1008. { /* remove the element from the row list */
  1009. if (aij->r_prev == NULL)
  1010. row->ptr = next;
  1011. else
  1012. aij->r_prev->r_next = next;
  1013. if (next == NULL)
  1014. ;
  1015. else
  1016. next->r_prev = aij->r_prev;
  1017. /* remove the element from the column list */
  1018. if (aij->c_prev == NULL)
  1019. aij->col->ptr = aij->c_next;
  1020. else
  1021. aij->c_prev->c_next = aij->c_next;
  1022. if (aij->c_next == NULL)
  1023. ;
  1024. else
  1025. aij->c_next->c_prev = aij->c_prev;
  1026. /* return the element to the memory pool */
  1027. dmp_free_atom(lp->pool, aij, sizeof(GLPAIJ)), lp->nnz--;
  1028. }
  1029. }
  1030. }
  1031. /* invalidate the basis factorization */
  1032. lp->valid = 0;
  1033. return;
  1034. }
  1035. /***********************************************************************
  1036. * NAME
  1037. *
  1038. * glp_check_dup - check for duplicate elements in sparse matrix
  1039. *
  1040. * SYNOPSIS
  1041. *
  1042. * int glp_check_dup(int m, int n, int ne, const int ia[],
  1043. * const int ja[]);
  1044. *
  1045. * DESCRIPTION
  1046. *
  1047. * The routine glp_check_dup checks for duplicate elements (that is,
  1048. * elements with identical indices) in a sparse matrix specified in the
  1049. * coordinate format.
  1050. *
  1051. * The parameters m and n specifies, respectively, the number of rows
  1052. * and columns in the matrix, m >= 0, n >= 0.
  1053. *
  1054. * The parameter ne specifies the number of (structurally) non-zero
  1055. * elements in the matrix, ne >= 0.
  1056. *
  1057. * Elements of the matrix are specified as doublets (ia[k],ja[k]) for
  1058. * k = 1,...,ne, where ia[k] is a row index, ja[k] is a column index.
  1059. *
  1060. * The routine glp_check_dup can be used prior to a call to the routine
  1061. * glp_load_matrix to check that the constraint matrix to be loaded has
  1062. * no duplicate elements.
  1063. *
  1064. * RETURNS
  1065. *
  1066. * The routine glp_check_dup returns one of the following values:
  1067. *
  1068. * 0 - the matrix has no duplicate elements;
  1069. *
  1070. * -k - indices ia[k] or/and ja[k] are out of range;
  1071. *
  1072. * +k - element (ia[k],ja[k]) is duplicate. */
  1073. int glp_check_dup(int m, int n, int ne, const int ia[], const int ja[])
  1074. { int i, j, k, *ptr, *next, ret;
  1075. char *flag;
  1076. if (m < 0)
  1077. xerror("glp_check_dup: m = %d; invalid parameter\n");
  1078. if (n < 0)
  1079. xerror("glp_check_dup: n = %d; invalid parameter\n");
  1080. if (ne < 0)
  1081. xerror("glp_check_dup: ne = %d; invalid parameter\n");
  1082. if (ne > 0 && ia == NULL)
  1083. xerror("glp_check_dup: ia = %p; invalid parameter\n", ia);
  1084. if (ne > 0 && ja == NULL)
  1085. xerror("glp_check_dup: ja = %p; invalid parameter\n", ja);
  1086. for (k = 1; k <= ne; k++)
  1087. { i = ia[k], j = ja[k];
  1088. if (!(1 <= i && i <= m && 1 <= j && j <= n))
  1089. { ret = -k;
  1090. goto done;
  1091. }
  1092. }
  1093. if (m == 0 || n == 0)
  1094. { ret = 0;
  1095. goto done;
  1096. }
  1097. /* allocate working arrays */
  1098. ptr = xcalloc(1+m, sizeof(int));
  1099. next = xcalloc(1+ne, sizeof(int));
  1100. flag = xcalloc(1+n, sizeof(char));
  1101. /* build row lists */
  1102. for (i = 1; i <= m; i++)
  1103. ptr[i] = 0;
  1104. for (k = 1; k <= ne; k++)
  1105. { i = ia[k];
  1106. next[k] = ptr[i];
  1107. ptr[i] = k;
  1108. }
  1109. /* clear column flags */
  1110. for (j = 1; j <= n; j++)
  1111. flag[j] = 0;
  1112. /* check for duplicate elements */
  1113. for (i = 1; i <= m; i++)
  1114. { for (k = ptr[i]; k != 0; k = next[k])
  1115. { j = ja[k];
  1116. if (flag[j])
  1117. { /* find first element (i,j) */
  1118. for (k = 1; k <= ne; k++)
  1119. if (ia[k] == i && ja[k] == j) break;
  1120. xassert(k <= ne);
  1121. /* find next (duplicate) element (i,j) */
  1122. for (k++; k <= ne; k++)
  1123. if (ia[k] == i && ja[k] == j) break;
  1124. xassert(k <= ne);
  1125. ret = +k;
  1126. goto skip;
  1127. }
  1128. flag[j] = 1;
  1129. }
  1130. /* clear column flags */
  1131. for (k = ptr[i]; k != 0; k = next[k])
  1132. flag[ja[k]] = 0;
  1133. }
  1134. /* no duplicate element found */
  1135. ret = 0;
  1136. skip: /* free working arrays */
  1137. xfree(ptr);
  1138. xfree(next);
  1139. xfree(flag);
  1140. done: return ret;
  1141. }
  1142. /***********************************************************************
  1143. * NAME
  1144. *
  1145. * glp_sort_matrix - sort elements of the constraint matrix
  1146. *
  1147. * SYNOPSIS
  1148. *
  1149. * void glp_sort_matrix(glp_prob *P);
  1150. *
  1151. * DESCRIPTION
  1152. *
  1153. * The routine glp_sort_matrix sorts elements of the constraint matrix
  1154. * rebuilding its row and column linked lists. On exit from the routine
  1155. * the constraint matrix is not changed, however, elements in the row
  1156. * linked lists become ordered by ascending column indices, and the
  1157. * elements in the column linked lists become ordered by ascending row
  1158. * indices. */
  1159. void glp_sort_matrix(glp_prob *P)
  1160. { GLPAIJ *aij;
  1161. int i, j;
  1162. if (P == NULL || P->magic != GLP_PROB_MAGIC)
  1163. xerror("glp_sort_matrix: P = %p; invalid problem object\n",
  1164. P);
  1165. /* rebuild row linked lists */
  1166. for (i = P->m; i >= 1; i--)
  1167. P->row[i]->ptr = NULL;
  1168. for (j = P->n; j >= 1; j--)
  1169. { for (aij = P->col[j]->ptr; aij != NULL; aij = aij->c_next)
  1170. { i = aij->row->i;
  1171. aij->r_prev = NULL;
  1172. aij->r_next = P->row[i]->ptr;
  1173. if (aij->r_next != NULL) aij->r_next->r_prev = aij;
  1174. P->row[i]->ptr = aij;
  1175. }
  1176. }
  1177. /* rebuild column linked lists */
  1178. for (j = P->n; j >= 1; j--)
  1179. P->col[j]->ptr = NULL;
  1180. for (i = P->m; i >= 1; i--)
  1181. { for (aij = P->row[i]->ptr; aij != NULL; aij = aij->r_next)
  1182. { j = aij->col->j;
  1183. aij->c_prev = NULL;
  1184. aij->c_next = P->col[j]->ptr;
  1185. if (aij->c_next != NULL) aij->c_next->c_prev = aij;
  1186. P->col[j]->ptr = aij;
  1187. }
  1188. }
  1189. return;
  1190. }
  1191. /***********************************************************************
  1192. * NAME
  1193. *
  1194. * glp_del_rows - delete rows from problem object
  1195. *
  1196. * SYNOPSIS
  1197. *
  1198. * void glp_del_rows(glp_prob *lp, int nrs, const int num[]);
  1199. *
  1200. * DESCRIPTION
  1201. *
  1202. * The routine glp_del_rows deletes rows from the specified problem
  1203. * object. Ordinal numbers of rows to be deleted should be placed in
  1204. * locations num[1], ..., num[nrs], where nrs > 0.
  1205. *
  1206. * Note that deleting rows involves changing ordinal numbers of other
  1207. * rows remaining in the problem object. New ordinal numbers of the
  1208. * remaining rows are assigned under the assumption that the original
  1209. * order of rows is not changed. */
  1210. void glp_del_rows(glp_prob *lp, int nrs, const int num[])
  1211. { glp_tree *tree = lp->tree;
  1212. GLPROW *row;
  1213. int i, k, m_new;
  1214. /* mark rows to be deleted */
  1215. if (!(1 <= nrs && nrs <= lp->m))
  1216. xerror("glp_del_rows: nrs = %d; invalid number of rows\n",
  1217. nrs);
  1218. for (k = 1; k <= nrs; k++)
  1219. { /* take the number of row to be deleted */
  1220. i = num[k];
  1221. /* obtain pointer to i-th row */
  1222. if (!(1 <= i && i <= lp->m))
  1223. xerror("glp_del_rows: num[%d] = %d; row number out of range"
  1224. "\n", k, i);
  1225. row = lp->row[i];
  1226. if (tree != NULL && tree->reason != 0)
  1227. { if (!(tree->reason == GLP_IROWGEN ||
  1228. tree->reason == GLP_ICUTGEN))
  1229. xerror("glp_del_rows: operation not allowed\n");
  1230. xassert(tree->curr != NULL);
  1231. if (row->level != tree->curr->level)
  1232. xerror("glp_del_rows: num[%d] = %d; invalid attempt to d"
  1233. "elete row created not in current subproblem\n", k,i);
  1234. if (row->stat != GLP_BS)
  1235. xerror("glp_del_rows: num[%d] = %d; invalid attempt to d"
  1236. "elete active row (constraint)\n", k, i);
  1237. tree->reinv = 1;
  1238. }
  1239. /* check that the row is not marked yet */
  1240. if (row->i == 0)
  1241. xerror("glp_del_rows: num[%d] = %d; duplicate row numbers n"
  1242. "ot allowed\n", k, i);
  1243. /* erase symbolic name assigned to the row */
  1244. glp_set_row_name(lp, i, NULL);
  1245. xassert(row->node == NULL);
  1246. /* erase corresponding row of the constraint matrix */
  1247. glp_set_mat_row(lp, i, 0, NULL, NULL);
  1248. xassert(row->ptr == NULL);
  1249. /* mark the row to be deleted */
  1250. row->i = 0;
  1251. }
  1252. /* delete all marked rows from the row list */
  1253. m_new = 0;
  1254. for (i = 1; i <= lp->m; i++)
  1255. { /* obtain pointer to i-th row */
  1256. row = lp->row[i];
  1257. /* check if the row is marked */
  1258. if (row->i == 0)
  1259. { /* it is marked, delete it */
  1260. dmp_free_atom(lp->pool, row, sizeof(GLPROW));
  1261. }
  1262. else
  1263. { /* it is not marked; keep it */
  1264. row->i = ++m_new;
  1265. lp->row[row->i] = row;
  1266. }
  1267. }
  1268. /* set new number of rows */
  1269. lp->m = m_new;
  1270. /* invalidate the basis factorization */
  1271. lp->valid = 0;
  1272. return;
  1273. }
  1274. /***********************************************************************
  1275. * NAME
  1276. *
  1277. * glp_del_cols - delete columns from problem object
  1278. *
  1279. * SYNOPSIS
  1280. *
  1281. * void glp_del_cols(glp_prob *lp, int ncs, const int num[]);
  1282. *
  1283. * DESCRIPTION
  1284. *
  1285. * The routine glp_del_cols deletes columns from the specified problem
  1286. * object. Ordinal numbers of columns to be deleted should be placed in
  1287. * locations num[1], ..., num[ncs], where ncs > 0.
  1288. *
  1289. * Note that deleting columns involves changing ordinal numbers of
  1290. * other columns remaining in the problem object. New ordinal numbers
  1291. * of the remaining columns are assigned under the assumption that the
  1292. * original order of columns is not changed. */
  1293. void glp_del_cols(glp_prob *lp, int ncs, const int num[])
  1294. { glp_tree *tree = lp->tree;
  1295. GLPCOL *col;
  1296. int j, k, n_new;
  1297. if (tree != NULL && tree->reason != 0)
  1298. xerror("glp_del_cols: operation not allowed\n");
  1299. /* mark columns to be deleted */
  1300. if (!(1 <= ncs && ncs <= lp->n))
  1301. xerror("glp_del_cols: ncs = %d; invalid number of columns\n",
  1302. ncs);
  1303. for (k = 1; k <= ncs; k++)
  1304. { /* take the number of column to be deleted */
  1305. j = num[k];
  1306. /* obtain pointer to j-th column */
  1307. if (!(1 <= j && j <= lp->n))
  1308. xerror("glp_del_cols: num[%d] = %d; column number out of ra"
  1309. "nge", k, j);
  1310. col = lp->col[j];
  1311. /* check that the column is not marked yet */
  1312. if (col->j == 0)
  1313. xerror("glp_del_cols: num[%d] = %d; duplicate column number"
  1314. "s not allowed\n", k, j);
  1315. /* erase symbolic name assigned to the column */
  1316. glp_set_col_name(lp, j, NULL);
  1317. xassert(col->node == NULL);
  1318. /* erase corresponding column of the constraint matrix */
  1319. glp_set_mat_col(lp, j, 0, NULL, NULL);
  1320. xassert(col->ptr == NULL);
  1321. /* mark the column to be deleted */
  1322. col->j = 0;
  1323. /* if it is basic, invalidate the basis factorization */
  1324. if (col->stat == GLP_BS) lp->valid = 0;
  1325. }
  1326. /* delete all marked columns from the column list */
  1327. n_new = 0;
  1328. for (j = 1; j <= lp->n; j++)
  1329. { /* obtain pointer to j-th column */
  1330. col = lp->col[j];
  1331. /* check if the column is marked */
  1332. if (col->j == 0)
  1333. { /* it is marked; delete it */
  1334. dmp_free_atom(lp->pool, col, sizeof(GLPCOL));
  1335. }
  1336. else
  1337. { /* it is not marked; keep it */
  1338. col->j = ++n_new;
  1339. lp->col[col->j] = col;
  1340. }
  1341. }
  1342. /* set new number of columns */
  1343. lp->n = n_new;
  1344. /* if the basis header is still valid, adjust it */
  1345. if (lp->valid)
  1346. { int m = lp->m;
  1347. int *head = lp->head;
  1348. for (j = 1; j <= n_new; j++)
  1349. { k = lp->col[j]->bind;
  1350. if (k != 0)
  1351. { xassert(1 <= k && k <= m);
  1352. head[k] = m + j;
  1353. }
  1354. }
  1355. }
  1356. return;
  1357. }
  1358. /***********************************************************************
  1359. * NAME
  1360. *
  1361. * glp_copy_prob - copy problem object content
  1362. *
  1363. * SYNOPSIS
  1364. *
  1365. * void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names);
  1366. *
  1367. * DESCRIPTION
  1368. *
  1369. * The routine glp_copy_prob copies the content of the problem object
  1370. * prob to the problem object dest.
  1371. *
  1372. * The parameter names is a flag. If it is non-zero, the routine also
  1373. * copies all symbolic names; otherwise, if it is zero, symbolic names
  1374. * are not copied. */
  1375. void glp_copy_prob(glp_prob *dest, glp_prob *prob, int names)
  1376. { glp_tree *tree = dest->tree;
  1377. glp_bfcp bfcp;
  1378. int i, j, len, *ind;
  1379. double *val;
  1380. if (tree != NULL && tree->reason != 0)
  1381. xerror("glp_copy_prob: operation not allowed\n");
  1382. if (dest == prob)
  1383. xerror("glp_copy_prob: copying problem object to itself not al"
  1384. "lowed\n");
  1385. if (!(names == GLP_ON || names == GLP_OFF))
  1386. xerror("glp_copy_prob: names = %d; invalid parameter\n",
  1387. names);
  1388. glp_erase_prob(dest);
  1389. if (names && prob->name != NULL)
  1390. glp_set_prob_name(dest, prob->name);
  1391. if (names && prob->obj != NULL)
  1392. glp_set_obj_name(dest, prob->obj);
  1393. dest->dir = prob->dir;
  1394. dest->c0 = prob->c0;
  1395. if (prob->m > 0)
  1396. glp_add_rows(dest, prob->m);
  1397. if (prob->n > 0)
  1398. glp_add_cols(dest, prob->n);
  1399. glp_get_bfcp(prob, &bfcp);
  1400. glp_set_bfcp(dest, &bfcp);
  1401. dest->pbs_stat = prob->pbs_stat;
  1402. dest->dbs_stat = prob->dbs_stat;
  1403. dest->obj_val = prob->obj_val;
  1404. dest->some = prob->some;
  1405. dest->ipt_stat = prob->ipt_stat;
  1406. dest->ipt_obj = prob->ipt_obj;
  1407. dest->mip_stat = prob->mip_stat;
  1408. dest->mip_obj = prob->mip_obj;
  1409. for (i = 1; i <= prob->m; i++)
  1410. { GLPROW *to = dest->row[i];
  1411. GLPROW *from = prob->row[i];
  1412. if (names && from->name != NULL)
  1413. glp_set_row_name(dest, i, from->name);
  1414. to->type = from->type;
  1415. to->lb = from->lb;
  1416. to->ub = from->ub;
  1417. to->rii = from->rii;
  1418. to->stat = from->stat;
  1419. to->prim = from->prim;
  1420. to->dual = from->dual;
  1421. to->pval = from->pval;
  1422. to->dval = from->dval;
  1423. to->mipx = from->mipx;
  1424. }
  1425. ind = xcalloc(1+prob->m, sizeof(int));
  1426. val = xcalloc(1+prob->m, sizeof(double));
  1427. for (j = 1; j <= prob->n; j++)
  1428. { GLPCOL *to = dest->col[j];
  1429. GLPCOL *from = prob->col[j];
  1430. if (names && from->name != NULL)
  1431. glp_set_col_name(dest, j, from->name);
  1432. to->kind = from->kind;
  1433. to->type = from->type;
  1434. to->lb = from->lb;
  1435. to->ub = from->ub;
  1436. to->coef = from->coef;
  1437. len = glp_get_mat_col(prob, j, ind, val);
  1438. glp_set_mat_col(dest, j, len, ind, val);
  1439. to->sjj = from->sjj;
  1440. to->stat = from->stat;
  1441. to->prim = from->prim;
  1442. to->dual = from->dual;
  1443. to->pval = from->pval;
  1444. to->dval = from->dval;
  1445. to->mipx = from->mipx;
  1446. }
  1447. xfree(ind);
  1448. xfree(val);
  1449. return;
  1450. }
  1451. /***********************************************************************
  1452. * NAME
  1453. *
  1454. * glp_erase_prob - erase problem object content
  1455. *
  1456. * SYNOPSIS
  1457. *
  1458. * void glp_erase_prob(glp_prob *lp);
  1459. *
  1460. * DESCRIPTION
  1461. *
  1462. * The routine glp_erase_prob erases the content of the specified
  1463. * problem object. The effect of this operation is the same as if the
  1464. * problem object would be deleted with the routine glp_delete_prob and
  1465. * then created anew with the routine glp_create_prob, with exception
  1466. * that the handle (pointer) to the problem object remains valid. */
  1467. static void delete_prob(glp_prob *lp);
  1468. void glp_erase_prob(glp_prob *lp)
  1469. { glp_tree *tree = lp->tree;
  1470. if (tree != NULL && tree->reason != 0)
  1471. xerror("glp_erase_prob: operation not allowed\n");
  1472. delete_prob(lp);
  1473. create_prob(lp);
  1474. return;
  1475. }
  1476. /***********************************************************************
  1477. * NAME
  1478. *
  1479. * glp_delete_prob - delete problem object
  1480. *
  1481. * SYNOPSIS
  1482. *
  1483. * void glp_delete_prob(glp_prob *lp);
  1484. *
  1485. * DESCRIPTION
  1486. *
  1487. * The routine glp_delete_prob deletes the specified problem object and
  1488. * frees all the memory allocated to it. */
  1489. static void delete_prob(glp_prob *lp)
  1490. { lp->magic = 0x3F3F3F3F;
  1491. dmp_delete_pool(lp->pool);
  1492. #if 0 /* 17/XI-2009 */
  1493. xfree(lp->cps);
  1494. #else
  1495. if (lp->parms != NULL) xfree(lp->parms);
  1496. #endif
  1497. xassert(lp->tree == NULL);
  1498. #if 0
  1499. if (lp->cwa != NULL) xfree(lp->cwa);
  1500. #endif
  1501. xfree(lp->row);
  1502. xfree(lp->col);
  1503. if (lp->r_tree != NULL) avl_delete_tree(lp->r_tree);
  1504. if (lp->c_tree != NULL) avl_delete_tree(lp->c_tree);
  1505. xfree(lp->head);
  1506. if (lp->bfcp != NULL) xfree(lp->bfcp);
  1507. if (lp->bfd != NULL) bfd_delete_it(lp->bfd);
  1508. return;
  1509. }
  1510. void glp_delete_prob(glp_prob *lp)
  1511. { glp_tree *tree = lp->tree;
  1512. if (tree != NULL && tree->reason != 0)
  1513. xerror("glp_delete_prob: operation not allowed\n");
  1514. delete_prob(lp);
  1515. xfree(lp);
  1516. return;
  1517. }
  1518. /* eof */