glpnpp03.c 96 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701170217031704170517061707170817091710171117121713171417151716171717181719172017211722172317241725172617271728172917301731173217331734173517361737173817391740174117421743174417451746174717481749175017511752175317541755175617571758175917601761176217631764176517661767176817691770177117721773177417751776177717781779178017811782178317841785178617871788178917901791179217931794179517961797179817991800180118021803180418051806180718081809181018111812181318141815181618171818181918201821182218231824182518261827182818291830183118321833183418351836183718381839184018411842184318441845184618471848184918501851185218531854185518561857185818591860186118621863186418651866186718681869187018711872187318741875187618771878187918801881188218831884188518861887188818891890189118921893189418951896189718981899190019011902190319041905190619071908190919101911191219131914191519161917191819191920192119221923192419251926192719281929193019311932193319341935193619371938193919401941194219431944194519461947194819491950195119521953195419551956195719581959196019611962196319641965196619671968196919701971197219731974197519761977197819791980198119821983198419851986198719881989199019911992199319941995199619971998199920002001200220032004200520062007200820092010201120122013201420152016201720182019202020212022202320242025202620272028202920302031203220332034203520362037203820392040204120422043204420452046204720482049205020512052205320542055205620572058205920602061206220632064206520662067206820692070207120722073207420752076207720782079208020812082208320842085208620872088208920902091209220932094209520962097209820992100210121022103210421052106210721082109211021112112211321142115211621172118211921202121212221232124212521262127212821292130213121322133213421352136213721382139214021412142214321442145214621472148214921502151215221532154215521562157215821592160216121622163216421652166216721682169217021712172217321742175217621772178217921802181218221832184218521862187218821892190219121922193219421952196219721982199220022012202220322042205220622072208220922102211221222132214221522162217221822192220222122222223222422252226222722282229223022312232223322342235223622372238223922402241224222432244224522462247224822492250225122522253225422552256225722582259226022612262226322642265226622672268226922702271227222732274227522762277227822792280228122822283228422852286228722882289229022912292229322942295229622972298229923002301230223032304230523062307230823092310231123122313231423152316231723182319232023212322232323242325232623272328232923302331233223332334233523362337233823392340234123422343234423452346234723482349235023512352235323542355235623572358235923602361236223632364236523662367236823692370237123722373237423752376237723782379238023812382238323842385238623872388238923902391239223932394239523962397239823992400240124022403240424052406240724082409241024112412241324142415241624172418241924202421242224232424242524262427242824292430243124322433243424352436243724382439244024412442244324442445244624472448244924502451245224532454245524562457245824592460246124622463246424652466246724682469247024712472247324742475247624772478247924802481248224832484248524862487248824892490249124922493249424952496249724982499250025012502250325042505250625072508250925102511251225132514251525162517251825192520252125222523252425252526252725282529253025312532253325342535253625372538253925402541254225432544254525462547254825492550255125522553255425552556255725582559256025612562256325642565256625672568256925702571257225732574257525762577257825792580258125822583258425852586258725882589259025912592259325942595259625972598259926002601260226032604260526062607260826092610261126122613261426152616261726182619262026212622262326242625262626272628262926302631263226332634263526362637263826392640264126422643264426452646264726482649265026512652265326542655265626572658265926602661266226632664266526662667266826692670267126722673267426752676267726782679268026812682268326842685268626872688268926902691269226932694269526962697269826992700270127022703270427052706270727082709271027112712271327142715271627172718271927202721272227232724272527262727272827292730273127322733273427352736273727382739274027412742274327442745274627472748274927502751275227532754275527562757275827592760276127622763276427652766276727682769277027712772277327742775277627772778277927802781278227832784278527862787278827892790279127922793279427952796279727982799280028012802280328042805280628072808280928102811281228132814281528162817281828192820282128222823282428252826282728282829283028312832283328342835283628372838283928402841284228432844284528462847284828492850285128522853285428552856285728582859286028612862
  1. /* glpnpp03.c */
  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 "glpnpp.h"
  24. /***********************************************************************
  25. * NAME
  26. *
  27. * npp_empty_row - process empty row
  28. *
  29. * SYNOPSIS
  30. *
  31. * #include "glpnpp.h"
  32. * int npp_empty_row(NPP *npp, NPPROW *p);
  33. *
  34. * DESCRIPTION
  35. *
  36. * The routine npp_empty_row processes row p, which is empty, i.e.
  37. * coefficients at all columns in this row are zero:
  38. *
  39. * L[p] <= sum 0 x[j] <= U[p], (1)
  40. *
  41. * where L[p] <= U[p].
  42. *
  43. * RETURNS
  44. *
  45. * 0 - success;
  46. *
  47. * 1 - problem has no primal feasible solution.
  48. *
  49. * PROBLEM TRANSFORMATION
  50. *
  51. * If the following conditions hold:
  52. *
  53. * L[p] <= +eps, U[p] >= -eps, (2)
  54. *
  55. * where eps is an absolute tolerance for row value, the row p is
  56. * redundant. In this case it can be replaced by equivalent redundant
  57. * row, which is free (unbounded), and then removed from the problem.
  58. * Otherwise, the row p is infeasible and, thus, the problem has no
  59. * primal feasible solution.
  60. *
  61. * RECOVERING BASIC SOLUTION
  62. *
  63. * See the routine npp_free_row.
  64. *
  65. * RECOVERING INTERIOR-POINT SOLUTION
  66. *
  67. * See the routine npp_free_row.
  68. *
  69. * RECOVERING MIP SOLUTION
  70. *
  71. * None needed. */
  72. int npp_empty_row(NPP *npp, NPPROW *p)
  73. { /* process empty row */
  74. double eps = 1e-3;
  75. /* the row must be empty */
  76. xassert(p->ptr == NULL);
  77. /* check primal feasibility */
  78. if (p->lb > +eps || p->ub < -eps)
  79. return 1;
  80. /* replace the row by equivalent free (unbounded) row */
  81. p->lb = -DBL_MAX, p->ub = +DBL_MAX;
  82. /* and process it */
  83. npp_free_row(npp, p);
  84. return 0;
  85. }
  86. /***********************************************************************
  87. * NAME
  88. *
  89. * npp_empty_col - process empty column
  90. *
  91. * SYNOPSIS
  92. *
  93. * #include "glpnpp.h"
  94. * int npp_empty_col(NPP *npp, NPPCOL *q);
  95. *
  96. * DESCRIPTION
  97. *
  98. * The routine npp_empty_col processes column q:
  99. *
  100. * l[q] <= x[q] <= u[q], (1)
  101. *
  102. * where l[q] <= u[q], which is empty, i.e. has zero coefficients in
  103. * all constraint rows.
  104. *
  105. * RETURNS
  106. *
  107. * 0 - success;
  108. *
  109. * 1 - problem has no dual feasible solution.
  110. *
  111. * PROBLEM TRANSFORMATION
  112. *
  113. * The row of the dual system corresponding to the empty column is the
  114. * following:
  115. *
  116. * sum 0 pi[i] + lambda[q] = c[q], (2)
  117. * i
  118. *
  119. * from which it follows that:
  120. *
  121. * lambda[q] = c[q]. (3)
  122. *
  123. * If the following condition holds:
  124. *
  125. * c[q] < - eps, (4)
  126. *
  127. * where eps is an absolute tolerance for column multiplier, the lower
  128. * column bound l[q] must be active to provide dual feasibility (note
  129. * that being preprocessed the problem is always minimization). In this
  130. * case the column can be fixed on its lower bound and removed from the
  131. * problem (if the column is integral, its bounds are also assumed to
  132. * be integral). And if the column has no lower bound (l[q] = -oo), the
  133. * problem has no dual feasible solution.
  134. *
  135. * If the following condition holds:
  136. *
  137. * c[q] > + eps, (5)
  138. *
  139. * the upper column bound u[q] must be active to provide dual
  140. * feasibility. In this case the column can be fixed on its upper bound
  141. * and removed from the problem. And if the column has no upper bound
  142. * (u[q] = +oo), the problem has no dual feasible solution.
  143. *
  144. * Finally, if the following condition holds:
  145. *
  146. * - eps <= c[q] <= +eps, (6)
  147. *
  148. * dual feasibility does not depend on a particular value of column q.
  149. * In this case the column can be fixed either on its lower bound (if
  150. * l[q] > -oo) or on its upper bound (if u[q] < +oo) or at zero (if the
  151. * column is unbounded) and then removed from the problem.
  152. *
  153. * RECOVERING BASIC SOLUTION
  154. *
  155. * See the routine npp_fixed_col. Having been recovered the column
  156. * is assigned status GLP_NS. However, if actually it is not fixed
  157. * (l[q] < u[q]), its status should be changed to GLP_NL, GLP_NU, or
  158. * GLP_NF depending on which bound it was fixed on transformation stage.
  159. *
  160. * RECOVERING INTERIOR-POINT SOLUTION
  161. *
  162. * See the routine npp_fixed_col.
  163. *
  164. * RECOVERING MIP SOLUTION
  165. *
  166. * See the routine npp_fixed_col. */
  167. struct empty_col
  168. { /* empty column */
  169. int q;
  170. /* column reference number */
  171. char stat;
  172. /* status in basic solution */
  173. };
  174. static int rcv_empty_col(NPP *npp, void *info);
  175. int npp_empty_col(NPP *npp, NPPCOL *q)
  176. { /* process empty column */
  177. struct empty_col *info;
  178. double eps = 1e-3;
  179. /* the column must be empty */
  180. xassert(q->ptr == NULL);
  181. /* check dual feasibility */
  182. if (q->coef > +eps && q->lb == -DBL_MAX)
  183. return 1;
  184. if (q->coef < -eps && q->ub == +DBL_MAX)
  185. return 1;
  186. /* create transformation stack entry */
  187. info = npp_push_tse(npp,
  188. rcv_empty_col, sizeof(struct empty_col));
  189. info->q = q->j;
  190. /* fix the column */
  191. if (q->lb == -DBL_MAX && q->ub == +DBL_MAX)
  192. { /* free column */
  193. info->stat = GLP_NF;
  194. q->lb = q->ub = 0.0;
  195. }
  196. else if (q->ub == +DBL_MAX)
  197. lo: { /* column with lower bound */
  198. info->stat = GLP_NL;
  199. q->ub = q->lb;
  200. }
  201. else if (q->lb == -DBL_MAX)
  202. up: { /* column with upper bound */
  203. info->stat = GLP_NU;
  204. q->lb = q->ub;
  205. }
  206. else if (q->lb != q->ub)
  207. { /* double-bounded column */
  208. if (q->coef >= +DBL_EPSILON) goto lo;
  209. if (q->coef <= -DBL_EPSILON) goto up;
  210. if (fabs(q->lb) <= fabs(q->ub)) goto lo; else goto up;
  211. }
  212. else
  213. { /* fixed column */
  214. info->stat = GLP_NS;
  215. }
  216. /* process fixed column */
  217. npp_fixed_col(npp, q);
  218. return 0;
  219. }
  220. static int rcv_empty_col(NPP *npp, void *_info)
  221. { /* recover empty column */
  222. struct empty_col *info = _info;
  223. if (npp->sol == GLP_SOL)
  224. npp->c_stat[info->q] = info->stat;
  225. return 0;
  226. }
  227. /***********************************************************************
  228. * NAME
  229. *
  230. * npp_implied_value - process implied column value
  231. *
  232. * SYNOPSIS
  233. *
  234. * #include "glpnpp.h"
  235. * int npp_implied_value(NPP *npp, NPPCOL *q, double s);
  236. *
  237. * DESCRIPTION
  238. *
  239. * For column q:
  240. *
  241. * l[q] <= x[q] <= u[q], (1)
  242. *
  243. * where l[q] < u[q], the routine npp_implied_value processes its
  244. * implied value s[q]. If this implied value satisfies to the current
  245. * column bounds and integrality condition, the routine fixes column q
  246. * at the given point. Note that the column is kept in the problem in
  247. * any case.
  248. *
  249. * RETURNS
  250. *
  251. * 0 - column has been fixed;
  252. *
  253. * 1 - implied value violates to current column bounds;
  254. *
  255. * 2 - implied value violates integrality condition.
  256. *
  257. * ALGORITHM
  258. *
  259. * Implied column value s[q] satisfies to the current column bounds if
  260. * the following condition holds:
  261. *
  262. * l[q] - eps <= s[q] <= u[q] + eps, (2)
  263. *
  264. * where eps is an absolute tolerance for column value. If the column
  265. * is integral, the following condition also must hold:
  266. *
  267. * |s[q] - floor(s[q]+0.5)| <= eps, (3)
  268. *
  269. * where floor(s[q]+0.5) is the nearest integer to s[q].
  270. *
  271. * If both condition (2) and (3) are satisfied, the column can be fixed
  272. * at the value s[q], or, if it is integral, at floor(s[q]+0.5).
  273. * Otherwise, if s[q] violates (2) or (3), the problem has no feasible
  274. * solution.
  275. *
  276. * Note: If s[q] is close to l[q] or u[q], it seems to be reasonable to
  277. * fix the column at its lower or upper bound, resp. rather than at the
  278. * implied value. */
  279. int npp_implied_value(NPP *npp, NPPCOL *q, double s)
  280. { /* process implied column value */
  281. double eps, nint;
  282. xassert(npp == npp);
  283. /* column must not be fixed */
  284. xassert(q->lb < q->ub);
  285. /* check integrality */
  286. if (q->is_int)
  287. { nint = floor(s + 0.5);
  288. if (fabs(s - nint) <= 1e-5)
  289. s = nint;
  290. else
  291. return 2;
  292. }
  293. /* check current column lower bound */
  294. if (q->lb != -DBL_MAX)
  295. { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb));
  296. if (s < q->lb - eps) return 1;
  297. /* if s[q] is close to l[q], fix column at its lower bound
  298. rather than at the implied value */
  299. if (s < q->lb + 1e-3 * eps)
  300. { q->ub = q->lb;
  301. return 0;
  302. }
  303. }
  304. /* check current column upper bound */
  305. if (q->ub != +DBL_MAX)
  306. { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub));
  307. if (s > q->ub + eps) return 1;
  308. /* if s[q] is close to u[q], fix column at its upper bound
  309. rather than at the implied value */
  310. if (s > q->ub - 1e-3 * eps)
  311. { q->lb = q->ub;
  312. return 0;
  313. }
  314. }
  315. /* fix column at the implied value */
  316. q->lb = q->ub = s;
  317. return 0;
  318. }
  319. /***********************************************************************
  320. * NAME
  321. *
  322. * npp_eq_singlet - process row singleton (equality constraint)
  323. *
  324. * SYNOPSIS
  325. *
  326. * #include "glpnpp.h"
  327. * int npp_eq_singlet(NPP *npp, NPPROW *p);
  328. *
  329. * DESCRIPTION
  330. *
  331. * The routine npp_eq_singlet processes row p, which is equiality
  332. * constraint having the only non-zero coefficient:
  333. *
  334. * a[p,q] x[q] = b. (1)
  335. *
  336. * RETURNS
  337. *
  338. * 0 - success;
  339. *
  340. * 1 - problem has no primal feasible solution;
  341. *
  342. * 2 - problem has no integer feasible solution.
  343. *
  344. * PROBLEM TRANSFORMATION
  345. *
  346. * The equality constraint defines implied value of column q:
  347. *
  348. * x[q] = s[q] = b / a[p,q]. (2)
  349. *
  350. * If the implied value s[q] satisfies to the column bounds (see the
  351. * routine npp_implied_value), the column can be fixed at s[q] and
  352. * removed from the problem. In this case row p becomes redundant, so
  353. * it can be replaced by equivalent free row and also removed from the
  354. * problem.
  355. *
  356. * Note that the routine removes from the problem only row p. Column q
  357. * becomes fixed, however, it is kept in the problem.
  358. *
  359. * RECOVERING BASIC SOLUTION
  360. *
  361. * In solution to the original problem row p is assigned status GLP_NS
  362. * (active equality constraint), and column q is assigned status GLP_BS
  363. * (basic column).
  364. *
  365. * Multiplier for row p can be computed as follows. In the dual system
  366. * of the original problem column q corresponds to the following row:
  367. *
  368. * sum a[i,q] pi[i] + lambda[q] = c[q] ==>
  369. * i
  370. *
  371. * sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q].
  372. * i!=p
  373. *
  374. * Therefore:
  375. *
  376. * 1
  377. * pi[p] = ------ (c[q] - lambda[q] - sum a[i,q] pi[i]), (3)
  378. * a[p,q] i!=q
  379. *
  380. * where lambda[q] = 0 (since column[q] is basic), and pi[i] for all
  381. * i != p are known in solution to the transformed problem.
  382. *
  383. * Value of column q in solution to the original problem is assigned
  384. * its implied value s[q].
  385. *
  386. * RECOVERING INTERIOR-POINT SOLUTION
  387. *
  388. * Multiplier for row p is computed with formula (3). Value of column
  389. * q is assigned its implied value s[q].
  390. *
  391. * RECOVERING MIP SOLUTION
  392. *
  393. * Value of column q is assigned its implied value s[q]. */
  394. struct eq_singlet
  395. { /* row singleton (equality constraint) */
  396. int p;
  397. /* row reference number */
  398. int q;
  399. /* column reference number */
  400. double apq;
  401. /* constraint coefficient a[p,q] */
  402. double c;
  403. /* objective coefficient at x[q] */
  404. NPPLFE *ptr;
  405. /* list of non-zero coefficients a[i,q], i != p */
  406. };
  407. static int rcv_eq_singlet(NPP *npp, void *info);
  408. int npp_eq_singlet(NPP *npp, NPPROW *p)
  409. { /* process row singleton (equality constraint) */
  410. struct eq_singlet *info;
  411. NPPCOL *q;
  412. NPPAIJ *aij;
  413. NPPLFE *lfe;
  414. int ret;
  415. double s;
  416. /* the row must be singleton equality constraint */
  417. xassert(p->lb == p->ub);
  418. xassert(p->ptr != NULL && p->ptr->r_next == NULL);
  419. /* compute and process implied column value */
  420. aij = p->ptr;
  421. q = aij->col;
  422. s = p->lb / aij->val;
  423. ret = npp_implied_value(npp, q, s);
  424. xassert(0 <= ret && ret <= 2);
  425. if (ret != 0) return ret;
  426. /* create transformation stack entry */
  427. info = npp_push_tse(npp,
  428. rcv_eq_singlet, sizeof(struct eq_singlet));
  429. info->p = p->i;
  430. info->q = q->j;
  431. info->apq = aij->val;
  432. info->c = q->coef;
  433. info->ptr = NULL;
  434. /* save column coefficients a[i,q], i != p (not needed for MIP
  435. solution) */
  436. if (npp->sol != GLP_MIP)
  437. { for (aij = q->ptr; aij != NULL; aij = aij->c_next)
  438. { if (aij->row == p) continue; /* skip a[p,q] */
  439. lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE));
  440. lfe->ref = aij->row->i;
  441. lfe->val = aij->val;
  442. lfe->next = info->ptr;
  443. info->ptr = lfe;
  444. }
  445. }
  446. /* remove the row from the problem */
  447. npp_del_row(npp, p);
  448. return 0;
  449. }
  450. static int rcv_eq_singlet(NPP *npp, void *_info)
  451. { /* recover row singleton (equality constraint) */
  452. struct eq_singlet *info = _info;
  453. NPPLFE *lfe;
  454. double temp;
  455. if (npp->sol == GLP_SOL)
  456. { /* column q must be already recovered as GLP_NS */
  457. if (npp->c_stat[info->q] != GLP_NS)
  458. { npp_error();
  459. return 1;
  460. }
  461. npp->r_stat[info->p] = GLP_NS;
  462. npp->c_stat[info->q] = GLP_BS;
  463. }
  464. if (npp->sol != GLP_MIP)
  465. { /* compute multiplier for row p with formula (3) */
  466. temp = info->c;
  467. for (lfe = info->ptr; lfe != NULL; lfe = lfe->next)
  468. temp -= lfe->val * npp->r_pi[lfe->ref];
  469. npp->r_pi[info->p] = temp / info->apq;
  470. }
  471. return 0;
  472. }
  473. /***********************************************************************
  474. * NAME
  475. *
  476. * npp_implied_lower - process implied column lower bound
  477. *
  478. * SYNOPSIS
  479. *
  480. * #include "glpnpp.h"
  481. * int npp_implied_lower(NPP *npp, NPPCOL *q, double l);
  482. *
  483. * DESCRIPTION
  484. *
  485. * For column q:
  486. *
  487. * l[q] <= x[q] <= u[q], (1)
  488. *
  489. * where l[q] < u[q], the routine npp_implied_lower processes its
  490. * implied lower bound l'[q]. As the result the current column lower
  491. * bound may increase. Note that the column is kept in the problem in
  492. * any case.
  493. *
  494. * RETURNS
  495. *
  496. * 0 - current column lower bound has not changed;
  497. *
  498. * 1 - current column lower bound has changed, but not significantly;
  499. *
  500. * 2 - current column lower bound has significantly changed;
  501. *
  502. * 3 - column has been fixed on its upper bound;
  503. *
  504. * 4 - implied lower bound violates current column upper bound.
  505. *
  506. * ALGORITHM
  507. *
  508. * If column q is integral, before processing its implied lower bound
  509. * should be rounded up:
  510. *
  511. * ( floor(l'[q]+0.5), if |l'[q] - floor(l'[q]+0.5)| <= eps
  512. * l'[q] := < (2)
  513. * ( ceil(l'[q]), otherwise
  514. *
  515. * where floor(l'[q]+0.5) is the nearest integer to l'[q], ceil(l'[q])
  516. * is smallest integer not less than l'[q], and eps is an absolute
  517. * tolerance for column value.
  518. *
  519. * Processing implied column lower bound l'[q] includes the following
  520. * cases:
  521. *
  522. * 1) if l'[q] < l[q] + eps, implied lower bound is redundant;
  523. *
  524. * 2) if l[q] + eps <= l[q] <= u[q] + eps, current column lower bound
  525. * l[q] can be strengthened by replacing it with l'[q]. If in this
  526. * case new column lower bound becomes close to current column upper
  527. * bound u[q], the column can be fixed on its upper bound;
  528. *
  529. * 3) if l'[q] > u[q] + eps, implied lower bound violates current
  530. * column upper bound u[q], in which case the problem has no primal
  531. * feasible solution. */
  532. int npp_implied_lower(NPP *npp, NPPCOL *q, double l)
  533. { /* process implied column lower bound */
  534. int ret;
  535. double eps, nint;
  536. xassert(npp == npp);
  537. /* column must not be fixed */
  538. xassert(q->lb < q->ub);
  539. /* implied lower bound must be finite */
  540. xassert(l != -DBL_MAX);
  541. /* if column is integral, round up l'[q] */
  542. if (q->is_int)
  543. { nint = floor(l + 0.5);
  544. if (fabs(l - nint) <= 1e-5)
  545. l = nint;
  546. else
  547. l = ceil(l);
  548. }
  549. /* check current column lower bound */
  550. if (q->lb != -DBL_MAX)
  551. { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->lb));
  552. if (l < q->lb + eps)
  553. { ret = 0; /* redundant */
  554. goto done;
  555. }
  556. }
  557. /* check current column upper bound */
  558. if (q->ub != +DBL_MAX)
  559. { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->ub));
  560. if (l > q->ub + eps)
  561. { ret = 4; /* infeasible */
  562. goto done;
  563. }
  564. /* if l'[q] is close to u[q], fix column at its upper bound */
  565. if (l > q->ub - 1e-3 * eps)
  566. { q->lb = q->ub;
  567. ret = 3; /* fixed */
  568. goto done;
  569. }
  570. }
  571. /* check if column lower bound changes significantly */
  572. if (q->lb == -DBL_MAX)
  573. ret = 2; /* significantly */
  574. else if (q->is_int && l > q->lb + 0.5)
  575. ret = 2; /* significantly */
  576. else if (l > q->lb + 0.30 * (1.0 + fabs(q->lb)))
  577. ret = 2; /* significantly */
  578. else
  579. ret = 1; /* not significantly */
  580. /* set new column lower bound */
  581. q->lb = l;
  582. done: return ret;
  583. }
  584. /***********************************************************************
  585. * NAME
  586. *
  587. * npp_implied_upper - process implied column upper bound
  588. *
  589. * SYNOPSIS
  590. *
  591. * #include "glpnpp.h"
  592. * int npp_implied_upper(NPP *npp, NPPCOL *q, double u);
  593. *
  594. * DESCRIPTION
  595. *
  596. * For column q:
  597. *
  598. * l[q] <= x[q] <= u[q], (1)
  599. *
  600. * where l[q] < u[q], the routine npp_implied_upper processes its
  601. * implied upper bound u'[q]. As the result the current column upper
  602. * bound may decrease. Note that the column is kept in the problem in
  603. * any case.
  604. *
  605. * RETURNS
  606. *
  607. * 0 - current column upper bound has not changed;
  608. *
  609. * 1 - current column upper bound has changed, but not significantly;
  610. *
  611. * 2 - current column upper bound has significantly changed;
  612. *
  613. * 3 - column has been fixed on its lower bound;
  614. *
  615. * 4 - implied upper bound violates current column lower bound.
  616. *
  617. * ALGORITHM
  618. *
  619. * If column q is integral, before processing its implied upper bound
  620. * should be rounded down:
  621. *
  622. * ( floor(u'[q]+0.5), if |u'[q] - floor(l'[q]+0.5)| <= eps
  623. * u'[q] := < (2)
  624. * ( floor(l'[q]), otherwise
  625. *
  626. * where floor(u'[q]+0.5) is the nearest integer to u'[q],
  627. * floor(u'[q]) is largest integer not greater than u'[q], and eps is
  628. * an absolute tolerance for column value.
  629. *
  630. * Processing implied column upper bound u'[q] includes the following
  631. * cases:
  632. *
  633. * 1) if u'[q] > u[q] - eps, implied upper bound is redundant;
  634. *
  635. * 2) if l[q] - eps <= u[q] <= u[q] - eps, current column upper bound
  636. * u[q] can be strengthened by replacing it with u'[q]. If in this
  637. * case new column upper bound becomes close to current column lower
  638. * bound, the column can be fixed on its lower bound;
  639. *
  640. * 3) if u'[q] < l[q] - eps, implied upper bound violates current
  641. * column lower bound l[q], in which case the problem has no primal
  642. * feasible solution. */
  643. int npp_implied_upper(NPP *npp, NPPCOL *q, double u)
  644. { int ret;
  645. double eps, nint;
  646. xassert(npp == npp);
  647. /* column must not be fixed */
  648. xassert(q->lb < q->ub);
  649. /* implied upper bound must be finite */
  650. xassert(u != +DBL_MAX);
  651. /* if column is integral, round down u'[q] */
  652. if (q->is_int)
  653. { nint = floor(u + 0.5);
  654. if (fabs(u - nint) <= 1e-5)
  655. u = nint;
  656. else
  657. u = floor(u);
  658. }
  659. /* check current column upper bound */
  660. if (q->ub != +DBL_MAX)
  661. { eps = (q->is_int ? 1e-3 : 1e-3 + 1e-6 * fabs(q->ub));
  662. if (u > q->ub - eps)
  663. { ret = 0; /* redundant */
  664. goto done;
  665. }
  666. }
  667. /* check current column lower bound */
  668. if (q->lb != -DBL_MAX)
  669. { eps = (q->is_int ? 1e-5 : 1e-5 + 1e-8 * fabs(q->lb));
  670. if (u < q->lb - eps)
  671. { ret = 4; /* infeasible */
  672. goto done;
  673. }
  674. /* if u'[q] is close to l[q], fix column at its lower bound */
  675. if (u < q->lb + 1e-3 * eps)
  676. { q->ub = q->lb;
  677. ret = 3; /* fixed */
  678. goto done;
  679. }
  680. }
  681. /* check if column upper bound changes significantly */
  682. if (q->ub == +DBL_MAX)
  683. ret = 2; /* significantly */
  684. else if (q->is_int && u < q->ub - 0.5)
  685. ret = 2; /* significantly */
  686. else if (u < q->ub - 0.30 * (1.0 + fabs(q->ub)))
  687. ret = 2; /* significantly */
  688. else
  689. ret = 1; /* not significantly */
  690. /* set new column upper bound */
  691. q->ub = u;
  692. done: return ret;
  693. }
  694. /***********************************************************************
  695. * NAME
  696. *
  697. * npp_ineq_singlet - process row singleton (inequality constraint)
  698. *
  699. * SYNOPSIS
  700. *
  701. * #include "glpnpp.h"
  702. * int npp_ineq_singlet(NPP *npp, NPPROW *p);
  703. *
  704. * DESCRIPTION
  705. *
  706. * The routine npp_ineq_singlet processes row p, which is inequality
  707. * constraint having the only non-zero coefficient:
  708. *
  709. * L[p] <= a[p,q] * x[q] <= U[p], (1)
  710. *
  711. * where L[p] < U[p], L[p] > -oo and/or U[p] < +oo.
  712. *
  713. * RETURNS
  714. *
  715. * 0 - current column bounds have not changed;
  716. *
  717. * 1 - current column bounds have changed, but not significantly;
  718. *
  719. * 2 - current column bounds have significantly changed;
  720. *
  721. * 3 - column has been fixed on its lower or upper bound;
  722. *
  723. * 4 - problem has no primal feasible solution.
  724. *
  725. * PROBLEM TRANSFORMATION
  726. *
  727. * Inequality constraint (1) defines implied bounds of column q:
  728. *
  729. * ( L[p] / a[p,q], if a[p,q] > 0
  730. * l'[q] = < (2)
  731. * ( U[p] / a[p,q], if a[p,q] < 0
  732. *
  733. * ( U[p] / a[p,q], if a[p,q] > 0
  734. * u'[q] = < (3)
  735. * ( L[p] / a[p,q], if a[p,q] < 0
  736. *
  737. * If these implied bounds do not violate current bounds of column q:
  738. *
  739. * l[q] <= x[q] <= u[q], (4)
  740. *
  741. * they can be used to strengthen the current column bounds:
  742. *
  743. * l[q] := max(l[q], l'[q]), (5)
  744. *
  745. * u[q] := min(u[q], u'[q]). (6)
  746. *
  747. * (See the routines npp_implied_lower and npp_implied_upper.)
  748. *
  749. * Once bounds of row p (1) have been carried over column q, the row
  750. * becomes redundant, so it can be replaced by equivalent free row and
  751. * removed from the problem.
  752. *
  753. * Note that the routine removes from the problem only row p. Column q,
  754. * even it has been fixed, is kept in the problem.
  755. *
  756. * RECOVERING BASIC SOLUTION
  757. *
  758. * Note that the row in the dual system corresponding to column q is
  759. * the following:
  760. *
  761. * sum a[i,q] pi[i] + lambda[q] = c[q] ==>
  762. * i
  763. * (7)
  764. * sum a[i,q] pi[i] + a[p,q] pi[p] + lambda[q] = c[q],
  765. * i!=p
  766. *
  767. * where pi[i] for all i != p are known in solution to the transformed
  768. * problem. Row p does not exist in the transformed problem, so it has
  769. * zero multiplier there. This allows computing multiplier for column q
  770. * in solution to the transformed problem:
  771. *
  772. * lambda~[q] = c[q] - sum a[i,q] pi[i]. (8)
  773. * i!=p
  774. *
  775. * Let in solution to the transformed problem column q be non-basic
  776. * with lower bound active (GLP_NL, lambda~[q] >= 0), and this lower
  777. * bound be implied one l'[q]. From the original problem's standpoint
  778. * this then means that actually the original column lower bound l[q]
  779. * is inactive, and active is that row bound L[p] or U[p] that defines
  780. * the implied bound l'[q] (2). In this case in solution to the
  781. * original problem column q is assigned status GLP_BS while row p is
  782. * assigned status GLP_NL (if a[p,q] > 0) or GLP_NU (if a[p,q] < 0).
  783. * Since now column q is basic, its multiplier lambda[q] is zero. This
  784. * allows using (7) and (8) to find multiplier for row p in solution to
  785. * the original problem:
  786. *
  787. * 1
  788. * pi[p] = ------ (c[q] - sum a[i,q] pi[i]) = lambda~[q] / a[p,q] (9)
  789. * a[p,q] i!=p
  790. *
  791. * Now let in solution to the transformed problem column q be non-basic
  792. * with upper bound active (GLP_NU, lambda~[q] <= 0), and this upper
  793. * bound be implied one u'[q]. As in the previous case this then means
  794. * that from the original problem's standpoint actually the original
  795. * column upper bound u[q] is inactive, and active is that row bound
  796. * L[p] or U[p] that defines the implied bound u'[q] (3). In this case
  797. * in solution to the original problem column q is assigned status
  798. * GLP_BS, row p is assigned status GLP_NU (if a[p,q] > 0) or GLP_NL
  799. * (if a[p,q] < 0), and its multiplier is computed with formula (9).
  800. *
  801. * Strengthening bounds of column q according to (5) and (6) may make
  802. * it fixed. Thus, if in solution to the transformed problem column q is
  803. * non-basic and fixed (GLP_NS), we can suppose that if lambda~[q] > 0,
  804. * column q has active lower bound (GLP_NL), and if lambda~[q] < 0,
  805. * column q has active upper bound (GLP_NU), reducing this case to two
  806. * previous ones. If, however, lambda~[q] is close to zero or
  807. * corresponding bound of row p does not exist (this may happen if
  808. * lambda~[q] has wrong sign due to round-off errors, in which case it
  809. * is expected to be close to zero, since solution is assumed to be dual
  810. * feasible), column q can be assigned status GLP_BS (basic), and row p
  811. * can be made active on its existing bound. In the latter case row
  812. * multiplier pi[p] computed with formula (9) will be also close to
  813. * zero, and dual feasibility will be kept.
  814. *
  815. * In all other cases, namely, if in solution to the transformed
  816. * problem column q is basic (GLP_BS), or non-basic with original lower
  817. * bound l[q] active (GLP_NL), or non-basic with original upper bound
  818. * u[q] active (GLP_NU), constraint (1) is inactive. So in solution to
  819. * the original problem status of column q remains unchanged, row p is
  820. * assigned status GLP_BS, and its multiplier pi[p] is assigned zero
  821. * value.
  822. *
  823. * RECOVERING INTERIOR-POINT SOLUTION
  824. *
  825. * First, value of multiplier for column q in solution to the original
  826. * problem is computed with formula (8). If lambda~[q] > 0 and column q
  827. * has implied lower bound, or if lambda~[q] < 0 and column q has
  828. * implied upper bound, this means that from the original problem's
  829. * standpoint actually row p has corresponding active bound, in which
  830. * case its multiplier pi[p] is computed with formula (9). In other
  831. * cases, when the sign of lambda~[q] corresponds to original bound of
  832. * column q, or when lambda~[q] =~ 0, value of row multiplier pi[p] is
  833. * assigned zero value.
  834. *
  835. * RECOVERING MIP SOLUTION
  836. *
  837. * None needed. */
  838. struct ineq_singlet
  839. { /* row singleton (inequality constraint) */
  840. int p;
  841. /* row reference number */
  842. int q;
  843. /* column reference number */
  844. double apq;
  845. /* constraint coefficient a[p,q] */
  846. double c;
  847. /* objective coefficient at x[q] */
  848. double lb;
  849. /* row lower bound */
  850. double ub;
  851. /* row upper bound */
  852. char lb_changed;
  853. /* this flag is set if column lower bound was changed */
  854. char ub_changed;
  855. /* this flag is set if column upper bound was changed */
  856. NPPLFE *ptr;
  857. /* list of non-zero coefficients a[i,q], i != p */
  858. };
  859. static int rcv_ineq_singlet(NPP *npp, void *info);
  860. int npp_ineq_singlet(NPP *npp, NPPROW *p)
  861. { /* process row singleton (inequality constraint) */
  862. struct ineq_singlet *info;
  863. NPPCOL *q;
  864. NPPAIJ *apq, *aij;
  865. NPPLFE *lfe;
  866. int lb_changed, ub_changed;
  867. double ll, uu;
  868. /* the row must be singleton inequality constraint */
  869. xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX);
  870. xassert(p->lb < p->ub);
  871. xassert(p->ptr != NULL && p->ptr->r_next == NULL);
  872. /* compute implied column bounds */
  873. apq = p->ptr;
  874. q = apq->col;
  875. xassert(q->lb < q->ub);
  876. if (apq->val > 0.0)
  877. { ll = (p->lb == -DBL_MAX ? -DBL_MAX : p->lb / apq->val);
  878. uu = (p->ub == +DBL_MAX ? +DBL_MAX : p->ub / apq->val);
  879. }
  880. else
  881. { ll = (p->ub == +DBL_MAX ? -DBL_MAX : p->ub / apq->val);
  882. uu = (p->lb == -DBL_MAX ? +DBL_MAX : p->lb / apq->val);
  883. }
  884. /* process implied column lower bound */
  885. if (ll == -DBL_MAX)
  886. lb_changed = 0;
  887. else
  888. { lb_changed = npp_implied_lower(npp, q, ll);
  889. xassert(0 <= lb_changed && lb_changed <= 4);
  890. if (lb_changed == 4) return 4; /* infeasible */
  891. }
  892. /* process implied column upper bound */
  893. if (uu == +DBL_MAX)
  894. ub_changed = 0;
  895. else if (lb_changed == 3)
  896. { /* column was fixed on its upper bound due to l'[q] = u[q] */
  897. /* note that L[p] < U[p], so l'[q] = u[q] < u'[q] */
  898. ub_changed = 0;
  899. }
  900. else
  901. { ub_changed = npp_implied_upper(npp, q, uu);
  902. xassert(0 <= ub_changed && ub_changed <= 4);
  903. if (ub_changed == 4) return 4; /* infeasible */
  904. }
  905. /* if neither lower nor upper column bound was changed, the row
  906. is originally redundant and can be replaced by free row */
  907. if (!lb_changed && !ub_changed)
  908. { p->lb = -DBL_MAX, p->ub = +DBL_MAX;
  909. npp_free_row(npp, p);
  910. return 0;
  911. }
  912. /* create transformation stack entry */
  913. info = npp_push_tse(npp,
  914. rcv_ineq_singlet, sizeof(struct ineq_singlet));
  915. info->p = p->i;
  916. info->q = q->j;
  917. info->apq = apq->val;
  918. info->c = q->coef;
  919. info->lb = p->lb;
  920. info->ub = p->ub;
  921. info->lb_changed = (char)lb_changed;
  922. info->ub_changed = (char)ub_changed;
  923. info->ptr = NULL;
  924. /* save column coefficients a[i,q], i != p (not needed for MIP
  925. solution) */
  926. if (npp->sol != GLP_MIP)
  927. { for (aij = q->ptr; aij != NULL; aij = aij->c_next)
  928. { if (aij == apq) continue; /* skip a[p,q] */
  929. lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE));
  930. lfe->ref = aij->row->i;
  931. lfe->val = aij->val;
  932. lfe->next = info->ptr;
  933. info->ptr = lfe;
  934. }
  935. }
  936. /* remove the row from the problem */
  937. npp_del_row(npp, p);
  938. return lb_changed >= ub_changed ? lb_changed : ub_changed;
  939. }
  940. static int rcv_ineq_singlet(NPP *npp, void *_info)
  941. { /* recover row singleton (inequality constraint) */
  942. struct ineq_singlet *info = _info;
  943. NPPLFE *lfe;
  944. double lambda;
  945. if (npp->sol == GLP_MIP) goto done;
  946. /* compute lambda~[q] in solution to the transformed problem
  947. with formula (8) */
  948. lambda = info->c;
  949. for (lfe = info->ptr; lfe != NULL; lfe = lfe->next)
  950. lambda -= lfe->val * npp->r_pi[lfe->ref];
  951. if (npp->sol == GLP_SOL)
  952. { /* recover basic solution */
  953. if (npp->c_stat[info->q] == GLP_BS)
  954. { /* column q is basic, so row p is inactive */
  955. npp->r_stat[info->p] = GLP_BS;
  956. npp->r_pi[info->p] = 0.0;
  957. }
  958. else if (npp->c_stat[info->q] == GLP_NL)
  959. nl: { /* column q is non-basic with lower bound active */
  960. if (info->lb_changed)
  961. { /* it is implied bound, so actually row p is active
  962. while column q is basic */
  963. npp->r_stat[info->p] =
  964. (char)(info->apq > 0.0 ? GLP_NL : GLP_NU);
  965. npp->c_stat[info->q] = GLP_BS;
  966. npp->r_pi[info->p] = lambda / info->apq;
  967. }
  968. else
  969. { /* it is original bound, so row p is inactive */
  970. npp->r_stat[info->p] = GLP_BS;
  971. npp->r_pi[info->p] = 0.0;
  972. }
  973. }
  974. else if (npp->c_stat[info->q] == GLP_NU)
  975. nu: { /* column q is non-basic with upper bound active */
  976. if (info->ub_changed)
  977. { /* it is implied bound, so actually row p is active
  978. while column q is basic */
  979. npp->r_stat[info->p] =
  980. (char)(info->apq > 0.0 ? GLP_NU : GLP_NL);
  981. npp->c_stat[info->q] = GLP_BS;
  982. npp->r_pi[info->p] = lambda / info->apq;
  983. }
  984. else
  985. { /* it is original bound, so row p is inactive */
  986. npp->r_stat[info->p] = GLP_BS;
  987. npp->r_pi[info->p] = 0.0;
  988. }
  989. }
  990. else if (npp->c_stat[info->q] == GLP_NS)
  991. { /* column q is non-basic and fixed; note, however, that in
  992. in the original problem it is non-fixed */
  993. if (lambda > +1e-7)
  994. { if (info->apq > 0.0 && info->lb != -DBL_MAX ||
  995. info->apq < 0.0 && info->ub != +DBL_MAX ||
  996. !info->lb_changed)
  997. { /* either corresponding bound of row p exists or
  998. column q remains non-basic with its original lower
  999. bound active */
  1000. npp->c_stat[info->q] = GLP_NL;
  1001. goto nl;
  1002. }
  1003. }
  1004. if (lambda < -1e-7)
  1005. { if (info->apq > 0.0 && info->ub != +DBL_MAX ||
  1006. info->apq < 0.0 && info->lb != -DBL_MAX ||
  1007. !info->ub_changed)
  1008. { /* either corresponding bound of row p exists or
  1009. column q remains non-basic with its original upper
  1010. bound active */
  1011. npp->c_stat[info->q] = GLP_NU;
  1012. goto nu;
  1013. }
  1014. }
  1015. /* either lambda~[q] is close to zero, or corresponding
  1016. bound of row p does not exist, because lambda~[q] has
  1017. wrong sign due to round-off errors; in the latter case
  1018. lambda~[q] is also assumed to be close to zero; so, we
  1019. can make row p active on its existing bound and column q
  1020. basic; pi[p] will have wrong sign, but it also will be
  1021. close to zero (rarus casus of dual degeneracy) */
  1022. if (info->lb != -DBL_MAX && info->ub == +DBL_MAX)
  1023. { /* row lower bound exists, but upper bound doesn't */
  1024. npp->r_stat[info->p] = GLP_NL;
  1025. }
  1026. else if (info->lb == -DBL_MAX && info->ub != +DBL_MAX)
  1027. { /* row upper bound exists, but lower bound doesn't */
  1028. npp->r_stat[info->p] = GLP_NU;
  1029. }
  1030. else if (info->lb != -DBL_MAX && info->ub != +DBL_MAX)
  1031. { /* both row lower and upper bounds exist */
  1032. /* to choose proper active row bound we should not use
  1033. lambda~[q], because its value being close to zero is
  1034. unreliable; so we choose that bound which provides
  1035. primal feasibility for original constraint (1) */
  1036. if (info->apq * npp->c_value[info->q] <=
  1037. 0.5 * (info->lb + info->ub))
  1038. npp->r_stat[info->p] = GLP_NL;
  1039. else
  1040. npp->r_stat[info->p] = GLP_NU;
  1041. }
  1042. else
  1043. { npp_error();
  1044. return 1;
  1045. }
  1046. npp->c_stat[info->q] = GLP_BS;
  1047. npp->r_pi[info->p] = lambda / info->apq;
  1048. }
  1049. else
  1050. { npp_error();
  1051. return 1;
  1052. }
  1053. }
  1054. if (npp->sol == GLP_IPT)
  1055. { /* recover interior-point solution */
  1056. if (lambda > +DBL_EPSILON && info->lb_changed ||
  1057. lambda < -DBL_EPSILON && info->ub_changed)
  1058. { /* actually row p has corresponding active bound */
  1059. npp->r_pi[info->p] = lambda / info->apq;
  1060. }
  1061. else
  1062. { /* either bounds of column q are both inactive or its
  1063. original bound is active */
  1064. npp->r_pi[info->p] = 0.0;
  1065. }
  1066. }
  1067. done: return 0;
  1068. }
  1069. /***********************************************************************
  1070. * NAME
  1071. *
  1072. * npp_implied_slack - process column singleton (implied slack variable)
  1073. *
  1074. * SYNOPSIS
  1075. *
  1076. * #include "glpnpp.h"
  1077. * void npp_implied_slack(NPP *npp, NPPCOL *q);
  1078. *
  1079. * DESCRIPTION
  1080. *
  1081. * The routine npp_implied_slack processes column q:
  1082. *
  1083. * l[q] <= x[q] <= u[q], (1)
  1084. *
  1085. * where l[q] < u[q], having the only non-zero coefficient in row p,
  1086. * which is equality constraint:
  1087. *
  1088. * sum a[p,j] x[j] + a[p,q] x[q] = b. (2)
  1089. * j!=q
  1090. *
  1091. * PROBLEM TRANSFORMATION
  1092. *
  1093. * (If x[q] is integral, this transformation must not be used.)
  1094. *
  1095. * The term a[p,q] x[q] in constraint (2) can be considered as a slack
  1096. * variable that allows to carry bounds of column q over row p and then
  1097. * remove column q from the problem.
  1098. *
  1099. * Constraint (2) can be written as follows:
  1100. *
  1101. * sum a[p,j] x[j] = b - a[p,q] x[q]. (3)
  1102. * j!=q
  1103. *
  1104. * According to (1) constraint (3) is equivalent to the following
  1105. * inequality constraint:
  1106. *
  1107. * L[p] <= sum a[p,j] x[j] <= U[p], (4)
  1108. * j!=q
  1109. *
  1110. * where
  1111. *
  1112. * ( b - a[p,q] u[q], if a[p,q] > 0
  1113. * L[p] = < (5)
  1114. * ( b - a[p,q] l[q], if a[p,q] < 0
  1115. *
  1116. * ( b - a[p,q] l[q], if a[p,q] > 0
  1117. * U[p] = < (6)
  1118. * ( b - a[p,q] u[q], if a[p,q] < 0
  1119. *
  1120. * From (2) it follows that:
  1121. *
  1122. * 1
  1123. * x[q] = ------ (b - sum a[p,j] x[j]). (7)
  1124. * a[p,q] j!=q
  1125. *
  1126. * In order to eliminate x[q] from the objective row we substitute it
  1127. * from (6) to that row:
  1128. *
  1129. * z = sum c[j] x[j] + c[q] x[q] + c[0] =
  1130. * j!=q
  1131. * 1
  1132. * = sum c[j] x[j] + c[q] [------ (b - sum a[p,j] x[j])] + c0 =
  1133. * j!=q a[p,q] j!=q
  1134. *
  1135. * = sum c~[j] x[j] + c~[0],
  1136. * j!=q
  1137. * a[p,j] b
  1138. * c~[j] = c[j] - c[q] ------, c~0 = c0 - c[q] ------ (8)
  1139. * a[p,q] a[p,q]
  1140. *
  1141. * are values of objective coefficients and constant term, resp., in
  1142. * the transformed problem.
  1143. *
  1144. * Note that column q is column singleton, so in the dual system of the
  1145. * original problem it corresponds to the following row singleton:
  1146. *
  1147. * a[p,q] pi[p] + lambda[q] = c[q]. (9)
  1148. *
  1149. * In the transformed problem row (9) would be the following:
  1150. *
  1151. * a[p,q] pi~[p] + lambda[q] = c~[q] = 0. (10)
  1152. *
  1153. * Subtracting (10) from (9) we have:
  1154. *
  1155. * a[p,q] (pi[p] - pi~[p]) = c[q]
  1156. *
  1157. * that gives the following formula to compute multiplier for row p in
  1158. * solution to the original problem using its value in solution to the
  1159. * transformed problem:
  1160. *
  1161. * pi[p] = pi~[p] + c[q] / a[p,q]. (11)
  1162. *
  1163. * RECOVERING BASIC SOLUTION
  1164. *
  1165. * Status of column q in solution to the original problem is defined
  1166. * by status of row p in solution to the transformed problem and the
  1167. * sign of coefficient a[p,q] in the original inequality constraint (2)
  1168. * as follows:
  1169. *
  1170. * +-----------------------+---------+--------------------+
  1171. * | Status of row p | Sign of | Status of column q |
  1172. * | (transformed problem) | a[p,q] | (original problem) |
  1173. * +-----------------------+---------+--------------------+
  1174. * | GLP_BS | + / - | GLP_BS |
  1175. * | GLP_NL | + | GLP_NU |
  1176. * | GLP_NL | - | GLP_NL |
  1177. * | GLP_NU | + | GLP_NL |
  1178. * | GLP_NU | - | GLP_NU |
  1179. * | GLP_NF | + / - | GLP_NF |
  1180. * +-----------------------+---------+--------------------+
  1181. *
  1182. * Value of column q is computed with formula (7). Since originally row
  1183. * p is equality constraint, its status is assigned GLP_NS, and value of
  1184. * its multiplier pi[p] is computed with formula (11).
  1185. *
  1186. * RECOVERING INTERIOR-POINT SOLUTION
  1187. *
  1188. * Value of column q is computed with formula (7). Row multiplier value
  1189. * pi[p] is computed with formula (11).
  1190. *
  1191. * RECOVERING MIP SOLUTION
  1192. *
  1193. * Value of column q is computed with formula (7). */
  1194. struct implied_slack
  1195. { /* column singleton (implied slack variable) */
  1196. int p;
  1197. /* row reference number */
  1198. int q;
  1199. /* column reference number */
  1200. double apq;
  1201. /* constraint coefficient a[p,q] */
  1202. double b;
  1203. /* right-hand side of original equality constraint */
  1204. double c;
  1205. /* original objective coefficient at x[q] */
  1206. NPPLFE *ptr;
  1207. /* list of non-zero coefficients a[p,j], j != q */
  1208. };
  1209. static int rcv_implied_slack(NPP *npp, void *info);
  1210. void npp_implied_slack(NPP *npp, NPPCOL *q)
  1211. { /* process column singleton (implied slack variable) */
  1212. struct implied_slack *info;
  1213. NPPROW *p;
  1214. NPPAIJ *aij;
  1215. NPPLFE *lfe;
  1216. /* the column must be non-integral non-fixed singleton */
  1217. xassert(!q->is_int);
  1218. xassert(q->lb < q->ub);
  1219. xassert(q->ptr != NULL && q->ptr->c_next == NULL);
  1220. /* corresponding row must be equality constraint */
  1221. aij = q->ptr;
  1222. p = aij->row;
  1223. xassert(p->lb == p->ub);
  1224. /* create transformation stack entry */
  1225. info = npp_push_tse(npp,
  1226. rcv_implied_slack, sizeof(struct implied_slack));
  1227. info->p = p->i;
  1228. info->q = q->j;
  1229. info->apq = aij->val;
  1230. info->b = p->lb;
  1231. info->c = q->coef;
  1232. info->ptr = NULL;
  1233. /* save row coefficients a[p,j], j != q, and substitute x[q]
  1234. into the objective row */
  1235. for (aij = p->ptr; aij != NULL; aij = aij->r_next)
  1236. { if (aij->col == q) continue; /* skip a[p,q] */
  1237. lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE));
  1238. lfe->ref = aij->col->j;
  1239. lfe->val = aij->val;
  1240. lfe->next = info->ptr;
  1241. info->ptr = lfe;
  1242. aij->col->coef -= info->c * (aij->val / info->apq);
  1243. }
  1244. npp->c0 += info->c * (info->b / info->apq);
  1245. /* compute new row bounds */
  1246. if (info->apq > 0.0)
  1247. { p->lb = (q->ub == +DBL_MAX ?
  1248. -DBL_MAX : info->b - info->apq * q->ub);
  1249. p->ub = (q->lb == -DBL_MAX ?
  1250. +DBL_MAX : info->b - info->apq * q->lb);
  1251. }
  1252. else
  1253. { p->lb = (q->lb == -DBL_MAX ?
  1254. -DBL_MAX : info->b - info->apq * q->lb);
  1255. p->ub = (q->ub == +DBL_MAX ?
  1256. +DBL_MAX : info->b - info->apq * q->ub);
  1257. }
  1258. /* remove the column from the problem */
  1259. npp_del_col(npp, q);
  1260. return;
  1261. }
  1262. static int rcv_implied_slack(NPP *npp, void *_info)
  1263. { /* recover column singleton (implied slack variable) */
  1264. struct implied_slack *info = _info;
  1265. NPPLFE *lfe;
  1266. double temp;
  1267. if (npp->sol == GLP_SOL)
  1268. { /* assign statuses to row p and column q */
  1269. if (npp->r_stat[info->p] == GLP_BS ||
  1270. npp->r_stat[info->p] == GLP_NF)
  1271. npp->c_stat[info->q] = npp->r_stat[info->p];
  1272. else if (npp->r_stat[info->p] == GLP_NL)
  1273. npp->c_stat[info->q] =
  1274. (char)(info->apq > 0.0 ? GLP_NU : GLP_NL);
  1275. else if (npp->r_stat[info->p] == GLP_NU)
  1276. npp->c_stat[info->q] =
  1277. (char)(info->apq > 0.0 ? GLP_NL : GLP_NU);
  1278. else
  1279. { npp_error();
  1280. return 1;
  1281. }
  1282. npp->r_stat[info->p] = GLP_NS;
  1283. }
  1284. if (npp->sol != GLP_MIP)
  1285. { /* compute multiplier for row p */
  1286. npp->r_pi[info->p] += info->c / info->apq;
  1287. }
  1288. /* compute value of column q */
  1289. temp = info->b;
  1290. for (lfe = info->ptr; lfe != NULL; lfe = lfe->next)
  1291. temp -= lfe->val * npp->c_value[lfe->ref];
  1292. npp->c_value[info->q] = temp / info->apq;
  1293. return 0;
  1294. }
  1295. /***********************************************************************
  1296. * NAME
  1297. *
  1298. * npp_implied_free - process column singleton (implied free variable)
  1299. *
  1300. * SYNOPSIS
  1301. *
  1302. * #include "glpnpp.h"
  1303. * int npp_implied_free(NPP *npp, NPPCOL *q);
  1304. *
  1305. * DESCRIPTION
  1306. *
  1307. * The routine npp_implied_free processes column q:
  1308. *
  1309. * l[q] <= x[q] <= u[q], (1)
  1310. *
  1311. * having non-zero coefficient in the only row p, which is inequality
  1312. * constraint:
  1313. *
  1314. * L[p] <= sum a[p,j] x[j] + a[p,q] x[q] <= U[p], (2)
  1315. * j!=q
  1316. *
  1317. * where l[q] < u[q], L[p] < U[p], L[p] > -oo and/or U[p] < +oo.
  1318. *
  1319. * RETURNS
  1320. *
  1321. * 0 - success;
  1322. *
  1323. * 1 - column lower and/or upper bound(s) can be active;
  1324. *
  1325. * 2 - problem has no dual feasible solution.
  1326. *
  1327. * PROBLEM TRANSFORMATION
  1328. *
  1329. * Constraint (2) can be written as follows:
  1330. *
  1331. * L[p] - sum a[p,j] x[j] <= a[p,q] x[q] <= U[p] - sum a[p,j] x[j],
  1332. * j!=q j!=q
  1333. *
  1334. * from which it follows that:
  1335. *
  1336. * alfa <= a[p,q] x[q] <= beta, (3)
  1337. *
  1338. * where
  1339. *
  1340. * alfa = inf(L[p] - sum a[p,j] x[j]) =
  1341. * j!=q
  1342. *
  1343. * = L[p] - sup sum a[p,j] x[j] = (4)
  1344. * j!=q
  1345. *
  1346. * = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j],
  1347. * j in Jp j in Jn
  1348. *
  1349. * beta = sup(L[p] - sum a[p,j] x[j]) =
  1350. * j!=q
  1351. *
  1352. * = L[p] - inf sum a[p,j] x[j] = (5)
  1353. * j!=q
  1354. *
  1355. * = L[p] - sum a[p,j] l[j] - sum a[p,j] u[j],
  1356. * j in Jp j in Jn
  1357. *
  1358. * Jp = {j != q: a[p,j] > 0}, Jn = {j != q: a[p,j] < 0}. (6)
  1359. *
  1360. * Inequality (3) defines implied bounds of variable x[q]:
  1361. *
  1362. * l'[q] <= x[q] <= u'[q], (7)
  1363. *
  1364. * where
  1365. *
  1366. * ( alfa / a[p,q], if a[p,q] > 0
  1367. * l'[q] = < (8a)
  1368. * ( beta / a[p,q], if a[p,q] < 0
  1369. *
  1370. * ( beta / a[p,q], if a[p,q] > 0
  1371. * u'[q] = < (8b)
  1372. * ( alfa / a[p,q], if a[p,q] < 0
  1373. *
  1374. * Thus, if l'[q] > l[q] - eps and u'[q] < u[q] + eps, where eps is
  1375. * an absolute tolerance for column value, column bounds (1) cannot be
  1376. * active, in which case column q can be replaced by equivalent free
  1377. * (unbounded) column.
  1378. *
  1379. * Note that column q is column singleton, so in the dual system of the
  1380. * original problem it corresponds to the following row singleton:
  1381. *
  1382. * a[p,q] pi[p] + lambda[q] = c[q], (9)
  1383. *
  1384. * from which it follows that:
  1385. *
  1386. * pi[p] = (c[q] - lambda[q]) / a[p,q]. (10)
  1387. *
  1388. * Let x[q] be implied free (unbounded) variable. Then column q can be
  1389. * only basic, so its multiplier lambda[q] is equal to zero, and from
  1390. * (10) we have:
  1391. *
  1392. * pi[p] = c[q] / a[p,q]. (11)
  1393. *
  1394. * There are possible three cases:
  1395. *
  1396. * 1) pi[p] < -eps, where eps is an absolute tolerance for row
  1397. * multiplier. In this case, to provide dual feasibility of the
  1398. * original problem, row p must be active on its lower bound, and
  1399. * if its lower bound does not exist (L[p] = -oo), the problem has
  1400. * no dual feasible solution;
  1401. *
  1402. * 2) pi[p] > +eps. In this case row p must be active on its upper
  1403. * bound, and if its upper bound does not exist (U[p] = +oo), the
  1404. * problem has no dual feasible solution;
  1405. *
  1406. * 3) -eps <= pi[p] <= +eps. In this case any (either lower or upper)
  1407. * bound of row p can be active, because this does not affect dual
  1408. * feasibility.
  1409. *
  1410. * Thus, in all three cases original inequality constraint (2) can be
  1411. * replaced by equality constraint, where the right-hand side is either
  1412. * lower or upper bound of row p, and bounds of column q can be removed
  1413. * that makes it free (unbounded). (May note that this transformation
  1414. * can be followed by transformation "Column singleton (implied slack
  1415. * variable)" performed by the routine npp_implied_slack.)
  1416. *
  1417. * RECOVERING BASIC SOLUTION
  1418. *
  1419. * Status of row p in solution to the original problem is determined
  1420. * by its status in solution to the transformed problem and its bound,
  1421. * which was choosen to be active:
  1422. *
  1423. * +-----------------------+--------+--------------------+
  1424. * | Status of row p | Active | Status of row p |
  1425. * | (transformed problem) | bound | (original problem) |
  1426. * +-----------------------+--------+--------------------+
  1427. * | GLP_BS | L[p] | GLP_BS |
  1428. * | GLP_BS | U[p] | GLP_BS |
  1429. * | GLP_NS | L[p] | GLP_NL |
  1430. * | GLP_NS | U[p] | GLP_NU |
  1431. * +-----------------------+--------+--------------------+
  1432. *
  1433. * Value of row multiplier pi[p] (as well as value of column q) in
  1434. * solution to the original problem is the same as in solution to the
  1435. * transformed problem.
  1436. *
  1437. * RECOVERING INTERIOR-POINT SOLUTION
  1438. *
  1439. * Value of row multiplier pi[p] in solution to the original problem is
  1440. * the same as in solution to the transformed problem.
  1441. *
  1442. * RECOVERING MIP SOLUTION
  1443. *
  1444. * None needed. */
  1445. struct implied_free
  1446. { /* column singleton (implied free variable) */
  1447. int p;
  1448. /* row reference number */
  1449. char stat;
  1450. /* row status:
  1451. GLP_NL - active constraint on lower bound
  1452. GLP_NU - active constraint on upper bound */
  1453. };
  1454. static int rcv_implied_free(NPP *npp, void *info);
  1455. int npp_implied_free(NPP *npp, NPPCOL *q)
  1456. { /* process column singleton (implied free variable) */
  1457. struct implied_free *info;
  1458. NPPROW *p;
  1459. NPPAIJ *apq, *aij;
  1460. double alfa, beta, l, u, pi, eps;
  1461. /* the column must be non-fixed singleton */
  1462. xassert(q->lb < q->ub);
  1463. xassert(q->ptr != NULL && q->ptr->c_next == NULL);
  1464. /* corresponding row must be inequality constraint */
  1465. apq = q->ptr;
  1466. p = apq->row;
  1467. xassert(p->lb != -DBL_MAX || p->ub != +DBL_MAX);
  1468. xassert(p->lb < p->ub);
  1469. /* compute alfa */
  1470. alfa = p->lb;
  1471. if (alfa != -DBL_MAX)
  1472. { for (aij = p->ptr; aij != NULL; aij = aij->r_next)
  1473. { if (aij == apq) continue; /* skip a[p,q] */
  1474. if (aij->val > 0.0)
  1475. { if (aij->col->ub == +DBL_MAX)
  1476. { alfa = -DBL_MAX;
  1477. break;
  1478. }
  1479. alfa -= aij->val * aij->col->ub;
  1480. }
  1481. else /* < 0.0 */
  1482. { if (aij->col->lb == -DBL_MAX)
  1483. { alfa = -DBL_MAX;
  1484. break;
  1485. }
  1486. alfa -= aij->val * aij->col->lb;
  1487. }
  1488. }
  1489. }
  1490. /* compute beta */
  1491. beta = p->ub;
  1492. if (beta != +DBL_MAX)
  1493. { for (aij = p->ptr; aij != NULL; aij = aij->r_next)
  1494. { if (aij == apq) continue; /* skip a[p,q] */
  1495. if (aij->val > 0.0)
  1496. { if (aij->col->lb == -DBL_MAX)
  1497. { beta = +DBL_MAX;
  1498. break;
  1499. }
  1500. beta -= aij->val * aij->col->lb;
  1501. }
  1502. else /* < 0.0 */
  1503. { if (aij->col->ub == +DBL_MAX)
  1504. { beta = +DBL_MAX;
  1505. break;
  1506. }
  1507. beta -= aij->val * aij->col->ub;
  1508. }
  1509. }
  1510. }
  1511. /* compute implied column lower bound l'[q] */
  1512. if (apq->val > 0.0)
  1513. l = (alfa == -DBL_MAX ? -DBL_MAX : alfa / apq->val);
  1514. else /* < 0.0 */
  1515. l = (beta == +DBL_MAX ? -DBL_MAX : beta / apq->val);
  1516. /* compute implied column upper bound u'[q] */
  1517. if (apq->val > 0.0)
  1518. u = (beta == +DBL_MAX ? +DBL_MAX : beta / apq->val);
  1519. else
  1520. u = (alfa == -DBL_MAX ? +DBL_MAX : alfa / apq->val);
  1521. /* check if column lower bound l[q] can be active */
  1522. if (q->lb != -DBL_MAX)
  1523. { eps = 1e-9 + 1e-12 * fabs(q->lb);
  1524. if (l < q->lb - eps) return 1; /* yes, it can */
  1525. }
  1526. /* check if column upper bound u[q] can be active */
  1527. if (q->ub != +DBL_MAX)
  1528. { eps = 1e-9 + 1e-12 * fabs(q->ub);
  1529. if (u > q->ub + eps) return 1; /* yes, it can */
  1530. }
  1531. /* okay; make column q free (unbounded) */
  1532. q->lb = -DBL_MAX, q->ub = +DBL_MAX;
  1533. /* create transformation stack entry */
  1534. info = npp_push_tse(npp,
  1535. rcv_implied_free, sizeof(struct implied_free));
  1536. info->p = p->i;
  1537. info->stat = -1;
  1538. /* compute row multiplier pi[p] */
  1539. pi = q->coef / apq->val;
  1540. /* check dual feasibility for row p */
  1541. if (pi > +DBL_EPSILON)
  1542. { /* lower bound L[p] must be active */
  1543. if (p->lb != -DBL_MAX)
  1544. nl: { info->stat = GLP_NL;
  1545. p->ub = p->lb;
  1546. }
  1547. else
  1548. { if (pi > +1e-5) return 2; /* dual infeasibility */
  1549. /* take a chance on U[p] */
  1550. xassert(p->ub != +DBL_MAX);
  1551. goto nu;
  1552. }
  1553. }
  1554. else if (pi < -DBL_EPSILON)
  1555. { /* upper bound U[p] must be active */
  1556. if (p->ub != +DBL_MAX)
  1557. nu: { info->stat = GLP_NU;
  1558. p->lb = p->ub;
  1559. }
  1560. else
  1561. { if (pi < -1e-5) return 2; /* dual infeasibility */
  1562. /* take a chance on L[p] */
  1563. xassert(p->lb != -DBL_MAX);
  1564. goto nl;
  1565. }
  1566. }
  1567. else
  1568. { /* any bound (either L[p] or U[p]) can be made active */
  1569. if (p->ub == +DBL_MAX)
  1570. { xassert(p->lb != -DBL_MAX);
  1571. goto nl;
  1572. }
  1573. if (p->lb == -DBL_MAX)
  1574. { xassert(p->ub != +DBL_MAX);
  1575. goto nu;
  1576. }
  1577. if (fabs(p->lb) <= fabs(p->ub)) goto nl; else goto nu;
  1578. }
  1579. return 0;
  1580. }
  1581. static int rcv_implied_free(NPP *npp, void *_info)
  1582. { /* recover column singleton (implied free variable) */
  1583. struct implied_free *info = _info;
  1584. if (npp->sol == GLP_SOL)
  1585. { if (npp->r_stat[info->p] == GLP_BS)
  1586. npp->r_stat[info->p] = GLP_BS;
  1587. else if (npp->r_stat[info->p] == GLP_NS)
  1588. { xassert(info->stat == GLP_NL || info->stat == GLP_NU);
  1589. npp->r_stat[info->p] = info->stat;
  1590. }
  1591. else
  1592. { npp_error();
  1593. return 1;
  1594. }
  1595. }
  1596. return 0;
  1597. }
  1598. /***********************************************************************
  1599. * NAME
  1600. *
  1601. * npp_eq_doublet - process row doubleton (equality constraint)
  1602. *
  1603. * SYNOPSIS
  1604. *
  1605. * #include "glpnpp.h"
  1606. * NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p);
  1607. *
  1608. * DESCRIPTION
  1609. *
  1610. * The routine npp_eq_doublet processes row p, which is equality
  1611. * constraint having exactly two non-zero coefficients:
  1612. *
  1613. * a[p,q] x[q] + a[p,r] x[r] = b. (1)
  1614. *
  1615. * As the result of processing one of columns q or r is eliminated from
  1616. * all other rows and, thus, becomes column singleton of type "implied
  1617. * slack variable". Row p is not changed and along with column q and r
  1618. * remains in the problem.
  1619. *
  1620. * RETURNS
  1621. *
  1622. * The routine npp_eq_doublet returns pointer to the descriptor of that
  1623. * column q or r which has been eliminated. If, due to some reason, the
  1624. * elimination was not performed, the routine returns NULL.
  1625. *
  1626. * PROBLEM TRANSFORMATION
  1627. *
  1628. * First, we decide which column q or r will be eliminated. Let it be
  1629. * column q. Consider i-th constraint row, where column q has non-zero
  1630. * coefficient a[i,q] != 0:
  1631. *
  1632. * L[i] <= sum a[i,j] x[j] <= U[i]. (2)
  1633. * j
  1634. *
  1635. * In order to eliminate column q from row (2) we subtract from it row
  1636. * (1) multiplied by gamma[i] = a[i,q] / a[p,q], i.e. we replace in the
  1637. * transformed problem row (2) by its linear combination with row (1).
  1638. * This transformation changes only coefficients in columns q and r,
  1639. * and bounds of row i as follows:
  1640. *
  1641. * a~[i,q] = a[i,q] - gamma[i] a[p,q] = 0, (3)
  1642. *
  1643. * a~[i,r] = a[i,r] - gamma[i] a[p,r], (4)
  1644. *
  1645. * L~[i] = L[i] - gamma[i] b, (5)
  1646. *
  1647. * U~[i] = U[i] - gamma[i] b. (6)
  1648. *
  1649. * RECOVERING BASIC SOLUTION
  1650. *
  1651. * The transformation of the primal system of the original problem:
  1652. *
  1653. * L <= A x <= U (7)
  1654. *
  1655. * is equivalent to multiplying from the left a transformation matrix F
  1656. * by components of this primal system, which in the transformed problem
  1657. * becomes the following:
  1658. *
  1659. * F L <= F A x <= F U ==> L~ <= A~x <= U~. (8)
  1660. *
  1661. * The matrix F has the following structure:
  1662. *
  1663. * ( 1 -gamma[1] )
  1664. * ( )
  1665. * ( 1 -gamma[2] )
  1666. * ( )
  1667. * ( ... ... )
  1668. * ( )
  1669. * F = ( 1 -gamma[p-1] ) (9)
  1670. * ( )
  1671. * ( 1 )
  1672. * ( )
  1673. * ( -gamma[p+1] 1 )
  1674. * ( )
  1675. * ( ... ... )
  1676. *
  1677. * where its column containing elements -gamma[i] corresponds to row p
  1678. * of the primal system.
  1679. *
  1680. * From (8) it follows that the dual system of the original problem:
  1681. *
  1682. * A'pi + lambda = c, (10)
  1683. *
  1684. * in the transformed problem becomes the following:
  1685. *
  1686. * A'F'inv(F')pi + lambda = c ==> (A~)'pi~ + lambda = c, (11)
  1687. *
  1688. * where:
  1689. *
  1690. * pi~ = inv(F')pi (12)
  1691. *
  1692. * is the vector of row multipliers in the transformed problem. Thus:
  1693. *
  1694. * pi = F'pi~. (13)
  1695. *
  1696. * Therefore, as it follows from (13), value of multiplier for row p in
  1697. * solution to the original problem can be computed as follows:
  1698. *
  1699. * pi[p] = pi~[p] - sum gamma[i] pi~[i], (14)
  1700. * i
  1701. *
  1702. * where pi~[i] = pi[i] is multiplier for row i (i != p).
  1703. *
  1704. * Note that the statuses of all rows and columns are not changed.
  1705. *
  1706. * RECOVERING INTERIOR-POINT SOLUTION
  1707. *
  1708. * Multiplier for row p in solution to the original problem is computed
  1709. * with formula (14).
  1710. *
  1711. * RECOVERING MIP SOLUTION
  1712. *
  1713. * None needed. */
  1714. struct eq_doublet
  1715. { /* row doubleton (equality constraint) */
  1716. int p;
  1717. /* row reference number */
  1718. double apq;
  1719. /* constraint coefficient a[p,q] */
  1720. NPPLFE *ptr;
  1721. /* list of non-zero coefficients a[i,q], i != p */
  1722. };
  1723. static int rcv_eq_doublet(NPP *npp, void *info);
  1724. NPPCOL *npp_eq_doublet(NPP *npp, NPPROW *p)
  1725. { /* process row doubleton (equality constraint) */
  1726. struct eq_doublet *info;
  1727. NPPROW *i;
  1728. NPPCOL *q, *r;
  1729. NPPAIJ *apq, *apr, *aiq, *air, *next;
  1730. NPPLFE *lfe;
  1731. double gamma;
  1732. /* the row must be doubleton equality constraint */
  1733. xassert(p->lb == p->ub);
  1734. xassert(p->ptr != NULL && p->ptr->r_next != NULL &&
  1735. p->ptr->r_next->r_next == NULL);
  1736. /* choose column to be eliminated */
  1737. { NPPAIJ *a1, *a2;
  1738. a1 = p->ptr, a2 = a1->r_next;
  1739. if (fabs(a2->val) < 0.001 * fabs(a1->val))
  1740. { /* only first column can be eliminated, because second one
  1741. has too small constraint coefficient */
  1742. apq = a1, apr = a2;
  1743. }
  1744. else if (fabs(a1->val) < 0.001 * fabs(a2->val))
  1745. { /* only second column can be eliminated, because first one
  1746. has too small constraint coefficient */
  1747. apq = a2, apr = a1;
  1748. }
  1749. else
  1750. { /* both columns are appropriate; choose that one which is
  1751. shorter to minimize fill-in */
  1752. if (npp_col_nnz(npp, a1->col) <= npp_col_nnz(npp, a2->col))
  1753. { /* first column is shorter */
  1754. apq = a1, apr = a2;
  1755. }
  1756. else
  1757. { /* second column is shorter */
  1758. apq = a2, apr = a1;
  1759. }
  1760. }
  1761. }
  1762. /* now columns q and r have been chosen */
  1763. q = apq->col, r = apr->col;
  1764. /* create transformation stack entry */
  1765. info = npp_push_tse(npp,
  1766. rcv_eq_doublet, sizeof(struct eq_doublet));
  1767. info->p = p->i;
  1768. info->apq = apq->val;
  1769. info->ptr = NULL;
  1770. /* transform each row i (i != p), where a[i,q] != 0, to eliminate
  1771. column q */
  1772. for (aiq = q->ptr; aiq != NULL; aiq = next)
  1773. { next = aiq->c_next;
  1774. if (aiq == apq) continue; /* skip row p */
  1775. i = aiq->row; /* row i to be transformed */
  1776. /* save constraint coefficient a[i,q] */
  1777. if (npp->sol != GLP_MIP)
  1778. { lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE));
  1779. lfe->ref = i->i;
  1780. lfe->val = aiq->val;
  1781. lfe->next = info->ptr;
  1782. info->ptr = lfe;
  1783. }
  1784. /* find coefficient a[i,r] in row i */
  1785. for (air = i->ptr; air != NULL; air = air->r_next)
  1786. if (air->col == r) break;
  1787. /* if a[i,r] does not exist, create a[i,r] = 0 */
  1788. if (air == NULL)
  1789. air = npp_add_aij(npp, i, r, 0.0);
  1790. /* compute gamma[i] = a[i,q] / a[p,q] */
  1791. gamma = aiq->val / apq->val;
  1792. /* (row i) := (row i) - gamma[i] * (row p); see (3)-(6) */
  1793. /* new a[i,q] is exact zero due to elimnation; remove it from
  1794. row i */
  1795. npp_del_aij(npp, aiq);
  1796. /* compute new a[i,r] */
  1797. air->val -= gamma * apr->val;
  1798. /* if new a[i,r] is close to zero due to numeric cancelation,
  1799. remove it from row i */
  1800. if (fabs(air->val) <= 1e-10)
  1801. npp_del_aij(npp, air);
  1802. /* compute new lower and upper bounds of row i */
  1803. if (i->lb == i->ub)
  1804. i->lb = i->ub = (i->lb - gamma * p->lb);
  1805. else
  1806. { if (i->lb != -DBL_MAX)
  1807. i->lb -= gamma * p->lb;
  1808. if (i->ub != +DBL_MAX)
  1809. i->ub -= gamma * p->lb;
  1810. }
  1811. }
  1812. return q;
  1813. }
  1814. static int rcv_eq_doublet(NPP *npp, void *_info)
  1815. { /* recover row doubleton (equality constraint) */
  1816. struct eq_doublet *info = _info;
  1817. NPPLFE *lfe;
  1818. double gamma, temp;
  1819. /* we assume that processing row p is followed by processing
  1820. column q as singleton of type "implied slack variable", in
  1821. which case row p must always be active equality constraint */
  1822. if (npp->sol == GLP_SOL)
  1823. { if (npp->r_stat[info->p] != GLP_NS)
  1824. { npp_error();
  1825. return 1;
  1826. }
  1827. }
  1828. if (npp->sol != GLP_MIP)
  1829. { /* compute value of multiplier for row p; see (14) */
  1830. temp = npp->r_pi[info->p];
  1831. for (lfe = info->ptr; lfe != NULL; lfe = lfe->next)
  1832. { gamma = lfe->val / info->apq; /* a[i,q] / a[p,q] */
  1833. temp -= gamma * npp->r_pi[lfe->ref];
  1834. }
  1835. npp->r_pi[info->p] = temp;
  1836. }
  1837. return 0;
  1838. }
  1839. /***********************************************************************
  1840. * NAME
  1841. *
  1842. * npp_forcing_row - process forcing row
  1843. *
  1844. * SYNOPSIS
  1845. *
  1846. * #include "glpnpp.h"
  1847. * int npp_forcing_row(NPP *npp, NPPROW *p, int at);
  1848. *
  1849. * DESCRIPTION
  1850. *
  1851. * The routine npp_forcing row processes row p of general format:
  1852. *
  1853. * L[p] <= sum a[p,j] x[j] <= U[p], (1)
  1854. * j
  1855. *
  1856. * l[j] <= x[j] <= u[j], (2)
  1857. *
  1858. * where L[p] <= U[p] and l[j] < u[j] for all a[p,j] != 0. It is also
  1859. * assumed that:
  1860. *
  1861. * 1) if at = 0 then |L[p] - U'[p]| <= eps, where U'[p] is implied
  1862. * row upper bound (see below), eps is an absolute tolerance for row
  1863. * value;
  1864. *
  1865. * 2) if at = 1 then |U[p] - L'[p]| <= eps, where L'[p] is implied
  1866. * row lower bound (see below).
  1867. *
  1868. * RETURNS
  1869. *
  1870. * 0 - success;
  1871. *
  1872. * 1 - cannot fix columns due to too small constraint coefficients.
  1873. *
  1874. * PROBLEM TRANSFORMATION
  1875. *
  1876. * Implied lower and upper bounds of row (1) are determined by bounds
  1877. * of corresponding columns (variables) as follows:
  1878. *
  1879. * L'[p] = inf sum a[p,j] x[j] =
  1880. * j
  1881. * (3)
  1882. * = sum a[p,j] l[j] + sum a[p,j] u[j],
  1883. * j in Jp j in Jn
  1884. *
  1885. * U'[p] = sup sum a[p,j] x[j] =
  1886. * (4)
  1887. * = sum a[p,j] u[j] + sum a[p,j] l[j],
  1888. * j in Jp j in Jn
  1889. *
  1890. * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5)
  1891. *
  1892. * If L[p] =~ U'[p] (at = 0), solution can be primal feasible only when
  1893. * all variables take their boundary values as defined by (4):
  1894. *
  1895. * ( u[j], if j in Jp
  1896. * x[j] = < (6)
  1897. * ( l[j], if j in Jn
  1898. *
  1899. * Similarly, if U[p] =~ L'[p] (at = 1), solution can be primal feasible
  1900. * only when all variables take their boundary values as defined by (3):
  1901. *
  1902. * ( l[j], if j in Jp
  1903. * x[j] = < (7)
  1904. * ( u[j], if j in Jn
  1905. *
  1906. * Condition (6) or (7) allows fixing all columns (variables x[j])
  1907. * in row (1) on their bounds and then removing them from the problem
  1908. * (see the routine npp_fixed_col). Due to this row p becomes redundant,
  1909. * so it can be replaced by equivalent free (unbounded) row and also
  1910. * removed from the problem (see the routine npp_free_row).
  1911. *
  1912. * 1. To apply this transformation row (1) should not have coefficients
  1913. * whose magnitude is too small, i.e. all a[p,j] should satisfy to
  1914. * the following condition:
  1915. *
  1916. * |a[p,j]| >= eps * max(1, |a[p,k]|), (8)
  1917. * k
  1918. * where eps is a relative tolerance for constraint coefficients.
  1919. * Otherwise, fixing columns may be numerically unreliable and may
  1920. * lead to wrong solution.
  1921. *
  1922. * 2. The routine fixes columns and remove bounds of row p, however,
  1923. * it does not remove the row and columns from the problem.
  1924. *
  1925. * RECOVERING BASIC SOLUTION
  1926. *
  1927. * In the transformed problem row p being inactive constraint is
  1928. * assigned status GLP_BS (as the result of transformation of free
  1929. * row), and all columns in this row are assigned status GLP_NS (as the
  1930. * result of transformation of fixed columns).
  1931. *
  1932. * Note that in the dual system of the transformed (as well as original)
  1933. * problem every column j in row p corresponds to the following row:
  1934. *
  1935. * sum a[i,j] pi[i] + a[p,j] pi[p] + lambda[j] = c[j], (9)
  1936. * i!=p
  1937. *
  1938. * from which it follows that:
  1939. *
  1940. * lambda[j] = c[j] - sum a[i,j] pi[i] - a[p,j] pi[p]. (10)
  1941. * i!=p
  1942. *
  1943. * In the transformed problem values of all multipliers pi[i] are known
  1944. * (including pi[i], whose value is zero, since row p is inactive).
  1945. * Thus, using formula (10) it is possible to compute values of
  1946. * multipliers lambda[j] for all columns in row p.
  1947. *
  1948. * Note also that in the original problem all columns in row p are
  1949. * bounded, not fixed. So status GLP_NS assigned to every such column
  1950. * must be changed to GLP_NL or GLP_NU depending on which bound the
  1951. * corresponding column has been fixed. This status change may lead to
  1952. * dual feasibility violation for solution of the original problem,
  1953. * because now column multipliers must satisfy to the following
  1954. * condition:
  1955. *
  1956. * ( >= 0, if status of column j is GLP_NL,
  1957. * lambda[j] < (11)
  1958. * ( <= 0, if status of column j is GLP_NU.
  1959. *
  1960. * If this condition holds, solution to the original problem is the
  1961. * same as to the transformed problem. Otherwise, we have to perform
  1962. * one degenerate pivoting step of the primal simplex method to obtain
  1963. * dual feasible (hence, optimal) solution to the original problem as
  1964. * follows. If, on problem transformation, row p was made active on its
  1965. * lower bound (case at = 0), we change its status to GLP_NL (or GLP_NS)
  1966. * and start increasing its multiplier pi[p]. Otherwise, if row p was
  1967. * made active on its upper bound (case at = 1), we change its status
  1968. * to GLP_NU (or GLP_NS) and start decreasing pi[p]. From (10) it
  1969. * follows that:
  1970. *
  1971. * delta lambda[j] = - a[p,j] * delta pi[p] = - a[p,j] pi[p]. (12)
  1972. *
  1973. * Simple analysis of formulae (3)-(5) shows that changing pi[p] in the
  1974. * specified direction causes increasing lambda[j] for every column j
  1975. * assigned status GLP_NL (delta lambda[j] > 0) and decreasing lambda[j]
  1976. * for every column j assigned status GLP_NU (delta lambda[j] < 0). It
  1977. * is understood that once the last lambda[q], which violates condition
  1978. * (11), has reached zero, multipliers lambda[j] for all columns get
  1979. * valid signs. Such column q can be determined as follows. Let d[j] be
  1980. * initial value of lambda[j] (i.e. reduced cost of column j) in the
  1981. * transformed problem computed with formula (10) when pi[p] = 0. Then
  1982. * lambda[j] = d[j] + delta lambda[j], and from (12) it follows that
  1983. * lambda[j] becomes zero if:
  1984. *
  1985. * delta lambda[j] = - a[p,j] pi[p] = - d[j] ==>
  1986. * (13)
  1987. * pi[p] = d[j] / a[p,j].
  1988. *
  1989. * Therefore, the last column q, for which lambda[q] becomes zero, can
  1990. * be determined from the following condition:
  1991. *
  1992. * |d[q] / a[p,q]| = max |pi[p]| = max |d[j] / a[p,j]|, (14)
  1993. * j in D j in D
  1994. *
  1995. * where D is a set of columns j whose, reduced costs d[j] have invalid
  1996. * signs, i.e. violate condition (11). (Thus, if D is empty, solution
  1997. * to the original problem is the same as solution to the transformed
  1998. * problem, and no correction is needed as was noticed above.) In
  1999. * solution to the original problem column q is assigned status GLP_BS,
  2000. * since it replaces column of auxiliary variable of row p (becoming
  2001. * active) in the basis, and multiplier for row p is assigned its new
  2002. * value, which is pi[p] = d[q] / a[p,q]. Note that due to primal
  2003. * degeneracy values of all columns having non-zero coefficients in row
  2004. * p remain unchanged.
  2005. *
  2006. * RECOVERING INTERIOR-POINT SOLUTION
  2007. *
  2008. * Value of multiplier pi[p] in solution to the original problem is
  2009. * corrected in the same way as for basic solution. Values of all
  2010. * columns having non-zero coefficients in row p remain unchanged.
  2011. *
  2012. * RECOVERING MIP SOLUTION
  2013. *
  2014. * None needed. */
  2015. struct forcing_col
  2016. { /* column fixed on its bound by forcing row */
  2017. int j;
  2018. /* column reference number */
  2019. char stat;
  2020. /* original column status:
  2021. GLP_NL - fixed on lower bound
  2022. GLP_NU - fixed on upper bound */
  2023. double a;
  2024. /* constraint coefficient a[p,j] */
  2025. double c;
  2026. /* objective coefficient c[j] */
  2027. NPPLFE *ptr;
  2028. /* list of non-zero coefficients a[i,j], i != p */
  2029. struct forcing_col *next;
  2030. /* pointer to another column fixed by forcing row */
  2031. };
  2032. struct forcing_row
  2033. { /* forcing row */
  2034. int p;
  2035. /* row reference number */
  2036. char stat;
  2037. /* status assigned to the row if it becomes active:
  2038. GLP_NS - active equality constraint
  2039. GLP_NL - inequality constraint with lower bound active
  2040. GLP_NU - inequality constraint with upper bound active */
  2041. struct forcing_col *ptr;
  2042. /* list of all columns having non-zero constraint coefficient
  2043. a[p,j] in the forcing row */
  2044. };
  2045. static int rcv_forcing_row(NPP *npp, void *info);
  2046. int npp_forcing_row(NPP *npp, NPPROW *p, int at)
  2047. { /* process forcing row */
  2048. struct forcing_row *info;
  2049. struct forcing_col *col = NULL;
  2050. NPPCOL *j;
  2051. NPPAIJ *apj, *aij;
  2052. NPPLFE *lfe;
  2053. double big;
  2054. xassert(at == 0 || at == 1);
  2055. /* determine maximal magnitude of the row coefficients */
  2056. big = 1.0;
  2057. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2058. if (big < fabs(apj->val)) big = fabs(apj->val);
  2059. /* if there are too small coefficients in the row, transformation
  2060. should not be applied */
  2061. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2062. if (fabs(apj->val) < 1e-7 * big) return 1;
  2063. /* create transformation stack entry */
  2064. info = npp_push_tse(npp,
  2065. rcv_forcing_row, sizeof(struct forcing_row));
  2066. info->p = p->i;
  2067. if (p->lb == p->ub)
  2068. { /* equality constraint */
  2069. info->stat = GLP_NS;
  2070. }
  2071. else if (at == 0)
  2072. { /* inequality constraint; case L[p] = U'[p] */
  2073. info->stat = GLP_NL;
  2074. xassert(p->lb != -DBL_MAX);
  2075. }
  2076. else /* at == 1 */
  2077. { /* inequality constraint; case U[p] = L'[p] */
  2078. info->stat = GLP_NU;
  2079. xassert(p->ub != +DBL_MAX);
  2080. }
  2081. info->ptr = NULL;
  2082. /* scan the forcing row, fix columns at corresponding bounds, and
  2083. save column information (the latter is not needed for MIP) */
  2084. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2085. { /* column j has non-zero coefficient in the forcing row */
  2086. j = apj->col;
  2087. /* it must be non-fixed */
  2088. xassert(j->lb < j->ub);
  2089. /* allocate stack entry to save column information */
  2090. if (npp->sol != GLP_MIP)
  2091. { col = dmp_get_atom(npp->stack, sizeof(struct forcing_col));
  2092. col->j = j->j;
  2093. col->stat = -1; /* will be set below */
  2094. col->a = apj->val;
  2095. col->c = j->coef;
  2096. col->ptr = NULL;
  2097. col->next = info->ptr;
  2098. info->ptr = col;
  2099. }
  2100. /* fix column j */
  2101. if (at == 0 && apj->val < 0.0 || at != 0 && apj->val > 0.0)
  2102. { /* at its lower bound */
  2103. if (npp->sol != GLP_MIP)
  2104. col->stat = GLP_NL;
  2105. xassert(j->lb != -DBL_MAX);
  2106. j->ub = j->lb;
  2107. }
  2108. else
  2109. { /* at its upper bound */
  2110. if (npp->sol != GLP_MIP)
  2111. col->stat = GLP_NU;
  2112. xassert(j->ub != +DBL_MAX);
  2113. j->lb = j->ub;
  2114. }
  2115. /* save column coefficients a[i,j], i != p */
  2116. if (npp->sol != GLP_MIP)
  2117. { for (aij = j->ptr; aij != NULL; aij = aij->c_next)
  2118. { if (aij == apj) continue; /* skip a[p,j] */
  2119. lfe = dmp_get_atom(npp->stack, sizeof(NPPLFE));
  2120. lfe->ref = aij->row->i;
  2121. lfe->val = aij->val;
  2122. lfe->next = col->ptr;
  2123. col->ptr = lfe;
  2124. }
  2125. }
  2126. }
  2127. /* make the row free (unbounded) */
  2128. p->lb = -DBL_MAX, p->ub = +DBL_MAX;
  2129. return 0;
  2130. }
  2131. static int rcv_forcing_row(NPP *npp, void *_info)
  2132. { /* recover forcing row */
  2133. struct forcing_row *info = _info;
  2134. struct forcing_col *col, *piv;
  2135. NPPLFE *lfe;
  2136. double d, big, temp;
  2137. if (npp->sol == GLP_MIP) goto done;
  2138. /* initially solution to the original problem is the same as
  2139. to the transformed problem, where row p is inactive constraint
  2140. with pi[p] = 0, and all columns are non-basic */
  2141. if (npp->sol == GLP_SOL)
  2142. { if (npp->r_stat[info->p] != GLP_BS)
  2143. { npp_error();
  2144. return 1;
  2145. }
  2146. for (col = info->ptr; col != NULL; col = col->next)
  2147. { if (npp->c_stat[col->j] != GLP_NS)
  2148. { npp_error();
  2149. return 1;
  2150. }
  2151. npp->c_stat[col->j] = col->stat; /* original status */
  2152. }
  2153. }
  2154. /* compute reduced costs d[j] for all columns with formula (10)
  2155. and store them in col.c instead objective coefficients */
  2156. for (col = info->ptr; col != NULL; col = col->next)
  2157. { d = col->c;
  2158. for (lfe = col->ptr; lfe != NULL; lfe = lfe->next)
  2159. d -= lfe->val * npp->r_pi[lfe->ref];
  2160. col->c = d;
  2161. }
  2162. /* consider columns j, whose multipliers lambda[j] has wrong
  2163. sign in solution to the transformed problem (where lambda[j] =
  2164. d[j]), and choose column q, whose multipler lambda[q] reaches
  2165. zero last on changing row multiplier pi[p]; see (14) */
  2166. piv = NULL, big = 0.0;
  2167. for (col = info->ptr; col != NULL; col = col->next)
  2168. { d = col->c; /* d[j] */
  2169. temp = fabs(d / col->a);
  2170. if (col->stat == GLP_NL)
  2171. { /* column j has active lower bound */
  2172. if (d < 0.0 && big < temp)
  2173. piv = col, big = temp;
  2174. }
  2175. else if (col->stat == GLP_NU)
  2176. { /* column j has active upper bound */
  2177. if (d > 0.0 && big < temp)
  2178. piv = col, big = temp;
  2179. }
  2180. else
  2181. { npp_error();
  2182. return 1;
  2183. }
  2184. }
  2185. /* if column q does not exist, no correction is needed */
  2186. if (piv != NULL)
  2187. { /* correct solution; row p becomes active constraint while
  2188. column q becomes basic */
  2189. if (npp->sol == GLP_SOL)
  2190. { npp->r_stat[info->p] = info->stat;
  2191. npp->c_stat[piv->j] = GLP_BS;
  2192. }
  2193. /* assign new value to row multiplier pi[p] = d[p] / a[p,q] */
  2194. npp->r_pi[info->p] = piv->c / piv->a;
  2195. }
  2196. done: return 0;
  2197. }
  2198. /***********************************************************************
  2199. * NAME
  2200. *
  2201. * npp_analyze_row - perform general row analysis
  2202. *
  2203. * SYNOPSIS
  2204. *
  2205. * #include "glpnpp.h"
  2206. * int npp_analyze_row(NPP *npp, NPPROW *p);
  2207. *
  2208. * DESCRIPTION
  2209. *
  2210. * The routine npp_analyze_row performs analysis of row p of general
  2211. * format:
  2212. *
  2213. * L[p] <= sum a[p,j] x[j] <= U[p], (1)
  2214. * j
  2215. *
  2216. * l[j] <= x[j] <= u[j], (2)
  2217. *
  2218. * where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0.
  2219. *
  2220. * RETURNS
  2221. *
  2222. * 0x?0 - row lower bound does not exist or is redundant;
  2223. *
  2224. * 0x?1 - row lower bound can be active;
  2225. *
  2226. * 0x?2 - row lower bound is a forcing bound;
  2227. *
  2228. * 0x0? - row upper bound does not exist or is redundant;
  2229. *
  2230. * 0x1? - row upper bound can be active;
  2231. *
  2232. * 0x2? - row upper bound is a forcing bound;
  2233. *
  2234. * 0x33 - row bounds are inconsistent with column bounds.
  2235. *
  2236. * ALGORITHM
  2237. *
  2238. * Analysis of row (1) is based on analysis of its implied lower and
  2239. * upper bounds, which are determined by bounds of corresponding columns
  2240. * (variables) as follows:
  2241. *
  2242. * L'[p] = inf sum a[p,j] x[j] =
  2243. * j
  2244. * (3)
  2245. * = sum a[p,j] l[j] + sum a[p,j] u[j],
  2246. * j in Jp j in Jn
  2247. *
  2248. * U'[p] = sup sum a[p,j] x[j] =
  2249. * (4)
  2250. * = sum a[p,j] u[j] + sum a[p,j] l[j],
  2251. * j in Jp j in Jn
  2252. *
  2253. * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5)
  2254. *
  2255. * (Note that bounds of all columns in row p are assumed to be correct,
  2256. * so L'[p] <= U'[p].)
  2257. *
  2258. * Analysis of row lower bound L[p] includes the following cases:
  2259. *
  2260. * 1) if L[p] > U'[p] + eps, where eps is an absolute tolerance for row
  2261. * value, row lower bound L[p] and implied row upper bound U'[p] are
  2262. * inconsistent, ergo, the problem has no primal feasible solution;
  2263. *
  2264. * 2) if U'[p] - eps <= L[p] <= U'[p] + eps, i.e. if L[p] =~ U'[p],
  2265. * the row is a forcing row on its lower bound (see description of
  2266. * the routine npp_forcing_row);
  2267. *
  2268. * 3) if L[p] > L'[p] + eps, row lower bound L[p] can be active (this
  2269. * conclusion does not account other rows in the problem);
  2270. *
  2271. * 4) if L[p] <= L'[p] + eps, row lower bound L[p] cannot be active, so
  2272. * it is redundant and can be removed (replaced by -oo).
  2273. *
  2274. * Analysis of row upper bound U[p] is performed in a similar way and
  2275. * includes the following cases:
  2276. *
  2277. * 1) if U[p] < L'[p] - eps, row upper bound U[p] and implied row lower
  2278. * bound L'[p] are inconsistent, ergo the problem has no primal
  2279. * feasible solution;
  2280. *
  2281. * 2) if L'[p] - eps <= U[p] <= L'[p] + eps, i.e. if U[p] =~ L'[p],
  2282. * the row is a forcing row on its upper bound (see description of
  2283. * the routine npp_forcing_row);
  2284. *
  2285. * 3) if U[p] < U'[p] - eps, row upper bound U[p] can be active (this
  2286. * conclusion does not account other rows in the problem);
  2287. *
  2288. * 4) if U[p] >= U'[p] - eps, row upper bound U[p] cannot be active, so
  2289. * it is redundant and can be removed (replaced by +oo). */
  2290. int npp_analyze_row(NPP *npp, NPPROW *p)
  2291. { /* perform general row analysis */
  2292. NPPAIJ *aij;
  2293. int ret = 0x00;
  2294. double l, u, eps;
  2295. xassert(npp == npp);
  2296. /* compute implied lower bound L'[p]; see (3) */
  2297. l = 0.0;
  2298. for (aij = p->ptr; aij != NULL; aij = aij->r_next)
  2299. { if (aij->val > 0.0)
  2300. { if (aij->col->lb == -DBL_MAX)
  2301. { l = -DBL_MAX;
  2302. break;
  2303. }
  2304. l += aij->val * aij->col->lb;
  2305. }
  2306. else /* aij->val < 0.0 */
  2307. { if (aij->col->ub == +DBL_MAX)
  2308. { l = -DBL_MAX;
  2309. break;
  2310. }
  2311. l += aij->val * aij->col->ub;
  2312. }
  2313. }
  2314. /* compute implied upper bound U'[p]; see (4) */
  2315. u = 0.0;
  2316. for (aij = p->ptr; aij != NULL; aij = aij->r_next)
  2317. { if (aij->val > 0.0)
  2318. { if (aij->col->ub == +DBL_MAX)
  2319. { u = +DBL_MAX;
  2320. break;
  2321. }
  2322. u += aij->val * aij->col->ub;
  2323. }
  2324. else /* aij->val < 0.0 */
  2325. { if (aij->col->lb == -DBL_MAX)
  2326. { u = +DBL_MAX;
  2327. break;
  2328. }
  2329. u += aij->val * aij->col->lb;
  2330. }
  2331. }
  2332. /* column bounds are assumed correct, so L'[p] <= U'[p] */
  2333. /* check if row lower bound is consistent */
  2334. if (p->lb != -DBL_MAX)
  2335. { eps = 1e-3 + 1e-6 * fabs(p->lb);
  2336. if (p->lb - eps > u)
  2337. { ret = 0x33;
  2338. goto done;
  2339. }
  2340. }
  2341. /* check if row upper bound is consistent */
  2342. if (p->ub != +DBL_MAX)
  2343. { eps = 1e-3 + 1e-6 * fabs(p->ub);
  2344. if (p->ub + eps < l)
  2345. { ret = 0x33;
  2346. goto done;
  2347. }
  2348. }
  2349. /* check if row lower bound can be active/forcing */
  2350. if (p->lb != -DBL_MAX)
  2351. { eps = 1e-9 + 1e-12 * fabs(p->lb);
  2352. if (p->lb - eps > l)
  2353. { if (p->lb + eps <= u)
  2354. ret |= 0x01;
  2355. else
  2356. ret |= 0x02;
  2357. }
  2358. }
  2359. /* check if row upper bound can be active/forcing */
  2360. if (p->ub != +DBL_MAX)
  2361. { eps = 1e-9 + 1e-12 * fabs(p->ub);
  2362. if (p->ub + eps < u)
  2363. { /* check if the upper bound is forcing */
  2364. if (p->ub - eps >= l)
  2365. ret |= 0x10;
  2366. else
  2367. ret |= 0x20;
  2368. }
  2369. }
  2370. done: return ret;
  2371. }
  2372. /***********************************************************************
  2373. * NAME
  2374. *
  2375. * npp_inactive_bound - remove row lower/upper inactive bound
  2376. *
  2377. * SYNOPSIS
  2378. *
  2379. * #include "glpnpp.h"
  2380. * void npp_inactive_bound(NPP *npp, NPPROW *p, int which);
  2381. *
  2382. * DESCRIPTION
  2383. *
  2384. * The routine npp_inactive_bound removes lower (if which = 0) or upper
  2385. * (if which = 1) bound of row p:
  2386. *
  2387. * L[p] <= sum a[p,j] x[j] <= U[p],
  2388. *
  2389. * which (bound) is assumed to be redundant.
  2390. *
  2391. * PROBLEM TRANSFORMATION
  2392. *
  2393. * If which = 0, current lower bound L[p] of row p is assigned -oo.
  2394. * If which = 1, current upper bound U[p] of row p is assigned +oo.
  2395. *
  2396. * RECOVERING BASIC SOLUTION
  2397. *
  2398. * If in solution to the transformed problem row p is inactive
  2399. * constraint (GLP_BS), its status is not changed in solution to the
  2400. * original problem. Otherwise, status of row p in solution to the
  2401. * original problem is defined by its type before transformation and
  2402. * its status in solution to the transformed problem as follows:
  2403. *
  2404. * +---------------------+-------+---------------+---------------+
  2405. * | Row | Flag | Row status in | Row status in |
  2406. * | type | which | transfmd soln | original soln |
  2407. * +---------------------+-------+---------------+---------------+
  2408. * | sum >= L[p] | 0 | GLP_NF | GLP_NL |
  2409. * | sum <= U[p] | 1 | GLP_NF | GLP_NU |
  2410. * | L[p] <= sum <= U[p] | 0 | GLP_NU | GLP_NU |
  2411. * | L[p] <= sum <= U[p] | 1 | GLP_NL | GLP_NL |
  2412. * | sum = L[p] = U[p] | 0 | GLP_NU | GLP_NS |
  2413. * | sum = L[p] = U[p] | 1 | GLP_NL | GLP_NS |
  2414. * +---------------------+-------+---------------+---------------+
  2415. *
  2416. * RECOVERING INTERIOR-POINT SOLUTION
  2417. *
  2418. * None needed.
  2419. *
  2420. * RECOVERING MIP SOLUTION
  2421. *
  2422. * None needed. */
  2423. struct inactive_bound
  2424. { /* row inactive bound */
  2425. int p;
  2426. /* row reference number */
  2427. char stat;
  2428. /* row status (if active constraint) */
  2429. };
  2430. static int rcv_inactive_bound(NPP *npp, void *info);
  2431. void npp_inactive_bound(NPP *npp, NPPROW *p, int which)
  2432. { /* remove row lower/upper inactive bound */
  2433. struct inactive_bound *info;
  2434. if (npp->sol == GLP_SOL)
  2435. { /* create transformation stack entry */
  2436. info = npp_push_tse(npp,
  2437. rcv_inactive_bound, sizeof(struct inactive_bound));
  2438. info->p = p->i;
  2439. if (p->ub == +DBL_MAX)
  2440. info->stat = GLP_NL;
  2441. else if (p->lb == -DBL_MAX)
  2442. info->stat = GLP_NU;
  2443. else if (p->lb != p->ub)
  2444. info->stat = (char)(which == 0 ? GLP_NU : GLP_NL);
  2445. else
  2446. info->stat = GLP_NS;
  2447. }
  2448. /* remove row inactive bound */
  2449. if (which == 0)
  2450. { xassert(p->lb != -DBL_MAX);
  2451. p->lb = -DBL_MAX;
  2452. }
  2453. else if (which == 1)
  2454. { xassert(p->ub != +DBL_MAX);
  2455. p->ub = +DBL_MAX;
  2456. }
  2457. else
  2458. xassert(which != which);
  2459. return;
  2460. }
  2461. static int rcv_inactive_bound(NPP *npp, void *_info)
  2462. { /* recover row status */
  2463. struct inactive_bound *info = _info;
  2464. if (npp->sol != GLP_SOL)
  2465. { npp_error();
  2466. return 1;
  2467. }
  2468. if (npp->r_stat[info->p] == GLP_BS)
  2469. npp->r_stat[info->p] = GLP_BS;
  2470. else
  2471. npp->r_stat[info->p] = info->stat;
  2472. return 0;
  2473. }
  2474. /***********************************************************************
  2475. * NAME
  2476. *
  2477. * npp_implied_bounds - determine implied column bounds
  2478. *
  2479. * SYNOPSIS
  2480. *
  2481. * #include "glpnpp.h"
  2482. * void npp_implied_bounds(NPP *npp, NPPROW *p);
  2483. *
  2484. * DESCRIPTION
  2485. *
  2486. * The routine npp_implied_bounds inspects general row (constraint) p:
  2487. *
  2488. * L[p] <= sum a[p,j] x[j] <= U[p], (1)
  2489. *
  2490. * l[j] <= x[j] <= u[j], (2)
  2491. *
  2492. * where L[p] <= U[p] and l[j] <= u[j] for all a[p,j] != 0, to compute
  2493. * implied bounds of columns (variables x[j]) in this row.
  2494. *
  2495. * The routine stores implied column bounds l'[j] and u'[j] in column
  2496. * descriptors (NPPCOL); it does not change current column bounds l[j]
  2497. * and u[j]. (Implied column bounds can be then used to strengthen the
  2498. * current column bounds; see the routines npp_implied_lower and
  2499. * npp_implied_upper).
  2500. *
  2501. * ALGORITHM
  2502. *
  2503. * Current column bounds (2) define implied lower and upper bounds of
  2504. * row (1) as follows:
  2505. *
  2506. * L'[p] = inf sum a[p,j] x[j] =
  2507. * j
  2508. * (3)
  2509. * = sum a[p,j] l[j] + sum a[p,j] u[j],
  2510. * j in Jp j in Jn
  2511. *
  2512. * U'[p] = sup sum a[p,j] x[j] =
  2513. * (4)
  2514. * = sum a[p,j] u[j] + sum a[p,j] l[j],
  2515. * j in Jp j in Jn
  2516. *
  2517. * Jp = {j: a[p,j] > 0}, Jn = {j: a[p,j] < 0}. (5)
  2518. *
  2519. * (Note that bounds of all columns in row p are assumed to be correct,
  2520. * so L'[p] <= U'[p].)
  2521. *
  2522. * If L[p] > L'[p] and/or U[p] < U'[p], the lower and/or upper bound of
  2523. * row (1) can be active, in which case such row defines implied bounds
  2524. * of its variables.
  2525. *
  2526. * Let x[k] be some variable having in row (1) coefficient a[p,k] != 0.
  2527. * Consider a case when row lower bound can be active (L[p] > L'[p]):
  2528. *
  2529. * sum a[p,j] x[j] >= L[p] ==>
  2530. * j
  2531. *
  2532. * sum a[p,j] x[j] + a[p,k] x[k] >= L[p] ==>
  2533. * j!=k
  2534. * (6)
  2535. * a[p,k] x[k] >= L[p] - sum a[p,j] x[j] ==>
  2536. * j!=k
  2537. *
  2538. * a[p,k] x[k] >= L[p,k],
  2539. *
  2540. * where
  2541. *
  2542. * L[p,k] = inf(L[p] - sum a[p,j] x[j]) =
  2543. * j!=k
  2544. *
  2545. * = L[p] - sup sum a[p,j] x[j] = (7)
  2546. * j!=k
  2547. *
  2548. * = L[p] - sum a[p,j] u[j] - sum a[p,j] l[j].
  2549. * j in Jp\{k} j in Jn\{k}
  2550. *
  2551. * Thus:
  2552. *
  2553. * x[k] >= l'[k] = L[p,k] / a[p,k], if a[p,k] > 0, (8)
  2554. *
  2555. * x[k] <= u'[k] = L[p,k] / a[p,k], if a[p,k] < 0. (9)
  2556. *
  2557. * where l'[k] and u'[k] are implied lower and upper bounds of variable
  2558. * x[k], resp.
  2559. *
  2560. * Now consider a similar case when row upper bound can be active
  2561. * (U[p] < U'[p]):
  2562. *
  2563. * sum a[p,j] x[j] <= U[p] ==>
  2564. * j
  2565. *
  2566. * sum a[p,j] x[j] + a[p,k] x[k] <= U[p] ==>
  2567. * j!=k
  2568. * (10)
  2569. * a[p,k] x[k] <= U[p] - sum a[p,j] x[j] ==>
  2570. * j!=k
  2571. *
  2572. * a[p,k] x[k] <= U[p,k],
  2573. *
  2574. * where:
  2575. *
  2576. * U[p,k] = sup(U[p] - sum a[p,j] x[j]) =
  2577. * j!=k
  2578. *
  2579. * = U[p] - inf sum a[p,j] x[j] = (11)
  2580. * j!=k
  2581. *
  2582. * = U[p] - sum a[p,j] l[j] - sum a[p,j] u[j].
  2583. * j in Jp\{k} j in Jn\{k}
  2584. *
  2585. * Thus:
  2586. *
  2587. * x[k] <= u'[k] = U[p,k] / a[p,k], if a[p,k] > 0, (12)
  2588. *
  2589. * x[k] >= l'[k] = U[p,k] / a[p,k], if a[p,k] < 0. (13)
  2590. *
  2591. * Note that in formulae (8), (9), (12), and (13) coefficient a[p,k]
  2592. * must not be too small in magnitude relatively to other non-zero
  2593. * coefficients in row (1), i.e. the following condition must hold:
  2594. *
  2595. * |a[p,k]| >= eps * max(1, |a[p,j]|), (14)
  2596. * j
  2597. *
  2598. * where eps is a relative tolerance for constraint coefficients.
  2599. * Otherwise the implied column bounds can be numerical inreliable. For
  2600. * example, using formula (8) for the following inequality constraint:
  2601. *
  2602. * 1e-12 x1 - x2 - x3 >= 0,
  2603. *
  2604. * where x1 >= -1, x2, x3, >= 0, may lead to numerically unreliable
  2605. * conclusion that x1 >= 0.
  2606. *
  2607. * Using formulae (8), (9), (12), and (13) to compute implied bounds
  2608. * for one variable requires |J| operations, where J = {j: a[p,j] != 0},
  2609. * because this needs computing L[p,k] and U[p,k]. Thus, computing
  2610. * implied bounds for all variables in row (1) would require |J|^2
  2611. * operations, that is not a good technique. However, the total number
  2612. * of operations can be reduced to |J| as follows.
  2613. *
  2614. * Let a[p,k] > 0. Then from (7) and (11) we have:
  2615. *
  2616. * L[p,k] = L[p] - (U'[p] - a[p,k] u[k]) =
  2617. *
  2618. * = L[p] - U'[p] + a[p,k] u[k],
  2619. *
  2620. * U[p,k] = U[p] - (L'[p] - a[p,k] l[k]) =
  2621. *
  2622. * = U[p] - L'[p] + a[p,k] l[k],
  2623. *
  2624. * where L'[p] and U'[p] are implied row lower and upper bounds defined
  2625. * by formulae (3) and (4). Substituting these expressions into (8) and
  2626. * (12) gives:
  2627. *
  2628. * l'[k] = L[p,k] / a[p,k] = u[k] + (L[p] - U'[p]) / a[p,k], (15)
  2629. *
  2630. * u'[k] = U[p,k] / a[p,k] = l[k] + (U[p] - L'[p]) / a[p,k]. (16)
  2631. *
  2632. * Similarly, if a[p,k] < 0, according to (7) and (11) we have:
  2633. *
  2634. * L[p,k] = L[p] - (U'[p] - a[p,k] l[k]) =
  2635. *
  2636. * = L[p] - U'[p] + a[p,k] l[k],
  2637. *
  2638. * U[p,k] = U[p] - (L'[p] - a[p,k] u[k]) =
  2639. *
  2640. * = U[p] - L'[p] + a[p,k] u[k],
  2641. *
  2642. * and substituting these expressions into (8) and (12) gives:
  2643. *
  2644. * l'[k] = U[p,k] / a[p,k] = u[k] + (U[p] - L'[p]) / a[p,k], (17)
  2645. *
  2646. * u'[k] = L[p,k] / a[p,k] = l[k] + (L[p] - U'[p]) / a[p,k]. (18)
  2647. *
  2648. * Note that formulae (15)-(18) can be used only if L'[p] and U'[p]
  2649. * exist. However, if for some variable x[j] it happens that l[j] = -oo
  2650. * and/or u[j] = +oo, values of L'[p] (if a[p,j] > 0) and/or U'[p] (if
  2651. * a[p,j] < 0) are undefined. Consider, therefore, the most general
  2652. * situation, when some column bounds (2) may not exist.
  2653. *
  2654. * Let:
  2655. *
  2656. * J' = {j : (a[p,j] > 0 and l[j] = -oo) or
  2657. * (19)
  2658. * (a[p,j] < 0 and u[j] = +oo)}.
  2659. *
  2660. * Then (assuming that row upper bound U[p] can be active) the following
  2661. * three cases are possible:
  2662. *
  2663. * 1) |J'| = 0. In this case L'[p] exists, thus, for all variables x[j]
  2664. * in row (1) we can use formulae (16) and (17);
  2665. *
  2666. * 2) J' = {k}. In this case L'[p] = -oo, however, U[p,k] (11) exists,
  2667. * so for variable x[k] we can use formulae (12) and (13). Note that
  2668. * for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] < 0)
  2669. * or u'[j] = +oo (if a[p,j] > 0);
  2670. *
  2671. * 3) |J'| > 1. In this case for all variables x[j] in row [1] we have
  2672. * l'[j] = -oo (if a[p,j] < 0) or u'[j] = +oo (if a[p,j] > 0).
  2673. *
  2674. * Similarly, let:
  2675. *
  2676. * J'' = {j : (a[p,j] > 0 and u[j] = +oo) or
  2677. * (20)
  2678. * (a[p,j] < 0 and l[j] = -oo)}.
  2679. *
  2680. * Then (assuming that row lower bound L[p] can be active) the following
  2681. * three cases are possible:
  2682. *
  2683. * 1) |J''| = 0. In this case U'[p] exists, thus, for all variables x[j]
  2684. * in row (1) we can use formulae (15) and (18);
  2685. *
  2686. * 2) J'' = {k}. In this case U'[p] = +oo, however, L[p,k] (7) exists,
  2687. * so for variable x[k] we can use formulae (8) and (9). Note that
  2688. * for all other variables x[j] (j != k) l'[j] = -oo (if a[p,j] > 0)
  2689. * or u'[j] = +oo (if a[p,j] < 0);
  2690. *
  2691. * 3) |J''| > 1. In this case for all variables x[j] in row (1) we have
  2692. * l'[j] = -oo (if a[p,j] > 0) or u'[j] = +oo (if a[p,j] < 0). */
  2693. void npp_implied_bounds(NPP *npp, NPPROW *p)
  2694. { NPPAIJ *apj, *apk;
  2695. double big, eps, temp;
  2696. xassert(npp == npp);
  2697. /* initialize implied bounds for all variables and determine
  2698. maximal magnitude of row coefficients a[p,j] */
  2699. big = 1.0;
  2700. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2701. { apj->col->ll.ll = -DBL_MAX, apj->col->uu.uu = +DBL_MAX;
  2702. if (big < fabs(apj->val)) big = fabs(apj->val);
  2703. }
  2704. eps = 1e-6 * big;
  2705. /* process row lower bound (assuming that it can be active) */
  2706. if (p->lb != -DBL_MAX)
  2707. { apk = NULL;
  2708. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2709. { if (apj->val > 0.0 && apj->col->ub == +DBL_MAX ||
  2710. apj->val < 0.0 && apj->col->lb == -DBL_MAX)
  2711. { if (apk == NULL)
  2712. apk = apj;
  2713. else
  2714. goto skip1;
  2715. }
  2716. }
  2717. /* if a[p,k] = NULL then |J'| = 0 else J' = { k } */
  2718. temp = p->lb;
  2719. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2720. { if (apj == apk)
  2721. /* skip a[p,k] */;
  2722. else if (apj->val > 0.0)
  2723. temp -= apj->val * apj->col->ub;
  2724. else /* apj->val < 0.0 */
  2725. temp -= apj->val * apj->col->lb;
  2726. }
  2727. /* compute column implied bounds */
  2728. if (apk == NULL)
  2729. { /* temp = L[p] - U'[p] */
  2730. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2731. { if (apj->val >= +eps)
  2732. { /* l'[j] := u[j] + (L[p] - U'[p]) / a[p,j] */
  2733. apj->col->ll.ll = apj->col->ub + temp / apj->val;
  2734. }
  2735. else if (apj->val <= -eps)
  2736. { /* u'[j] := l[j] + (L[p] - U'[p]) / a[p,j] */
  2737. apj->col->uu.uu = apj->col->lb + temp / apj->val;
  2738. }
  2739. }
  2740. }
  2741. else
  2742. { /* temp = L[p,k] */
  2743. if (apk->val >= +eps)
  2744. { /* l'[k] := L[p,k] / a[p,k] */
  2745. apk->col->ll.ll = temp / apk->val;
  2746. }
  2747. else if (apk->val <= -eps)
  2748. { /* u'[k] := L[p,k] / a[p,k] */
  2749. apk->col->uu.uu = temp / apk->val;
  2750. }
  2751. }
  2752. skip1: ;
  2753. }
  2754. /* process row upper bound (assuming that it can be active) */
  2755. if (p->ub != +DBL_MAX)
  2756. { apk = NULL;
  2757. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2758. { if (apj->val > 0.0 && apj->col->lb == -DBL_MAX ||
  2759. apj->val < 0.0 && apj->col->ub == +DBL_MAX)
  2760. { if (apk == NULL)
  2761. apk = apj;
  2762. else
  2763. goto skip2;
  2764. }
  2765. }
  2766. /* if a[p,k] = NULL then |J''| = 0 else J'' = { k } */
  2767. temp = p->ub;
  2768. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2769. { if (apj == apk)
  2770. /* skip a[p,k] */;
  2771. else if (apj->val > 0.0)
  2772. temp -= apj->val * apj->col->lb;
  2773. else /* apj->val < 0.0 */
  2774. temp -= apj->val * apj->col->ub;
  2775. }
  2776. /* compute column implied bounds */
  2777. if (apk == NULL)
  2778. { /* temp = U[p] - L'[p] */
  2779. for (apj = p->ptr; apj != NULL; apj = apj->r_next)
  2780. { if (apj->val >= +eps)
  2781. { /* u'[j] := l[j] + (U[p] - L'[p]) / a[p,j] */
  2782. apj->col->uu.uu = apj->col->lb + temp / apj->val;
  2783. }
  2784. else if (apj->val <= -eps)
  2785. { /* l'[j] := u[j] + (U[p] - L'[p]) / a[p,j] */
  2786. apj->col->ll.ll = apj->col->ub + temp / apj->val;
  2787. }
  2788. }
  2789. }
  2790. else
  2791. { /* temp = U[p,k] */
  2792. if (apk->val >= +eps)
  2793. { /* u'[k] := U[p,k] / a[p,k] */
  2794. apk->col->uu.uu = temp / apk->val;
  2795. }
  2796. else if (apk->val <= -eps)
  2797. { /* l'[k] := U[p,k] / a[p,k] */
  2798. apk->col->ll.ll = temp / apk->val;
  2799. }
  2800. }
  2801. skip2: ;
  2802. }
  2803. return;
  2804. }
  2805. /* eof */