00001 #include<scil/global.h>
00002 #include<scil/cons.h>
00003 #include<scil/cons_obj.h>
00004 #include<scil/var_obj.h>
00005 #include<scil/subproblem.h>
00006 #include<scil/aba_constraint.h>
00007 #include<scil/aba_variable.h>
00008 #include<scil/sym_constraint.h>
00009 #include<scil/ilp_problem.h>
00010 #include<scil/primal_heur.h>
00011 #include<scil/row.h>
00012 #include<scil/solution.h>
00013 #include<scil/constraints/quadref.h>
00014
00015 #include<abacus/setbranchrule.h>
00016
00017 using namespace SCIL;
00018
00019 void subproblem::add_sym_constraint (sym_constraint * c)
00020 {
00021 sym_constraints.push_back (c);
00022 }
00023
00024 const
00025 std::string subproblem::configuration(const std::string& s) const {
00026 return GM.configuration(s);
00027 };
00028
00029 void subproblem::configuration(const std::string& s1, const std::string& s2) {
00030 GM.configuration(s1, s2);
00031 return;
00032 };
00033
00034 cons
00035 subproblem::add_basic_constraint (cons_obj * c, Activation a, Validity v)
00036 {
00037
00038 if(GM.monomialinstance != NULL && (GM.get_qr_on_separate() || master_->nLp() == 1)){
00039 cons_obj* cons = NULL;
00040
00041 switch (c->get_qrStatus()){
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053 case CHECK:
00054 switch (GM.get_qrType()){
00055 case SQK2:
00056 cons = GM.qr->reformulate_SQK2(c, false);
00057 break;
00058 case SQK3:
00059 GM.qr->reformulate_SQK3(c, false);
00060 break;
00061 case SQK2_SQK3:
00062 cons = GM.qr->reformulate_SQK2(c, false);
00063 GM.qr->reformulate_SQK3(c, false);
00064 break;
00065 default:
00066 break;
00067 }
00068 break;
00069 default:
00070 break;
00071 }
00072 if(cons != NULL)
00073 _add_basic_constraint (cons, a, v);
00074 }
00075 return _add_basic_constraint (c, a, v);
00076 };
00077
00078 cons
00079 subproblem::_add_basic_constraint (cons_obj * c, Activation a, Validity v)
00080 {
00081 c->init (*this, GM.number_of_constraints(), a, v);
00082 GM.nconss++;
00083 ABA_BUFFER< ABA_CONSTRAINT * > constraint (master_, 1);
00084 constraint.push(c->Acons());
00085 addCons(constraint);
00086 return c;
00087 };
00088
00089 cons
00090 subproblem::add_basic_constraint (cons_sense s, double rhs,
00091 Activation a, Validity v)
00092 {
00093 cons_obj *
00094 c = new cons_obj (s, rhs);
00095 add_basic_constraint (c, a, v);
00096 return c;
00097 };
00098
00099 var subproblem::add_binary_variable (double obj, Activation a)
00100 {
00101 return add_variable(obj, 0, 1, Vartype_Binary, a);
00102 };
00103
00104 var
00105 subproblem::add_variable (double obj,
00106 double lBound, double uBound,
00107 Vartype t, Activation a)
00108 {
00109 var v;
00110
00111 if (initpricing == false)
00112 {
00113 v = new var_obj (obj, lBound, uBound, t);
00114 add_variable (v, a);
00115 }
00116 else
00117 {
00118 if (newvarbuffer->size () == newvarbuffer->number ())
00119 newvarbuffer->realloc (newvarbuffer->size () * 2);
00120 v = new var_obj (obj, lBound, uBound, t);
00121 v.var_pointer ()->init (*this, GM.nvars, a);
00122 newvarbuffer->push (v.Avar_pointer ());
00123 GM.nvars++;
00124 }
00125 return v;
00126 };
00127
00128 void
00129 subproblem::add_variable (var v, Activation a)
00130 {
00131 v.var_pointer ()->init (*this, GM.nvars, a);
00132 if (v.var_pointer () != nil)
00133 {
00134 GM.nvars++;
00135 ABA_BUFFER < ABA_VARIABLE * >p (master_, 1);
00136 p.push (v.Avar_pointer ());
00137 if (addVars (p) == 0)
00138 cout << "Variable not added\n";
00139 }
00140 }
00141
00142 subproblem::subproblem (ABA_MASTER * master):ABA_SUB (master, 0, 0, 0),
00143 GM (*(ILP_Problem *) master_)
00144 {
00145
00146 prio = 0;
00147 initpricing = false;
00148 newvarbuffer= new ABA_BUFFER < ABA_VARIABLE * >(master_,8);
00149 };
00150
00151 subproblem::subproblem (ABA_MASTER * master, ABA_SUB * father,
00152 ABA_BRANCHRULE * branchRule):ABA_SUB (master, father, branchRule),
00153 GM (*(ILP_Problem *) master_)
00154 {
00155
00156 prio = 0;
00157 initpricing = false;
00158 newvarbuffer=new ABA_BUFFER < ABA_VARIABLE * >(master_,8);
00159 };
00160
00161 bool
00162 subproblem::feasible ()
00163 {
00164
00165 if (master_->nLp () == 1)
00166 return false;
00167
00168
00169 solution S;
00170 S.save_solution(*this);
00171 for (int i = 0; i < nVar (); i++)
00172 if (get_var (i).Avar_pointer ()->varType () != ABA_VARTYPE::Continuous)
00173 {
00174 if (fabs (xVal (i) - floor (xVal (i) + 0.5)) > GM.machineEps())
00175 {
00176 return false;
00177 }
00178 S.round_to_integer(get_var(i));
00179 };
00180
00181
00182 update_indices ();
00183 if (!feasible (*this, S))
00184 return false;
00185
00186 GM.updateBestSolution (S);
00187
00188 return true;
00189 }
00190
00191 bool
00192 subproblem::feasible (subproblem & S, solution& Sol)
00193 {
00194
00195 std::list<sym_constraint*>::const_iterator s;
00196 foreach (s, sym_constraints)
00197 {
00198 if ((*s)->feasible (Sol) == sym_constraint::infeasible_solution)
00199 return false;
00200 }
00201
00202 if (father () != 0)
00203 {
00204 if (!((subproblem *) father ())->feasible (S, Sol))
00205 return false;
00206 }
00207
00208 return true;
00209 };
00210
00211 void
00212 subproblem::update_indices ()
00213 {
00214
00215
00216
00217
00218 for (int i = 0; i < nVar (); i++)
00219 {
00220 get_var (i).var_pointer ()->vi = i;
00221 }
00222
00223 for (int i = 0; i < nCon (); i++)
00224 {
00225 ((ABA_Constraint *) constraint (i))->ii = i;
00226 }
00227 };
00228
00229 int
00230 subproblem::separate ()
00231 {
00232 if (master_->nLp () == 1)
00233 {
00234 std::list<sym_constraint*>::iterator c;
00235 foreach (c, sym_constraints) (*c)->init (*this);
00236
00237 add_basic_constraint((row) 0 <= 0);
00238
00239 return 1;
00240 }
00241
00242 update_indices ();
00243 return separate (*this);
00244 };
00245
00246 int
00247 subproblem::separate (subproblem & S)
00248 {
00249
00250 t = 0;
00251
00252 sym_constraint_iterator s;
00253 sym_constraint::status rs;
00254 foreach (s, sym_constraints) if(t!=-1)
00255 {
00256 rs=(*s)->standard_separation(S);
00257 if (rs == sym_constraint::constraint_found) t++;
00258 if (rs == sym_constraint::fathom) t=-1;
00259 };
00260
00261 int l;
00262 if ((father () != 0) && (t!=-1))
00263 {
00264 l = ((subproblem *) father ())->separate (S);
00265 if(l==-1) return -1; else t+=l;
00266 }
00267
00268 if(t==-1) {
00269 t=1; add_basic_constraint((row) get_var(0) <= -1);
00270 };
00271
00272 return t;
00273 };
00274
00275 int
00276 subproblem::pricing ()
00277 {
00278 update_indices ();
00279 int
00280 i;
00281 if (lp ()->infeasible ())
00282 {
00283 i = mf_pricing (*this);
00284 }
00285 else
00286 {
00287 i = pricing (*this);
00288 }
00289 cout << i << " Vars added\n";
00290 return i;
00291 };
00292
00293 int
00294 subproblem::mf_pricing (subproblem & S)
00295 {
00296 int
00297 counter = 0;
00298
00299 sym_constraint_iterator p;
00300 foreach (p, sym_constraints)
00301 {
00302 if ((*p)->mf_pricing (S) == sym_constraint::variable_found)
00303 counter++;
00304 }
00305
00306 if (father () != 0)
00307 {
00308 counter += ((subproblem *) father ())->mf_pricing (S);
00309 }
00310
00311 return counter;
00312 };
00313
00314 int
00315 subproblem::pricing (subproblem & S)
00316 {
00317 int
00318 counter = 0;
00319
00320 sym_constraint_iterator p;
00321 foreach (p, sym_constraints)
00322 {
00323 if ((*p)->LP_pricing (S) == sym_constraint::variable_found)
00324 counter++;
00325 }
00326
00327 if (father () != 0)
00328 {
00329 counter += ((subproblem *) father ())->pricing (S);
00330 }
00331
00332 return counter;
00333 };
00334
00335
00336 void subproblem::remove_variable (var V)
00337 {
00338
00339
00340 removeVar (V.var_pointer ()->index ());
00341 };
00342
00343
00344 double subproblem::get_coeff (var v, cons i)
00345 {
00346 return v.var_pointer ()->coeff (i.cons_pointer ()->Acons ()) +
00347 i.cons_pointer ()->coeff (v.var_pointer ());
00348
00349 }
00350
00351
00352 void subproblem::set_coefficient (var v, cons i, double d)
00353 {
00354
00355
00356 v.var_pointer ()->set (i.cons_pointer (), d);
00357 i.cons_pointer ()->set (v.var_pointer (), d);
00358 };
00359
00360
00361
00362 var subproblem::get_var (int i)
00363 {
00364
00365 if(i>=nVar()) return nil;
00366 return var (((ABA_Variable *) ABA_SUB::variable (i))->SVar ());
00367 };
00368
00369 int subproblem::nVar () const
00370 {
00371
00372 return ABA_SUB::nVar ();
00373 };
00374
00375 cons subproblem::get_cons (int i)
00376 {
00377
00378
00379 if(i>=nCon()) return nil;
00380 return cons (((ABA_Constraint *) ABA_SUB::constraint (i))->Scons ());
00381 };
00382
00383 int subproblem::ncons ()
00384 {
00385
00386
00387 return ABA_SUB::nCon ();
00388 };
00389
00390
00391 double subproblem::value (var v)
00392 {
00393
00394 if(v==nil) return 1;
00395 return xVal (v.var_pointer ()->index ());
00396 };
00397
00398 double subproblem::value(row& r) {
00399 row_entry::list_constiterator re;
00400 double d=0;
00401 foreach(re, r) d+=re->coeff*value(re->Var);
00402 return d;
00403 };
00404
00405 double subproblem::lower_bound (var v)
00406 {
00407
00408 if (fsVarStat (v.var_pointer ()->index ())->status () !=
00409 ABA_FSVARSTAT::Free)
00410 {
00411 return myvalue (v.var_pointer ()->index ());
00412 }
00413 return lBound (v.var_pointer ()->index ());
00414 }
00415
00416
00417 double subproblem::upper_bound (var v)
00418 {
00419
00420 if (fsVarStat (v.var_pointer ()->index ())->fixedOrSet ())
00421 {
00422 return myvalue (v.var_pointer ()->index ());
00423 }
00424 return uBound (v.var_pointer ()->index ());
00425 }
00426
00427 double subproblem::value (cons i, as_what as) {
00428
00429 if (i.cons_pointer () == nil)
00430 {
00431 cout << "nil basic constraint\n"; return 0;}
00432 double d = yVal (i.cons_pointer ()->Acons ()->index ());
00433 if (as == as_is) return d;
00434 if ((as == as_max) && (GM.opt_sense () == Optsense_Max)) return d;
00435 if ((as == as_min) && (GM.opt_sense () == Optsense_Min)) return d;
00436 return -d;
00437 }
00438
00439
00440
00441
00442
00443 void subproblem::activate (subproblem & S)
00444 {
00445 sym_constraint_iterator s;
00446
00447 foreach (s, sym_constraints)
00448 {
00449 (*s)->open_subproblem (S);
00450 }
00451
00452 if (father () != 0)
00453 {
00454 ((subproblem *) father ())->activate (S);
00455 }
00456
00457 }
00458
00459 void subproblem::activate ()
00460 {
00461 activate (*this);
00462 };
00463
00464
00465 void subproblem::deactivate (subproblem & S)
00466 {
00467 sym_constraint_iterator s;
00468 foreach (s, sym_constraints)
00469 {
00470 (*s)->close_subproblem (S);
00471 };
00472 if (father () != 0)
00473 {
00474 ((subproblem *) father ())->deactivate (S);
00475 }
00476 };
00477
00478
00479 bool subproblem::save_solution(solution& s) {
00480 return GM.save_solution(s);
00481 };
00482
00483 void subproblem::deactivate ()
00484 {
00485 deactivate (*this);
00486
00487
00488
00489
00490
00491
00492
00493 };
00494
00495 double subproblem::myvalue (int i)
00496 {
00497 if (fsVarStat (i)->status () == ABA_FSVARSTAT::FixedToLowerBound)
00498 return lBound (i);
00499 if (fsVarStat (i)->status () == ABA_FSVARSTAT::SetToLowerBound)
00500 return lBound (i);
00501 if (fsVarStat (i)->status () == ABA_FSVARSTAT::FixedToUpperBound)
00502 return uBound (i);
00503 if (fsVarStat (i)->status () == ABA_FSVARSTAT::SetToUpperBound)
00504 return uBound (i);
00505 return fsVarStat (i)->value ();
00506 }
00507
00508
00509
00510 Varstat subproblem::get_varstat(var v) {
00511
00512 ABA_FSVARSTAT::STATUS st;
00513
00514 st = fsVarStat(v.var_pointer()->index())->status();
00515 switch( st ) {
00516 case ABA_FSVARSTAT::Free:
00517 return Free;
00518 case ABA_FSVARSTAT::SetToUpperBound:
00519 return SetToUpperBound;
00520 case ABA_FSVARSTAT::SetToLowerBound:
00521 return SetToLowerBound;
00522 case ABA_FSVARSTAT::Set:
00523 return Set;
00524 case ABA_FSVARSTAT::FixedToUpperBound:
00525 return FixedToUpperBound;
00526 case ABA_FSVARSTAT::FixedToLowerBound:
00527 return FixedToLowerBound;
00528 case ABA_FSVARSTAT::Fixed:
00529 return Fixed;
00530 }
00531 }
00532
00533
00534
00535 void subproblem::fixByLogImp(ABA_BUFFER<int>& variable,
00536 ABA_BUFFER< ABA_FSVARSTAT * > & status ) {
00537
00538 implicator *im = GM.implic;
00539 if(!im) return;
00540
00541 std::list< std::pair<var, double> > fv;
00542 variable.clear();
00543 status.clear();
00544 im->implicate(*this, fv, true);
00545 if( !fv.empty() ) {
00546 std::list< pair<var,double> >::const_iterator tt;
00547 foreach(tt, fv) {
00548 variable.push(tt->first.var_pointer()->index());
00549 if( tt->second < .001 ) {
00550 status.push(new ABA_FSVARSTAT(master(), ABA_FSVARSTAT::FixedToLowerBound));
00551 }
00552 else if( tt->second > .999 ) {
00553 cerr << "fixing to 1" << endl;
00554 status.push(new ABA_FSVARSTAT(master(), ABA_FSVARSTAT::FixedToUpperBound));
00555 }
00556 else {
00557 cerr << "cannot fix to " << tt->second << endl;
00558 exit(Fatal);
00559 }
00560 }
00561 }
00562 return;
00563 }
00564
00565 void subproblem::setByLogImp(ABA_BUFFER<int>& variable,
00566 ABA_BUFFER< ABA_FSVARSTAT * > & status ) {
00567
00568 implicator *im = GM.implic;
00569 if(!im) return;
00570
00571 std::list< pair<var, double> > fv;
00572 variable.clear();
00573 status.clear();
00574 im->implicate(*this, fv, false);
00575 if( !fv.empty() ) {
00576 std::list< pair<var,double> >::const_iterator tt;
00577 foreach(tt, fv) {
00578 variable.push(tt->first.var_pointer()->index());
00579 if( tt->second < .001 ) {
00580 status.push(new ABA_FSVARSTAT(master(), ABA_FSVARSTAT::SetToLowerBound));
00581 }
00582 else if( tt->second > .999 ) {
00583 cerr << "setting to 1" << endl;
00584 status.push(new ABA_FSVARSTAT(master(), ABA_FSVARSTAT::SetToUpperBound));
00585 }
00586 else {
00587 cerr << "cannot set to " << tt->second << endl;
00588 exit(Fatal);
00589 }
00590 }
00591 }
00592 return;
00593 }
00594
00595 int subproblem::improve (double &primalValue) {
00596 primal_heuristic *ph = GM.primal_heur;
00597 if(!ph) return 0;
00598
00599 solution newSol;
00600 double pb = GM.primalBound();
00601
00602
00603 if( ph->heuristic(*this, newSol) && feasible(*this, newSol) ) {
00604 for(int i=0; i<this->ncons(); i++) {
00605 cons_obj* cons = get_cons(i).cons_pointer();
00606 if (cons->violation(*this) > GM.eps()) return 0;
00607 }
00608 if( save_solution(newSol) ) {
00609 primalValue = GM.primalBound();
00610 return 1;
00611 }
00612 }
00613 return 0;
00614 }
00615
00616 double* subproblem::MxVal ()
00617 {
00618 return xVal_;
00619 };
00620
00621 ABA_SUB * subproblem::generateSon (ABA_BRANCHRULE * rule)
00622 {
00623
00624 subproblem* newsub = new subproblem (master_, this, rule);
00625 newsub->prio = prio;
00626 if( rule->branchOnSetVar() && ((ABA_SETBRANCHRULE*)rule)->setToUpperBound() )
00627 newsub->prio += 1;
00628
00629
00630 return newsub;
00631 };
00632
00633
00634 double subproblem::red_cost(var v) {
00635
00636 return lp()->reco(v.var_pointer()->index());
00637 };
00638
00639
00640
00641
00642
00643
00644
00645
00646
00647
00648
00649
00650
00651
00652
00653 subproblem::~subproblem() {
00654 delete newvarbuffer;
00655 };