00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024 static int TRACE = 0;
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039 #include "econfig.h"
00040 #include "dbl_priority.h"
00041 #include "dbl_sortrus.h"
00042 #include "dbl_iqsutil.h"
00043 #include "dbl_lpdata.h"
00044 #include "dbl_lpdefs.h"
00045 #include "dbl_simplex.h"
00046 #include "dbl_binary.h"
00047 #include "dbl_price.h"
00048 #include "dbl_lib.h"
00049 #include "dbl_qstruct.h"
00050 #include "dbl_qsopt.h"
00051 #ifdef USEDMALLOC
00052 #include "dmalloc.h"
00053 #endif
00054
00055
00056 #define dbl_ILL_INTTOL dbl_PFEAS_TOLER
00057
00058 #define dbl_STRONG_PIVOTS (50)
00059 #define dbl_STRONG_CANDIDATES (10)
00060
00061 #define dbl_ILL_BRANCH_STRONG_WEIGHT (10)
00062 #define dbl_ILL_BRANCH_STRONG_VAL(v0,v1) \
00063 (((v0) < (v1) ? (dbl_ILL_BRANCH_STRONG_WEIGHT * (v0) + (v1)) \
00064 : (dbl_ILL_BRANCH_STRONG_WEIGHT * (v1) + (v0))) \
00065 / (dbl_ILL_BRANCH_STRONG_WEIGHT + 1.0))
00066
00067 #define dbl_ILL_BRANCH_PENALTY_WEIGHT (2)
00068 #define dbl_ILL_BRANCH_PENALTY_VAL(v0,v1,f) \
00069 (((v0)*(f) < (v1)*(1.0-(f)) ? \
00070 (dbl_ILL_BRANCH_PENALTY_WEIGHT * (v0)*(f) + (v1)*(1.0-(f))) \
00071 : (dbl_ILL_BRANCH_PENALTY_WEIGHT * (v1)*(1.0-(f)) + (v0)*(f))) \
00072 / (dbl_ILL_BRANCH_PENALTY_WEIGHT + 1.0))
00073
00074
00075
00076 #define dbl_FIRSTBRANCH 1
00077 #define dbl_MIDDLEBRANCH 2
00078 #define dbl_STRONGBRANCH 3
00079 #define dbl_PENALTYBRANCH 4
00080
00081
00082 typedef struct dbl_bbnode
00083 {
00084 struct dbl_bbnode *next;
00085 struct dbl_bbnode *prev;
00086 int id;
00087 int depth;
00088 int handle;
00089 double bound;
00090 char *cstat;
00091 char *rstat;
00092 double *rownorms;
00093 int rownorms_size;
00094 int bound_cnt;
00095 int *bound_indx;
00096 char *lu;
00097 double *bounds;
00098 int bounds_size;
00099 }
00100 dbl_bbnode;
00101
00102 typedef struct dbl_mipinfo
00103 {
00104 int branching_rule;
00105 int watch;
00106 int depth;
00107 int totalnodes;
00108 int activenodes;
00109 int totalpivots;
00110 int lastpivots;
00111 int objsense;
00112 double objectivebound;
00113 double value;
00114 double *downpen;
00115 double *uppen;
00116 double *x;
00117 double *bestx;
00118 double *orig_lower;
00119 double *orig_upper;
00120 double *lower;
00121 double *upper;
00122 int nstruct;
00123 dbl_lpinfo *lp;
00124 dbl_price_info *pinf;
00125 dbl_bbnode head_bbnode;
00126 dbl_ILLpriority *que;
00127 ILLptrworld ptrworld;
00128 }
00129 dbl_mipinfo;
00130
00131
00132 ILL_PTRWORLD_ROUTINES (dbl_bbnode, bbnodealloc, bbnode_bulkalloc, bbnodefree)
00133 ILL_PTRWORLD_LISTFREE_ROUTINE (dbl_bbnode, bbnode_listfree, bbnodefree)
00134 ILL_PTRWORLD_LEAKS_ROUTINE (dbl_bbnode, bbnode_check_leaks, depth, int)
00135 static void dbl_cleanup_mip ( dbl_mipinfo * minf),
00136 dbl_choose_initial_price ( dbl_price_info * pinf),
00137 dbl_best_bbnode ( dbl_mipinfo * minf, dbl_bbnode ** best),
00138 dbl_put_bbnode ( dbl_mipinfo * minf, dbl_bbnode * b),
00139 dbl_remove_bbnode ( dbl_bbnode * b),
00140 dbl_find_first_branch ( dbl_lpinfo * lp, double * x, int *bvar),
00141 dbl_find_middle_branch ( dbl_lpinfo * lp, double * x, int *bvar),
00142 dbl_check_integral ( dbl_lpinfo * lp, double * x, int *yesno),
00143 dbl_copy_x ( int nstruct, double * from_x, double * to_x),
00144 dbl_init_mipinfo ( dbl_mipinfo * minf),
00145 dbl_free_mipinfo ( dbl_mipinfo * minf),
00146 dbl_init_bbnode ( dbl_bbnode * b),
00147 dbl_free_bbnode ( dbl_bbnode * b);
00148
00149 static int dbl_startup_mip ( dbl_mipinfo * minf, dbl_lpinfo * lp, dbl_price_info * pinf,
00150 double * lpval, itcnt_t*itcnt),
00151 dbl_run_bfs ( dbl_mipinfo * minf, itcnt_t*itcnt),
00152 dbl_process_bfs_bbnode ( dbl_mipinfo * minf, dbl_bbnode * b, itcnt_t*itcnt),
00153 dbl_child_work ( dbl_mipinfo * minf, dbl_bbnode * active, int bvar, int bdir,
00154 double * cval, int *cp, itcnt_t*itcnt),
00155 dbl_fix_variables ( dbl_lpinfo * lp, double * bestval, dbl_bbnode * b,
00156 double * wupper, double * wlower, int *hit),
00157 dbl_find_branch ( dbl_mipinfo * minf, double * x, double * lpval,
00158 int *bvar, itcnt_t*itcnt),
00159 dbl_find_penalty_branch ( dbl_lpinfo * lp, dbl_price_info * pinf, double * x,
00160 double * downpen, double * uppen, double * lpval, int *bvar,
00161 itcnt_t*itcnt),
00162 dbl_find_strong_branch ( dbl_lpinfo * lp, dbl_price_info * pinf, double * x,
00163 int *bvar, itcnt_t*itcnt),
00164 dbl_plunge ( dbl_mipinfo * minf, itcnt_t*itcnt),
00165 dbl_plunge_work ( dbl_mipinfo * minf, int depth, itcnt_t*itcnt),
00166 dbl_round_variables ( dbl_mipinfo * minf, int *count, double * tol);
00167
00168 static void dbl_choose_initial_price ( dbl_price_info * pinf)
00169 {
00170 pinf->pI_price = QS_PRICE_PSTEEP;
00171 pinf->pII_price = QS_PRICE_PSTEEP;
00172 pinf->dI_price = QS_PRICE_DSTEEP;
00173 pinf->dII_price = QS_PRICE_DSTEEP;
00174 }
00175
00176 int dbl_ILLmip_bfs (
00177 dbl_lpinfo * lp,
00178 double * val,
00179 double * x,
00180 itcnt_t*itcnt)
00181 {
00182 int tval, rval = 0;
00183 dbl_price_info pinf;
00184 dbl_mipinfo minf;
00185 dbl_bbnode *b;
00186 double lpval;
00187 double szeit = ILLutil_zeit ();
00188
00189 dbl_EGlpNumInitVar (lpval);
00190 dbl_EGlpNumInitVar (pinf.htrigger);
00191
00192 dbl_ILLprice_init_pricing_info (&pinf);
00193 dbl_init_mipinfo (&minf);
00194
00195 if (!lp)
00196 {
00197 fprintf (stderr, "dbl_ILLmip_bfs called without an LP\n");
00198 rval = 1;
00199 goto CLEANUP;
00200 }
00201
00202 rval = dbl_startup_mip (&minf, lp, &pinf, &lpval, itcnt);
00203 ILL_CLEANUP_IF (rval);
00204
00205 ILL_SAFE_MALLOC (minf.que, 1, dbl_ILLpriority);
00206 rval = dbl_ILLutil_priority_init (minf.que, lp->O->nstruct + 1);
00207 ILL_CLEANUP_IF (rval);
00208
00209 b = bbnodealloc (&minf.ptrworld);
00210 dbl_init_bbnode (b);
00211 b->depth = 0;
00212 b->id = minf.totalnodes++;
00213 dbl_EGlpNumCopy (b->bound, lpval);
00214 ILL_SAFE_MALLOC (b->cstat, lp->O->nstruct, char);
00215 ILL_SAFE_MALLOC (b->rstat, lp->nrows, char);
00216
00217 rval = dbl_ILLlib_getbasis (lp, b->cstat, b->rstat);
00218 ILL_CLEANUP_IF (rval);
00219
00220 if (pinf.dII_price == QS_PRICE_DSTEEP)
00221 {
00222 b->rownorms = dbl_EGlpNumAllocArray (lp->nrows);
00223 tval = dbl_ILLlib_getrownorms (lp, &pinf, b->rownorms);
00224 if (tval)
00225 {
00226 printf ("Row norms not available\n");
00227 fflush (stdout);
00228 dbl_EGlpNumFreeArray (b->rownorms);
00229 }
00230 }
00231
00232 rval = dbl_ILLutil_priority_insert (minf.que, (void *) b, &lpval, &(b->handle));
00233 ILL_CLEANUP_IF (rval);
00234
00235 b->prev = &(minf.head_bbnode);
00236 b->next = 0;
00237 minf.head_bbnode.next = b;
00238 minf.activenodes++;
00239
00240 minf.branching_rule = dbl_PENALTYBRANCH;
00241
00242 rval = dbl_run_bfs (&minf, itcnt);
00243 ILL_CLEANUP_IF (rval);
00244
00245 printf ("Total Number of Nodes: %d\n", minf.totalnodes);
00246 printf ("Total Number of Pivots: %d\n", minf.totalpivots);
00247 printf ("BFS MIP Runing Time: %.2f seconds\n", ILLutil_zeit () - szeit);
00248 fflush (stdout);
00249
00250 dbl_EGlpNumCopy (*val, minf.value);
00251 if (minf.objsense == dbl_ILL_MAX)
00252 dbl_EGlpNumSign (*val);
00253
00254 if (x && dbl_EGlpNumIsNeqq (minf.value, dbl_ILL_MAXDOUBLE))
00255 {
00256 dbl_copy_x (lp->O->nstruct, minf.bestx, x);
00257 }
00258
00259 CLEANUP:
00260
00261 if (minf.que)
00262 {
00263 dbl_ILLutil_priority_free (minf.que);
00264 ILL_IFFREE (minf.que, dbl_ILLpriority);
00265 }
00266 dbl_cleanup_mip (&minf);
00267 dbl_free_mipinfo (&minf);
00268 dbl_ILLprice_free_pricing_info (&pinf);
00269 dbl_EGlpNumClearVar (lpval);
00270 dbl_EGlpNumClearVar (pinf.htrigger);
00271 ILL_RETURN (rval, "dbl_ILLmip_bfs");
00272 }
00273
00274 static int dbl_startup_mip (
00275 dbl_mipinfo * minf,
00276 dbl_lpinfo * lp,
00277 dbl_price_info * pinf,
00278 double * lpval,
00279 itcnt_t*itcnt)
00280 {
00281 int rval = 0;
00282 int i, col, status, intcount = 0;
00283 double val;
00284 dbl_ILLlpdata *qlp;
00285
00286 dbl_EGlpNumInitVar (val);
00287
00288 dbl_choose_initial_price (pinf);
00289
00290 qlp = lp->O;
00291
00292 rval = dbl_ILLlib_optimize (lp, 0, pinf, DUAL_SIMPLEX, &status, 0, itcnt);
00293 ILL_CLEANUP_IF (rval);
00294
00295 minf->totalpivots += dbl_ILLlib_iter (lp);
00296
00297 rval = dbl_ILLlib_objval (lp, 0, &val);
00298 ILL_CLEANUP_IF (rval);
00299
00300 printf ("LP Value: %.6f\n", dbl_EGlpNumToLf (val));
00301 fflush (stdout);
00302 if (lpval)
00303 dbl_EGlpNumCopy (*lpval, val);
00304
00305 if (qlp->intmarker)
00306 {
00307 for (i = 0; i < qlp->nstruct; i++)
00308 {
00309 if (qlp->intmarker[i])
00310 {
00311 col = qlp->structmap[i];
00312 intcount++;
00313 if (dbl_EGlpNumIsEqqual (qlp->lower[col], dbl_ILL_MINDOUBLE)
00314 || dbl_EGlpNumIsEqqual (qlp->upper[col], dbl_ILL_MAXDOUBLE))
00315 {
00316 printf ("Instance has unbounded integer variable\n");
00317 fflush (stdout);
00318 rval = 1;
00319 goto CLEANUP;
00320 }
00321 }
00322 }
00323 }
00324
00325 if (intcount == 0)
00326 {
00327 printf ("No integer variables\n");
00328 fflush (stdout);
00329 rval = 1;
00330 goto CLEANUP;
00331 }
00332 else
00333 {
00334 printf ("%d integer variables\n", intcount);
00335 fflush (stdout);
00336 }
00337
00338 if (qlp->sinfo)
00339 {
00340 dbl_ILLlp_sinfo_free (qlp->sinfo);
00341 ILL_IFFREE (qlp->sinfo, dbl_ILLlp_sinfo);
00342 }
00343
00344
00345 minf->lp = lp;
00346 minf->pinf = pinf;
00347 minf->objsense = qlp->objsense;
00348 if (qlp->objsense == dbl_ILL_MAX)
00349 {
00350 for (i = 0; i < lp->ncols; i++)
00351 {
00352 dbl_EGlpNumCopyNeg (qlp->obj[i], qlp->obj[i]);
00353 }
00354 qlp->objsense = dbl_ILL_MIN;
00355 }
00356
00357 minf->x = dbl_EGlpNumAllocArray (qlp->nstruct);
00358 minf->bestx = dbl_EGlpNumAllocArray (qlp->nstruct);
00359 minf->lower = dbl_EGlpNumAllocArray (qlp->nstruct);
00360 minf->upper = dbl_EGlpNumAllocArray (qlp->nstruct);
00361 minf->orig_lower = dbl_EGlpNumAllocArray (qlp->nstruct);
00362 minf->orig_upper = dbl_EGlpNumAllocArray (qlp->nstruct);
00363 minf->downpen = dbl_EGlpNumAllocArray (qlp->nstruct);
00364 minf->uppen = dbl_EGlpNumAllocArray (qlp->nstruct);
00365 minf->nstruct = qlp->nstruct;
00366
00367 rval = dbl_ILLlib_get_x (lp, 0, minf->x);
00368 ILL_CLEANUP_IF (rval);
00369
00370 for (i = 0; i < qlp->nstruct; i++)
00371 {
00372 dbl_EGlpNumCopy (minf->lower[i], qlp->lower[i]);
00373 dbl_EGlpNumCopy (minf->upper[i], qlp->upper[i]);
00374 dbl_EGlpNumCopy (minf->orig_lower[i], qlp->lower[i]);
00375 dbl_EGlpNumCopy (minf->orig_upper[i], qlp->upper[i]);
00376 dbl_EGlpNumOne (minf->downpen[i]);
00377 dbl_EGlpNumOne (minf->uppen[i]);
00378 dbl_EGlpNumSign (minf->downpen[i]);
00379 dbl_EGlpNumSign (minf->uppen[i]);
00380 }
00381
00382
00383 CLEANUP:
00384
00385 dbl_EGlpNumClearVar (val);
00386 ILL_RETURN (rval, "dbl_startup_mip");
00387 }
00388
00389 static void dbl_cleanup_mip (
00390 dbl_mipinfo * minf)
00391 {
00392 int i;
00393 dbl_ILLlpdata *qslp;
00394
00395 if (minf && minf->lp)
00396 {
00397 qslp = minf->lp->O;
00398 if (minf->objsense == dbl_ILL_MAX)
00399 {
00400 for (i = 0; i < minf->lp->ncols; i++)
00401 {
00402 dbl_EGlpNumSign (qslp->obj[i]);
00403 }
00404 qslp->objsense = dbl_ILL_MIN;
00405 }
00406 }
00407 }
00408
00409 static int dbl_run_bfs (
00410 dbl_mipinfo * minf,
00411 itcnt_t*itcnt)
00412 {
00413 int rval = 0;
00414 dbl_bbnode *b;
00415
00416 while (minf->head_bbnode.next)
00417 {
00418 dbl_best_bbnode (minf, &b);
00419 rval = dbl_process_bfs_bbnode (minf, b, itcnt);
00420 ILL_CLEANUP_IF (rval);
00421 dbl_remove_bbnode (b);
00422 dbl_free_bbnode (b);
00423 bbnodefree (&minf->ptrworld, b);
00424 minf->activenodes--;
00425 }
00426
00427 CLEANUP:
00428
00429 ILL_RETURN (rval, "dbl_run_bfs");
00430 }
00431
00432 static int dbl_process_bfs_bbnode (
00433 dbl_mipinfo * minf,
00434 dbl_bbnode * active,
00435 itcnt_t*itcnt)
00436 {
00437 dbl_lpinfo *lp = minf->lp;
00438 dbl_ILLlp_basis B;
00439 int status, bvar = 0;
00440 int i, j, hit, dnp = 0, upp = 0;
00441 int nstruct = lp->O->nstruct;
00442 double t, lpval, dnval, upval;
00443 double *wupper = 0;
00444 double *wlower = 0;
00445 int rval = 0;
00446
00447 dbl_EGlpNumInitVar (t);
00448 dbl_EGlpNumInitVar (lpval);
00449 dbl_EGlpNumInitVar (dnval);
00450 dbl_EGlpNumInitVar (upval);
00451
00452 dbl_ILLlp_basis_init (&B);
00453
00454 if (minf->watch > 1)
00455 {
00456 printf ("Node %4d: %.3f", active->id, dbl_EGlpNumToLf (active->bound));
00457 if (dbl_EGlpNumIsNeqq (minf->value, dbl_ILL_MAXDOUBLE))
00458 printf (" %.3f", dbl_EGlpNumToLf (minf->value));
00459 else
00460 printf (" None");
00461 printf (", Active %d ", minf->activenodes);
00462 fflush (stdout);
00463 }
00464 else if (minf->watch == 1)
00465 {
00466 if (minf->lastpivots > 1000)
00467 {
00468 minf->lastpivots = 0;
00469 printf ("Pivots %d, Active Nodes %d, Bound %.3f, Soln ",
00470 minf->totalpivots, minf->activenodes,
00471 dbl_EGlpNumToLf (active->bound));
00472 if (!dbl_EGlpNumIsLess (minf->value, dbl_ILL_MAXDOUBLE))
00473 printf ("%.3f", dbl_EGlpNumToLf (minf->value));
00474 else
00475 printf ("None\n");
00476 }
00477 }
00478
00479 if (dbl_EGlpNumIsLeq (minf->objectivebound, active->bound))
00480 {
00481 if (minf->watch > 1)
00482 {
00483 printf (" Node can be purged\n");
00484 fflush (stdout);
00485 }
00486 goto CLEANUP;
00487 }
00488
00489
00490
00491 wlower = dbl_EGlpNumAllocArray (nstruct);
00492 wupper = dbl_EGlpNumAllocArray (nstruct);
00493
00494 for (i = 0; i < nstruct; i++)
00495 {
00496 dbl_EGlpNumCopy (wlower[i], minf->orig_lower[i]);
00497 dbl_EGlpNumCopy (wupper[i], minf->orig_upper[i]);
00498 }
00499 for (i = 0; i < active->bound_cnt; i++)
00500 {
00501 j = active->bound_indx[i];
00502 if (active->lu[i] == 'L')
00503 dbl_EGlpNumCopy (wlower[j], active->bounds[i]);
00504 else
00505 dbl_EGlpNumCopy (wupper[j], active->bounds[i]);
00506 }
00507
00508 if (active->bound_cnt > 0)
00509 {
00510 rval = dbl_ILLlib_chgbnds (lp, active->bound_cnt, active->bound_indx,
00511 active->lu, active->bounds);
00512 ILL_CLEANUP_IF (rval);
00513 }
00514
00515
00516
00517 rval = dbl_ILLlib_loadbasis (&B, nstruct, lp->nrows, active->cstat,
00518 active->rstat);
00519 ILL_CLEANUP_IF (rval);
00520 if (active->rownorms)
00521 {
00522 B.rownorms = dbl_EGlpNumAllocArray (lp->nrows);
00523 for (i = 0; i < lp->nrows; i++)
00524 {
00525 dbl_EGlpNumCopy (B.rownorms[i], active->rownorms[i]);
00526 }
00527 }
00528
00529 rval = dbl_ILLlib_optimize (lp, &B, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
00530 ILL_CLEANUP_IF (rval);
00531
00532 minf->totalpivots += dbl_ILLlib_iter (lp);
00533 minf->lastpivots += dbl_ILLlib_iter (lp);
00534
00535 if (status == QS_LP_UNSOLVED)
00536 {
00537 printf ("Simplex did not solve the LP\n");
00538 fflush (stdout);
00539 rval = 1;
00540 ILL_CLEANUP;
00541 }
00542
00543 if (status == QS_LP_INFEASIBLE)
00544 {
00545 printf (" Infeasible LP, should have been purged earlier\n");
00546 fflush (stdout);
00547 rval = 1;
00548 ILL_CLEANUP;
00549 }
00550
00551 if (active->depth < 0)
00552 {
00553 for (i = 0; i < nstruct; i++)
00554 {
00555 dbl_EGlpNumCopy (minf->lower[i], wlower[i]);
00556 dbl_EGlpNumCopy (minf->upper[i], wupper[i]);
00557 }
00558 rval = dbl_plunge (minf, itcnt);
00559 ILL_CLEANUP_IF (rval);
00560 }
00561
00562
00563
00564 if (dbl_EGlpNumIsLess (minf->value, dbl_ILL_MAXDOUBLE))
00565 {
00566 rval = dbl_fix_variables (lp, &(minf->value), active, wupper, wlower, &hit);
00567 ILL_CLEANUP_IF (rval);
00568
00569 if (hit)
00570 {
00571 rval = dbl_ILLlib_optimize (lp, &B, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
00572 ILL_CLEANUP_IF (rval);
00573
00574 minf->totalpivots += dbl_ILLlib_iter (lp);
00575 minf->lastpivots += dbl_ILLlib_iter (lp);
00576
00577 if (status == QS_LP_UNSOLVED)
00578 {
00579 printf ("Simplex did not solve the LP\n");
00580 fflush (stdout);
00581 rval = 1;
00582 ILL_CLEANUP;
00583 }
00584
00585 if (status == QS_LP_INFEASIBLE)
00586 {
00587 printf (" Infeasible LP after fixing\n");
00588 fflush (stdout);
00589 rval = 1;
00590 ILL_CLEANUP;
00591 }
00592 }
00593 }
00594
00595
00596
00597
00598 rval = dbl_ILLlib_get_x (lp, 0, minf->x);
00599 ILL_CLEANUP_IF (rval);
00600
00601 rval = dbl_ILLlib_objval (lp, 0, &lpval);
00602 ILL_CLEANUP_IF (rval);
00603
00604 rval = dbl_find_branch (minf, minf->x, &lpval, &bvar, itcnt);
00605 ILL_CLEANUP_IF (rval);
00606
00607 if (bvar == -1)
00608 {
00609 printf ("Found integral solution: %f\n", dbl_EGlpNumToLf (lpval));
00610 if (dbl_EGlpNumIsLess (lpval, minf->value))
00611 {
00612 dbl_EGlpNumCopy (minf->value, lpval);
00613 dbl_EGlpNumCopy (minf->objectivebound, lpval);
00614 dbl_EGlpNumSubTo (minf->objectivebound, dbl_ILL_INTTOL);
00615 dbl_copy_x (nstruct, minf->x, minf->bestx);
00616 }
00617 }
00618 else
00619 {
00620
00621
00622 rval = dbl_child_work (minf, active, bvar, 'D', &dnval, &dnp, itcnt);
00623 ILL_CLEANUP_IF (rval);
00624
00625
00626
00627 rval = dbl_ILLlib_loadbasis (&B, nstruct, lp->nrows, active->cstat,
00628 active->rstat);
00629 ILL_CLEANUP_IF (rval);
00630 if (active->rownorms)
00631 {
00632 B.rownorms = dbl_EGlpNumAllocArray (lp->nrows);
00633 for (i = 0; i < lp->nrows; i++)
00634 {
00635 dbl_EGlpNumCopy (B.rownorms[i], active->rownorms[i]);
00636 }
00637 }
00638
00639
00640
00641 rval = dbl_child_work (minf, active, bvar, 'U', &upval, &upp, itcnt);
00642 ILL_CLEANUP_IF (rval);
00643
00644 if (minf->watch > 1)
00645 {
00646 if (dbl_EGlpNumIsEqqual (dnval, dbl_ILL_MAXDOUBLE))
00647 {
00648 printf ("DN->XXX");
00649 }
00650 else
00651 {
00652 printf ("DN->%.3f%c", dbl_EGlpNumToLf (dnval), dnp ? 'X' : ' ');
00653 }
00654 if (dbl_EGlpNumIsEqqual (upval, dbl_ILL_MAXDOUBLE))
00655 {
00656 printf ("UP->XXX\n");
00657 }
00658 else
00659 {
00660 printf ("UP->%.3f%c\n", dbl_EGlpNumToLf (upval), upp ? 'X' : ' ');
00661 }
00662 fflush (stdout);
00663 }
00664 }
00665
00666
00667
00668 for (i = 0; i < active->bound_cnt; i++)
00669 {
00670 if (active->lu[i] == 'L')
00671 dbl_EGlpNumCopy (t, minf->orig_lower[active->bound_indx[i]]);
00672 else
00673 dbl_EGlpNumCopy (t, minf->orig_upper[active->bound_indx[i]]);
00674
00675 rval = dbl_ILLlib_chgbnd (lp, active->bound_indx[i], active->lu[i], t);
00676 ILL_CLEANUP_IF (rval);
00677 }
00678
00679 CLEANUP:
00680
00681 dbl_EGlpNumFreeArray (wlower);
00682 dbl_EGlpNumFreeArray (wupper);
00683 dbl_ILLlp_basis_free (&B);
00684 dbl_EGlpNumClearVar (t);
00685 dbl_EGlpNumClearVar (lpval);
00686 dbl_EGlpNumClearVar (dnval);
00687 dbl_EGlpNumClearVar (upval);
00688 ILL_RETURN (rval, "dbl_process_bfs_bbnode");
00689 }
00690
00691 static int dbl_child_work (
00692 dbl_mipinfo * minf,
00693 dbl_bbnode * active,
00694 int bvar,
00695 int bdir,
00696 double * cval,
00697 int *cp,
00698 itcnt_t*itcnt)
00699 {
00700 int tval, rval = 0;
00701 int i, status, intsol;
00702 double t, oldt, lpval;
00703 double *xi = &(minf->x[bvar]);
00704 dbl_lpinfo *lp = minf->lp;
00705 dbl_bbnode *b;
00706
00707 dbl_EGlpNumInitVar (t);
00708 dbl_EGlpNumInitVar (lpval);
00709 dbl_EGlpNumInitVar (oldt);
00710
00711 *cp = 0;
00712
00713 if (bdir == 'D')
00714 {
00715 rval = dbl_ILLlib_getbnd (lp, bvar, 'U', &oldt);
00716 ILL_CLEANUP_IF (rval);
00717 dbl_EGlpNumFloor (t, *xi);
00718 rval = dbl_ILLlib_chgbnd (lp, bvar, 'U', t);
00719 ILL_CLEANUP_IF (rval);
00720 }
00721 else
00722 {
00723 rval = dbl_ILLlib_getbnd (lp, bvar, 'L', &oldt);
00724 ILL_CLEANUP_IF (rval);
00725 dbl_EGlpNumCeil (t, *xi);
00726 rval = dbl_ILLlib_chgbnd (lp, bvar, 'L', t);
00727 ILL_CLEANUP_IF (rval);
00728 }
00729
00730 rval = dbl_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
00731 ILL_CLEANUP_IF (rval);
00732
00733 minf->totalpivots += dbl_ILLlib_iter (lp);
00734 minf->lastpivots += dbl_ILLlib_iter (lp);
00735
00736 if (status == QS_LP_UNSOLVED)
00737 {
00738 printf ("Simplex did not solve Child LP\n");
00739 fflush (stdout);
00740 rval = 1;
00741 ILL_CLEANUP;
00742 }
00743
00744 if (status == QS_LP_INFEASIBLE)
00745 {
00746 dbl_EGlpNumCopy (*cval, dbl_ILL_MAXDOUBLE);
00747 *cp = 1;
00748 }
00749 else
00750 {
00751 rval = dbl_ILLlib_objval (lp, 0, &lpval);
00752 ILL_CLEANUP_IF (rval);
00753 dbl_EGlpNumCopy (*cval, lpval);
00754
00755
00756
00757 dbl_check_integral (lp, minf->x, &intsol);
00758 if (intsol)
00759 {
00760 if (dbl_EGlpNumIsLess (lpval, minf->value))
00761 {
00762 printf ("Found integral solution: %f\n", dbl_EGlpNumToLf (lpval));
00763 dbl_EGlpNumCopy (minf->value, lpval);
00764 dbl_EGlpNumCopy (minf->objectivebound, lpval);
00765 dbl_EGlpNumSubTo (minf->objectivebound, dbl_ILL_INTTOL);
00766 dbl_copy_x (lp->O->nstruct, minf->x, minf->bestx);
00767 }
00768 }
00769
00770 if (dbl_EGlpNumIsLeq (minf->objectivebound, lpval))
00771 {
00772 *cp = 1;
00773 }
00774 else
00775 {
00776 b = bbnodealloc (&minf->ptrworld);
00777 dbl_init_bbnode (b);
00778 b->depth = active->depth + 1;
00779 b->id = minf->totalnodes;
00780 dbl_EGlpNumCopy (b->bound, lpval);
00781 ILL_SAFE_MALLOC (b->cstat, lp->O->nstruct, char);
00782 ILL_SAFE_MALLOC (b->rstat, lp->nrows, char);
00783
00784 rval = dbl_ILLlib_getbasis (lp, b->cstat, b->rstat);
00785 ILL_CLEANUP_IF (rval);
00786 if (minf->pinf->dII_price == QS_PRICE_DSTEEP)
00787 {
00788 b->rownorms = dbl_EGlpNumAllocArray (lp->nrows);
00789 tval = dbl_ILLlib_getrownorms (lp, minf->pinf, b->rownorms);
00790 if (tval)
00791 {
00792 printf ("Row norms not available\n");
00793 fflush (stdout);
00794 printf ("A\n");
00795 exit (1);
00796 dbl_EGlpNumFreeArray (b->rownorms);
00797 }
00798 }
00799 ILL_SAFE_MALLOC (b->bound_indx, active->bound_cnt + 1, int);
00800 ILL_SAFE_MALLOC (b->lu, active->bound_cnt + 1, char);
00801
00802 b->bounds = dbl_EGlpNumAllocArray (active->bound_cnt + 1);
00803 for (i = 0; i < active->bound_cnt; i++)
00804 {
00805 b->bound_indx[i] = active->bound_indx[i];
00806 b->lu[i] = active->lu[i];
00807 dbl_EGlpNumCopy (b->bounds[i], active->bounds[i]);
00808 }
00809 b->bound_indx[active->bound_cnt] = bvar;
00810 if (bdir == 'D')
00811 b->lu[active->bound_cnt] = 'U';
00812 else
00813 b->lu[active->bound_cnt] = 'L';
00814 dbl_EGlpNumCopy (b->bounds[active->bound_cnt], t);
00815 b->bound_cnt = active->bound_cnt + 1;
00816
00817 rval = dbl_ILLutil_priority_insert (minf->que, (void *) b, &lpval,
00818 &(b->handle));
00819 ILL_CLEANUP_IF (rval);
00820
00821 dbl_put_bbnode (minf, b);
00822 minf->activenodes++;
00823 }
00824 }
00825 minf->totalnodes++;
00826
00827 if (bdir == 'D')
00828 {
00829 rval = dbl_ILLlib_chgbnd (lp, bvar, 'U', oldt);
00830 ILL_CLEANUP_IF (rval);
00831 }
00832 else
00833 {
00834 rval = dbl_ILLlib_chgbnd (lp, bvar, 'L', oldt);
00835 ILL_CLEANUP_IF (rval);
00836 }
00837
00838 CLEANUP:
00839
00840 dbl_EGlpNumClearVar (t);
00841 dbl_EGlpNumClearVar (lpval);
00842 dbl_EGlpNumClearVar (oldt);
00843 return rval;
00844 }
00845
00846 static int dbl_fix_variables (
00847 dbl_lpinfo * lp,
00848 double * bestval,
00849 dbl_bbnode * b,
00850 double * wupper,
00851 double * wlower,
00852 int *hit)
00853 {
00854 int rval = 0;
00855 int i, nnew = 0;
00856 int nstruct = lp->O->nstruct;
00857 double delta, lpval;
00858 int *new_indx = 0;
00859 char *new_lu = 0;
00860 double *new_bounds = 0;
00861 double *dj = 0;
00862
00863 dbl_EGlpNumInitVar (delta);
00864 dbl_EGlpNumInitVar (lpval);
00865
00866 *hit = 0;
00867
00868 if (dbl_EGlpNumIsLess (*bestval, dbl_ILL_MAXDOUBLE))
00869 {
00870 rval = dbl_ILLlib_objval (lp, 0, &lpval);
00871 ILL_CLEANUP_IF (rval);
00872
00873 dbl_EGlpNumCopy (delta, *bestval);
00874 dbl_EGlpNumSubTo (delta, lpval);
00875 dbl_EGlpNumAddTo (delta, dbl_ILL_INTTOL);
00876
00877 ILL_SAFE_MALLOC (new_indx, nstruct, int);
00878 ILL_SAFE_MALLOC (new_lu, nstruct, char);
00879
00880 dj = dbl_EGlpNumAllocArray (nstruct);
00881 new_bounds = dbl_EGlpNumAllocArray (nstruct);
00882
00883 rval = dbl_ILLlib_solution (lp, 0, 0, 0, 0, 0, dj);
00884 ILL_CLEANUP_IF (rval);
00885
00886 for (i = 0; i < nstruct; i++)
00887 {
00888 if (lp->O->intmarker[i])
00889 {
00890 if (dbl_EGlpNumIsNeqq (wlower[i], wupper[i]))
00891 {
00892 if (dbl_EGlpNumIsLess (delta, dj[i]))
00893 {
00894 dbl_EGlpNumSubTo (wupper[i], dbl_oneLpNum);
00895 rval = dbl_ILLlib_chgbnd (lp, i, 'U', wupper[i]);
00896 ILL_CLEANUP_IF (rval);
00897 new_indx[nnew] = i;
00898 new_lu[nnew] = 'U';
00899 dbl_EGlpNumCopy (new_bounds[nnew], wupper[i]);
00900 nnew++;
00901 }
00902
00903 dbl_EGlpNumSign (delta);
00904 if (dbl_EGlpNumIsLess (delta, dj[i]))
00905 {
00906 dbl_EGlpNumAddTo (wlower[i], dbl_oneLpNum);
00907 rval = dbl_ILLlib_chgbnd (lp, i, 'L', wlower[i]);
00908 ILL_CLEANUP_IF (rval);
00909 new_indx[nnew] = i;
00910 new_lu[nnew] = 'L';
00911 dbl_EGlpNumCopy (new_bounds[nnew], wlower[i]);
00912 nnew++;
00913 }
00914 dbl_EGlpNumSign (delta);
00915 }
00916 }
00917 }
00918
00919 if (nnew)
00920 {
00921 b->bound_indx =
00922 EGrealloc (b->bound_indx, sizeof (int) * (b->bound_cnt + nnew));
00923
00924
00925
00926 b->lu = EGrealloc (b->lu, sizeof (char) * (b->bound_cnt + nnew));
00927
00928
00929
00930 dbl_EGlpNumReallocArray (&(b->bounds), b->bound_cnt + nnew);
00931 for (i = 0; i < nnew; i++)
00932 {
00933 b->bound_indx[b->bound_cnt + i] = new_indx[i];
00934 b->lu[b->bound_cnt + i] = new_lu[i];
00935 dbl_EGlpNumCopy (b->bounds[b->bound_cnt + i], new_bounds[i]);
00936 }
00937 b->bound_cnt += nnew;
00938 }
00939 }
00940
00941 *hit = nnew;
00942
00943 CLEANUP:
00944
00945 ILL_IFFREE (new_indx, int);
00946 ILL_IFFREE (new_lu, char);
00947
00948 dbl_EGlpNumFreeArray (dj);
00949 dbl_EGlpNumFreeArray (new_bounds);
00950 dbl_EGlpNumClearVar (delta);
00951 dbl_EGlpNumClearVar (lpval);
00952 return rval;
00953 }
00954
00955 static void dbl_best_bbnode (
00956 dbl_mipinfo * minf,
00957 dbl_bbnode ** best)
00958 {
00959 #if 0
00960 dbl_bbnode *b;
00961 double bestval = dbl_ILL_MAXDOUBLE;
00962
00963 for (b = minf->head_bbnode.next; b; b = b->next)
00964 {
00965 if (b->bound < bestval)
00966 {
00967 *best = b;
00968 bestval = b->bound;
00969 }
00970 }
00971 #endif
00972
00973 double val;
00974
00975 dbl_EGlpNumInitVar (val);
00976 dbl_ILLutil_priority_deletemin (minf->que, &val, (void **) best);
00977 dbl_EGlpNumClearVar (val);
00978 }
00979
00980 static void dbl_put_bbnode (
00981 dbl_mipinfo * minf,
00982 dbl_bbnode * b)
00983 {
00984 b->next = minf->head_bbnode.next;
00985 b->prev = &(minf->head_bbnode);
00986 if (b->next)
00987 b->next->prev = b;
00988 minf->head_bbnode.next = b;
00989 }
00990
00991 static void dbl_remove_bbnode (
00992 dbl_bbnode * b)
00993 {
00994 b->prev->next = b->next;
00995 if (b->next)
00996 b->next->prev = b->prev;
00997 }
00998
00999 static int dbl_find_branch (
01000 dbl_mipinfo * minf,
01001 double * x,
01002 double * lpval,
01003 int *bvar,
01004 itcnt_t*itcnt)
01005 {
01006 dbl_lpinfo *lp = minf->lp;
01007 int rval = 0;
01008
01009 switch (minf->branching_rule)
01010 {
01011 case dbl_PENALTYBRANCH:
01012 rval = dbl_find_penalty_branch (lp, minf->pinf, x, minf->downpen,
01013 minf->uppen, lpval, bvar, itcnt);
01014 ILL_CLEANUP_IF (rval);
01015 break;
01016 case dbl_FIRSTBRANCH:
01017 dbl_find_first_branch (lp, x, bvar);
01018 break;
01019 case dbl_MIDDLEBRANCH:
01020 dbl_find_middle_branch (lp, x, bvar);
01021 break;
01022 case dbl_STRONGBRANCH:
01023 rval = dbl_find_strong_branch (lp, minf->pinf, x, bvar, itcnt);
01024 ILL_CLEANUP_IF (rval);
01025 break;
01026 default:
01027 fprintf (stderr, "Unknown branching rule.\n");
01028 rval = 1;
01029 goto CLEANUP;
01030 }
01031
01032 CLEANUP:
01033
01034 ILL_RETURN (rval, "dbl_find_branch");
01035 }
01036
01037 static void dbl_find_first_branch (
01038 dbl_lpinfo * lp,
01039 double * x,
01040 int *bvar)
01041 {
01042 int i, ibest = -1;
01043 dbl_ILLlpdata *qslp = lp->O;
01044 double t;
01045
01046 dbl_EGlpNumInitVar (t);
01047
01048 for (i = 0; i < qslp->nstruct; i++)
01049 {
01050 if (qslp->intmarker[i])
01051 {
01052
01053 dbl_EGlpNumFloor (t, x[i]);
01054 dbl_EGlpNumSubTo (t, x[i]);
01055 dbl_EGlpNumSign (t);
01056 if ((dbl_EGlpNumIsNeqZero (t, dbl_ILL_INTTOL)) &&
01057 (dbl_EGlpNumIsNeq (t, dbl_oneLpNum, dbl_ILL_INTTOL)))
01058 {
01059 ibest = i;
01060 break;
01061 }
01062 }
01063 }
01064 *bvar = ibest;
01065 dbl_EGlpNumClearVar (t);
01066 }
01067
01068 static void dbl_find_middle_branch (
01069 dbl_lpinfo * lp,
01070 double * x,
01071 int *bvar)
01072 {
01073 int i, ibest = -1;
01074 double t, tbest;
01075 dbl_ILLlpdata *qlp = lp->O;
01076
01077 dbl_EGlpNumInitVar (t);
01078 dbl_EGlpNumInitVar (tbest);
01079 dbl_EGlpNumSet (tbest, 0.5);
01080
01081 for (i = 0; i < qlp->nstruct; i++)
01082 {
01083 if (qlp->intmarker[i])
01084 {
01085
01086
01087
01088 dbl_EGlpNumFloor (t, x[i]);
01089 dbl_EGlpNumMultUiTo (t, 2);
01090 dbl_EGlpNumSubTo (t, dbl_oneLpNum);
01091 dbl_EGlpNumDivUiTo (t, 2);
01092 if (dbl_EGlpNumIsLessZero (t))
01093 dbl_EGlpNumSign (t);
01094
01095 if (dbl_EGlpNumIsLess (t, tbest))
01096 {
01097 dbl_EGlpNumCopy (tbest, t);
01098 ibest = i;
01099 }
01100 }
01101 }
01102
01103
01104 dbl_EGlpNumAddTo (tbest, dbl_ILL_INTTOL);
01105 if (dbl_EGlpNumIsLessDbl (tbest, 0.5))
01106 {
01107 *bvar = ibest;
01108 }
01109 else
01110 {
01111 *bvar = -1;
01112 }
01113 dbl_EGlpNumClearVar (t);
01114 dbl_EGlpNumClearVar (tbest);
01115 }
01116
01117 static int dbl_find_penalty_branch (
01118 dbl_lpinfo * lp,
01119 dbl_price_info * pinf,
01120 double * x,
01121 double * downpen,
01122 double * uppen,
01123 double * lpval,
01124 int *bvar,
01125 itcnt_t*itcnt)
01126 {
01127 int rval = 0;
01128 int i, k, ibest = -1, ncand = 0, nneed = 0;
01129 dbl_ILLlpdata *qslp = lp->O;
01130 int *candidatelist = 0;
01131 int *needlist = 0;
01132 double *fval = 0;
01133 double *xlist = 0;
01134 double *newdown = 0;
01135 double *newup = 0;
01136 double a, t, tbest;
01137
01138 dbl_EGlpNumInitVar (a);
01139 dbl_EGlpNumInitVar (t);
01140 dbl_EGlpNumInitVar (tbest);
01141 dbl_EGlpNumCopy (tbest, dbl_ILL_MINDOUBLE);
01142
01143 ILL_SAFE_MALLOC (candidatelist, qslp->nstruct, int);
01144 ILL_SAFE_MALLOC (needlist, qslp->nstruct, int);
01145
01146 fval = dbl_EGlpNumAllocArray (qslp->nstruct);
01147 xlist = dbl_EGlpNumAllocArray (qslp->nstruct);
01148 for (i = 0; i < qslp->nstruct; i++)
01149 {
01150 if (qslp->intmarker[i])
01151 {
01152
01153 dbl_EGlpNumFloor (fval[i], x[i]);
01154 dbl_EGlpNumSubTo (fval[i], x[i]);
01155 dbl_EGlpNumSign (fval[i]);
01156 if ((dbl_EGlpNumIsNeqZero (fval[i], dbl_ILL_INTTOL)) &&
01157 (dbl_EGlpNumIsNeq (fval[i], dbl_oneLpNum, dbl_ILL_INTTOL)))
01158 {
01159 candidatelist[ncand++] = i;
01160
01161 dbl_EGlpNumSign (downpen[i]);
01162 if (dbl_EGlpNumIsEqqual (downpen[i], dbl_oneLpNum))
01163 {
01164 dbl_EGlpNumCopy (xlist[nneed], x[i]);
01165 needlist[nneed++] = i;
01166 }
01167 dbl_EGlpNumSign (downpen[i]);
01168 }
01169 }
01170 }
01171
01172 if (nneed > 0)
01173 {
01174 newdown = dbl_EGlpNumAllocArray (nneed);
01175 newup = dbl_EGlpNumAllocArray (nneed);
01176 rval = dbl_ILLlib_strongbranch (lp, pinf, needlist, nneed,
01177 0, newdown, newup,
01178 5 * dbl_STRONG_PIVOTS, dbl_ILL_MAXDOUBLE, itcnt);
01179 ILL_CLEANUP_IF (rval);
01180
01181 for (i = 0; i < nneed; i++)
01182 {
01183 k = needlist[i];
01184
01185 dbl_EGlpNumCopyDiff (uppen[k], newup[i], *lpval);
01186 dbl_EGlpNumCopyDiff (downpen[k], dbl_oneLpNum, fval[k]);
01187 dbl_EGlpNumDivTo (uppen[k], downpen[k]);
01188
01189 dbl_EGlpNumCopyDiffRatio (downpen[k], newdown[i], *lpval, fval[k]);
01190
01191 }
01192 }
01193
01194 for (i = 0; i < ncand; i++)
01195 {
01196 k = candidatelist[i];
01197
01198 dbl_EGlpNumCopy (t, downpen[k]);
01199 dbl_EGlpNumMultTo (t, fval[k]);
01200 dbl_EGlpNumCopyDiff (a, dbl_oneLpNum, fval[k]);
01201 dbl_EGlpNumMultTo (a, uppen[k]);
01202 if (dbl_EGlpNumIsLess (t, a))
01203 {
01204 dbl_EGlpNumMultUiTo (t, dbl_ILL_BRANCH_PENALTY_WEIGHT);
01205 dbl_EGlpNumAddTo (t, a);
01206 }
01207 else
01208 {
01209 dbl_EGlpNumMultUiTo (a, dbl_ILL_BRANCH_PENALTY_WEIGHT);
01210 dbl_EGlpNumAddTo (t, a);
01211 }
01212 dbl_EGlpNumDivUiTo (t, dbl_ILL_BRANCH_PENALTY_WEIGHT + 1);
01213
01214 if (dbl_EGlpNumIsLess (tbest, t))
01215 {
01216 dbl_EGlpNumCopy (tbest, t);
01217 ibest = k;
01218 }
01219 }
01220
01221 *bvar = ibest;
01222
01223 CLEANUP:
01224
01225 dbl_EGlpNumClearVar (a);
01226 dbl_EGlpNumClearVar (t);
01227 dbl_EGlpNumClearVar (tbest);
01228 dbl_EGlpNumFreeArray (newdown);
01229 dbl_EGlpNumFreeArray (newup);
01230 dbl_EGlpNumFreeArray (fval);
01231 dbl_EGlpNumFreeArray (xlist);
01232 ILL_IFFREE (candidatelist, int);
01233 ILL_IFFREE (needlist, int);
01234
01235 return rval;
01236 }
01237
01238 static int dbl_find_strong_branch (
01239 dbl_lpinfo * lp,
01240 dbl_price_info * pinf,
01241 double * x,
01242 int *bvar,
01243 itcnt_t*itcnt)
01244 {
01245 int rval = 0;
01246 int i, ibest = -1, ncand = 0;
01247 int maxtrys = dbl_STRONG_CANDIDATES;
01248 double t, tbest;
01249 dbl_ILLlpdata *qlp = lp->O;
01250 int *candidatelist = 0;
01251 int *newlist = 0;
01252 int *perm = 0;
01253 double *tval = 0;
01254 double *xlist = 0;
01255 double *downpen = 0;
01256 double *uppen = 0;
01257 ILLrandstate rstate;
01258
01259 dbl_EGlpNumInitVar (t);
01260 dbl_EGlpNumInitVar (tbest);
01261 dbl_EGlpNumCopy (tbest, dbl_ILL_MINDOUBLE);
01262
01263 ILLutil_sprand (999, &rstate);
01264 ILL_SAFE_MALLOC (candidatelist, qlp->nstruct, int);
01265
01266 tval = dbl_EGlpNumAllocArray (qlp->nstruct);
01267
01268 for (i = 0; i < qlp->nstruct; i++)
01269 {
01270 if (qlp->intmarker[i])
01271 {
01272
01273
01274
01275 dbl_EGlpNumFloor (t, x[i]);
01276 dbl_EGlpNumSubTo (t, x[i]);
01277 dbl_EGlpNumSign (t);
01278 dbl_EGlpNumMultUiTo (t, 2);
01279 dbl_EGlpNumSubTo (t, dbl_oneLpNum);
01280 if (dbl_EGlpNumIsLessZero (t))
01281 dbl_EGlpNumSign (t);
01282
01283 if (dbl_EGlpNumIsNeq (t, dbl_oneLpNum, dbl_ILL_INTTOL))
01284 {
01285 candidatelist[ncand] = i;
01286 dbl_EGlpNumDivUiTo (t, 2);
01287 dbl_EGlpNumCopy (tval[ncand++], t);
01288 }
01289 }
01290 }
01291
01292 if (ncand > 0)
01293 {
01294 if (ncand > maxtrys)
01295 {
01296 ILL_SAFE_MALLOC (perm, ncand, int);
01297
01298 for (i = 0; i < ncand; i++)
01299 {
01300 perm[i] = i;
01301 }
01302 dbl_ILLutil_EGlpNum_rselect (perm, 0, ncand - 1, maxtrys, tval, &rstate);
01303
01304 ILL_SAFE_MALLOC (newlist, maxtrys, int);
01305
01306 for (i = 0; i < maxtrys; i++)
01307 {
01308 newlist[i] = candidatelist[perm[i]];
01309 }
01310 ILL_IFFREE (candidatelist, int);
01311
01312 candidatelist = newlist;
01313 newlist = 0;
01314 ncand = maxtrys;
01315 }
01316
01317 downpen = dbl_EGlpNumAllocArray (ncand);
01318 uppen = dbl_EGlpNumAllocArray (ncand);
01319 xlist = dbl_EGlpNumAllocArray (ncand);
01320
01321 for (i = 0; i < ncand; i++)
01322 {
01323 dbl_EGlpNumCopy (xlist[i], x[candidatelist[i]]);
01324 }
01325
01326 rval = dbl_ILLlib_strongbranch (lp, pinf, candidatelist, ncand,
01327 0, downpen, uppen, dbl_STRONG_PIVOTS,
01328 dbl_ILL_MAXDOUBLE, itcnt);
01329 ILL_CLEANUP_IF (rval);
01330
01331 for (i = 0; i < ncand; i++)
01332 {
01333
01334 if (dbl_EGlpNumIsLess (downpen[i], uppen[i]))
01335 {
01336 dbl_EGlpNumCopy (t, downpen[i]);
01337 dbl_EGlpNumMultUiTo (t, dbl_ILL_BRANCH_STRONG_WEIGHT);
01338 dbl_EGlpNumAddTo (t, uppen[i]);
01339 }
01340 else
01341 {
01342 dbl_EGlpNumCopy (t, uppen[i]);
01343 dbl_EGlpNumMultUiTo (t, dbl_ILL_BRANCH_STRONG_WEIGHT);
01344 dbl_EGlpNumAddTo (t, downpen[i]);
01345 }
01346 dbl_EGlpNumDivUiTo (t, dbl_ILL_BRANCH_STRONG_WEIGHT + 1);
01347 if (dbl_EGlpNumIsLess (tbest, t))
01348 {
01349 dbl_EGlpNumCopy (tbest, t);
01350 ibest = candidatelist[i];
01351 }
01352 }
01353 }
01354
01355 *bvar = ibest;
01356
01357
01358 CLEANUP:
01359
01360 dbl_EGlpNumClearVar (t);
01361 dbl_EGlpNumClearVar (tbest);
01362 dbl_EGlpNumFreeArray (tval);
01363 dbl_EGlpNumFreeArray (xlist);
01364 dbl_EGlpNumFreeArray (uppen);
01365 dbl_EGlpNumFreeArray (downpen);
01366 ILL_IFFREE (candidatelist, int);
01367 ILL_IFFREE (newlist, int);
01368 ILL_IFFREE (perm, int);
01369
01370 ILL_RETURN (rval, "dbl_find_strong_branch");
01371 }
01372
01373 static void dbl_check_integral (
01374 dbl_lpinfo * lp,
01375 double * x,
01376 int *yesno)
01377 {
01378 int i;
01379 double t;
01380 dbl_ILLlpdata *qlp = lp->O;
01381
01382 dbl_EGlpNumInitVar (t);
01383
01384 for (i = 0; i < qlp->nstruct; i++)
01385 {
01386 if (qlp->intmarker[i])
01387 {
01388
01389 dbl_EGlpNumFloor (t, x[i]);
01390 dbl_EGlpNumSubTo (t, x[i]);
01391 dbl_EGlpNumSign (t);
01392
01393 if ((dbl_EGlpNumIsNeqZero (t, dbl_ILL_INTTOL)) &&
01394 (dbl_EGlpNumIsNeq (t, dbl_oneLpNum, dbl_ILL_INTTOL)))
01395 {
01396 *yesno = 0;
01397 dbl_EGlpNumClearVar (t);
01398 return;
01399 }
01400 }
01401 }
01402
01403 *yesno = 1;
01404 dbl_EGlpNumClearVar (t);
01405 }
01406
01407 static int dbl_plunge (
01408 dbl_mipinfo * minf,
01409 itcnt_t*itcnt)
01410 {
01411 int rval = 0;
01412 int i, status;
01413 dbl_lpinfo *lp = minf->lp;
01414 dbl_ILLlpdata *qlp = minf->lp->O;
01415 double *oldlower = 0;
01416 double *oldupper = 0;
01417
01418 if (minf->watch)
01419 {
01420 printf ("Plunging ...\n");
01421 fflush (stdout);
01422 }
01423
01424 oldlower = dbl_EGlpNumAllocArray (qlp->nstruct);
01425 oldupper = dbl_EGlpNumAllocArray (qlp->nstruct);
01426
01427 for (i = 0; i < qlp->nstruct; i++)
01428 {
01429 dbl_EGlpNumCopy (oldlower[i], minf->lower[i]);
01430 dbl_EGlpNumCopy (oldupper[i], minf->upper[i]);
01431 }
01432
01433 rval = dbl_plunge_work (minf, 0, itcnt);
01434 ILL_CLEANUP_IF (rval);
01435
01436 for (i = 0; i < qlp->nstruct; i++)
01437 {
01438 rval = dbl_ILLlib_chgbnd (lp, i, 'L', oldlower[i]);
01439 ILL_CLEANUP_IF (rval);
01440 rval = dbl_ILLlib_chgbnd (lp, i, 'U', oldupper[i]);
01441 ILL_CLEANUP_IF (rval);
01442 dbl_EGlpNumCopy (minf->lower[i], oldlower[i]);
01443 dbl_EGlpNumCopy (minf->upper[i], oldupper[i]);
01444 }
01445
01446 rval = dbl_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
01447 ILL_CLEANUP_IF (rval);
01448
01449
01450 CLEANUP:
01451
01452 dbl_EGlpNumFreeArray (oldlower);
01453 dbl_EGlpNumFreeArray (oldupper);
01454
01455 ILL_RETURN (rval, "dbl_plunge");
01456 }
01457
01458 static int dbl_plunge_work (
01459 dbl_mipinfo * minf,
01460 int depth,
01461 itcnt_t*itcnt)
01462 {
01463 int rval = 0;
01464 int bvar, status, count;
01465 double lpval, val0, val1, int_tol;
01466 dbl_lpinfo *lp = minf->lp;
01467
01468 dbl_EGlpNumInitVar (lpval);
01469 dbl_EGlpNumInitVar (val0);
01470 dbl_EGlpNumInitVar (val1);
01471 dbl_EGlpNumInitVar (int_tol);
01472 dbl_EGlpNumSet (int_tol, 0.001);
01473
01474 rval = dbl_ILLlib_get_x (lp, 0, minf->x);
01475 ILL_CLEANUP_IF (rval);
01476
01477 rval = dbl_round_variables (minf, &count, &int_tol );
01478 ILL_CLEANUP_IF (rval);
01479 if (count)
01480 {
01481 rval = dbl_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
01482 ILL_CLEANUP_IF (rval);
01483 if (status != QS_LP_OPTIMAL)
01484 {
01485 goto CLEANUP;
01486 }
01487 rval = dbl_ILLlib_get_x (lp, 0, minf->x);
01488 ILL_CLEANUP_IF (rval);
01489 }
01490
01491 dbl_find_middle_branch (lp, minf->x, &bvar);
01492 if (bvar == -1)
01493 {
01494 rval = dbl_ILLlib_objval (lp, 0, &lpval);
01495 ILL_CLEANUP_IF (rval);
01496
01497 if (dbl_EGlpNumIsLess (lpval, minf->value))
01498 {
01499 printf ("Plunge Integral Solution: %.6f (Depth: %d)\n",
01500 dbl_EGlpNumToLf (lpval), depth);
01501 fflush (stdout);
01502
01503 dbl_EGlpNumCopy (minf->value, lpval);
01504 dbl_EGlpNumCopyDiff (minf->objectivebound, lpval, dbl_ILL_INTTOL);
01505 dbl_copy_x (lp->O->nstruct, minf->x, minf->bestx);
01506 }
01507 goto CLEANUP;
01508 }
01509
01510 dbl_EGlpNumOne (minf->lower[bvar]);
01511 rval = dbl_ILLlib_chgbnd (lp, bvar, 'L', dbl_oneLpNum);
01512 ILL_CLEANUP_IF (rval);
01513 rval = dbl_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
01514 ILL_CLEANUP_IF (rval);
01515
01516 if (status == QS_LP_UNSOLVED)
01517 {
01518 printf ("Simplex did not solve the dbl_plunge LP\n");
01519 fflush (stdout);
01520 rval = 1;
01521 ILL_CLEANUP;
01522 }
01523 else if (status == QS_LP_INFEASIBLE)
01524 {
01525 dbl_EGlpNumCopy (val1, dbl_ILL_MAXDOUBLE);
01526 }
01527 else if (status == QS_LP_OPTIMAL)
01528 {
01529 rval = dbl_ILLlib_objval (lp, 0, &val1);
01530 ILL_CLEANUP_IF (rval);
01531 }
01532 else
01533 {
01534 ILL_CLEANUP;
01535 }
01536
01537 rval = dbl_ILLlib_chgbnd (lp, bvar, 'L', dbl_zeroLpNum);
01538 ILL_CLEANUP_IF (rval);
01539 dbl_EGlpNumZero (minf->lower[bvar]);
01540
01541 dbl_EGlpNumZero (minf->upper[bvar]);
01542 rval = dbl_ILLlib_chgbnd (lp, bvar, 'U', dbl_zeroLpNum);
01543 ILL_CLEANUP_IF (rval);
01544 rval = dbl_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
01545 ILL_CLEANUP_IF (rval);
01546
01547 if (status == QS_LP_UNSOLVED)
01548 {
01549 printf ("Simplex did not solve the dbl_plunge LP\n");
01550 fflush (stdout);
01551 rval = 1;
01552 ILL_CLEANUP;
01553 }
01554 else if (status == QS_LP_INFEASIBLE)
01555 {
01556 dbl_EGlpNumCopy (val0, dbl_ILL_MAXDOUBLE);
01557 }
01558 else if (status == QS_LP_OPTIMAL)
01559 {
01560 rval = dbl_ILLlib_objval (lp, 0, &val0);
01561 ILL_CLEANUP_IF (rval);
01562 }
01563 else
01564 {
01565 ILL_CLEANUP;
01566 }
01567
01568 rval = dbl_ILLlib_chgbnd (lp, bvar, 'U', dbl_oneLpNum);
01569 ILL_CLEANUP_IF (rval);
01570 dbl_EGlpNumCopy (minf->upper[bvar], dbl_oneLpNum);
01571
01572 if (dbl_EGlpNumIsEqqual (val0, dbl_ILL_MAXDOUBLE) &&
01573 dbl_EGlpNumIsEqqual (val1, dbl_ILL_MAXDOUBLE))
01574 {
01575 ILL_CLEANUP;
01576 }
01577
01578 if (dbl_EGlpNumIsLess (val0, val1))
01579 {
01580 dbl_EGlpNumZero (minf->upper[bvar]);
01581 rval = dbl_ILLlib_chgbnd (lp, bvar, 'U', dbl_zeroLpNum);
01582 ILL_CLEANUP_IF (rval);
01583 rval = dbl_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
01584 ILL_CLEANUP_IF (rval);
01585 rval = dbl_plunge_work (minf, depth + 1, itcnt);
01586 ILL_CLEANUP_IF (rval);
01587 rval = dbl_ILLlib_chgbnd (lp, bvar, 'U', dbl_oneLpNum);
01588 ILL_CLEANUP_IF (rval);
01589 dbl_EGlpNumOne (minf->upper[bvar]);
01590 }
01591 else
01592 {
01593 dbl_EGlpNumOne (minf->lower[bvar]);
01594 rval = dbl_ILLlib_chgbnd (lp, bvar, 'L', dbl_oneLpNum);
01595 ILL_CLEANUP_IF (rval);
01596 rval = dbl_ILLlib_optimize (lp, 0, minf->pinf, DUAL_SIMPLEX, &status, 0, itcnt);
01597 ILL_CLEANUP_IF (rval);
01598 rval = dbl_plunge_work (minf, depth + 1, itcnt);
01599 ILL_CLEANUP_IF (rval);
01600 rval = dbl_ILLlib_chgbnd (lp, bvar, 'L', dbl_zeroLpNum);
01601 ILL_CLEANUP_IF (rval);
01602 dbl_EGlpNumZero (minf->lower[bvar]);
01603 }
01604
01605 CLEANUP:
01606
01607 dbl_EGlpNumClearVar (lpval);
01608 dbl_EGlpNumClearVar (val0);
01609 dbl_EGlpNumClearVar (val1);
01610 dbl_EGlpNumClearVar (int_tol);
01611 ILL_RETURN (rval, "dbl_plunge_work");
01612 }
01613
01614 static int dbl_round_variables (
01615 dbl_mipinfo * minf,
01616 int *count,
01617 double * tol)
01618 {
01619 int rval = 0;
01620 int i, hit = 0;
01621 dbl_lpinfo *lp = minf->lp;
01622 dbl_ILLlpdata *qlp = lp->O;
01623
01624 *count = 0;
01625
01626 for (i = 0; i < qlp->nstruct; i++)
01627 {
01628 if (qlp->intmarker[i])
01629 {
01630 if (dbl_EGlpNumIsNeqq (minf->lower[i], minf->upper[i]))
01631 {
01632 if (dbl_EGlpNumIsLess (minf->x[i], *tol))
01633 {
01634 dbl_EGlpNumZero (minf->upper[i]);
01635 rval = dbl_ILLlib_chgbnd (lp, i, 'U', dbl_zeroLpNum);
01636 ILL_CLEANUP_IF (rval);
01637 hit++;
01638 }
01639 else if (dbl_EGlpNumIsEqual (minf->x[i], dbl_oneLpNum, *tol))
01640 {
01641 dbl_EGlpNumOne (minf->lower[i]);
01642 rval = dbl_ILLlib_chgbnd (lp, i, 'L', dbl_oneLpNum);
01643 ILL_CLEANUP_IF (rval);
01644 hit++;
01645 }
01646 }
01647 }
01648 }
01649 *count = hit;
01650
01651 CLEANUP:
01652
01653 ILL_RETURN (rval, "dbl_round_variables");
01654 }
01655
01656 static void dbl_copy_x (
01657 int nstruct,
01658 double * from_x,
01659 double * to_x)
01660 {
01661 int j;
01662
01663 for (j = 0; j < nstruct; j++)
01664 {
01665 dbl_EGlpNumCopy (to_x[j], from_x[j]);
01666 }
01667 }
01668
01669 static void dbl_init_mipinfo (
01670 dbl_mipinfo * minf)
01671 {
01672 if (minf)
01673 {
01674 minf->depth = 0;
01675 minf->totalnodes = 0;
01676 minf->activenodes = 0;
01677 minf->totalpivots = 0;
01678 minf->lastpivots = 0;
01679 minf->downpen = 0;
01680 minf->uppen = 0;
01681 minf->x = 0;
01682 minf->bestx = 0;
01683 minf->lower = 0;
01684 minf->upper = 0;
01685 minf->lp = 0;
01686 minf->pinf = 0;
01687 minf->head_bbnode.prev = 0;
01688 minf->head_bbnode.next = 0;
01689 minf->que = 0;
01690 minf->branching_rule = dbl_STRONGBRANCH;
01691 minf->watch = 1;
01692 dbl_EGlpNumInitVar (minf->objectivebound);
01693 dbl_EGlpNumInitVar (minf->value);
01694 dbl_EGlpNumCopy (minf->objectivebound, dbl_ILL_MAXDOUBLE);
01695 dbl_EGlpNumCopy (minf->value, dbl_ILL_MAXDOUBLE);
01696 ILLptrworld_init (&minf->ptrworld);
01697 }
01698 }
01699
01700 static void dbl_free_mipinfo (
01701 dbl_mipinfo * minf)
01702 {
01703 int total, onlist;
01704
01705 if (minf)
01706 {
01707 dbl_EGlpNumFreeArray (minf->downpen);
01708 dbl_EGlpNumFreeArray (minf->uppen);
01709 dbl_EGlpNumFreeArray (minf->x);
01710 dbl_EGlpNumFreeArray (minf->bestx);
01711 dbl_EGlpNumFreeArray (minf->lower);
01712 dbl_EGlpNumFreeArray (minf->upper);
01713 bbnode_listfree (&minf->ptrworld, minf->head_bbnode.next);
01714 if (bbnode_check_leaks (&minf->ptrworld, &total, &onlist))
01715 {
01716 fprintf (stderr, "WARNING: %d outstanding bbnodes\n", total - onlist);
01717 }
01718 ILLptrworld_delete (&minf->ptrworld);
01719 dbl_EGlpNumClearVar ((minf->objectivebound));
01720 dbl_EGlpNumClearVar ((minf->value));
01721 memset (minf, 0, sizeof (dbl_mipinfo));
01722
01723 }
01724 }
01725
01726 static void dbl_init_bbnode (
01727 dbl_bbnode * b)
01728 {
01729 if (b)
01730 {
01731 b->next = 0;
01732 b->prev = 0;
01733 b->id = 0;
01734 b->depth = 0;
01735 b->handle = 0;
01736 b->cstat = 0;
01737 b->rstat = 0;
01738 b->rownorms = 0;
01739 b->bound_cnt = 0;
01740 b->bound_indx = 0;
01741 b->lu = 0;
01742 b->bounds = 0;
01743 dbl_EGlpNumInitVar ((b->bound));
01744 dbl_EGlpNumCopy (b->bound, dbl_ILL_MINDOUBLE);
01745 }
01746 }
01747
01748 static void dbl_free_bbnode (
01749 dbl_bbnode * b)
01750 {
01751 if (b)
01752 {
01753 dbl_EGlpNumFreeArray (b->rownorms);
01754 dbl_EGlpNumFreeArray (b->bounds);
01755 ILL_IFFREE (b->cstat, char);
01756 ILL_IFFREE (b->rstat, char);
01757 ILL_IFFREE (b->bound_indx, int);
01758 ILL_IFFREE (b->lu, char);
01759
01760 dbl_EGlpNumClearVar ((b->bound));
01761 memset (b, 0, sizeof (dbl_bbnode));
01762 }
01763 }