Main Page   Class Hierarchy   Compound List   File List   Contact   Download   Symbolic Constraints   Examples  

subproblem.cc

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 //FIXME prio
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   //check if the objective function is not linear and if sqk2 option is activated
00038   if(GM.monomialinstance != NULL && (GM.get_qr_on_separate() || master_->nLp() == 1)){
00039     cons_obj* cons = NULL;
00040     //check for reformulation (if no new variables have to be added -> reformulate)
00041     switch (c->get_qrStatus()){
00042          //TODO Column Generation
00043          /*case SQK2:
00044             cons = GM.qr->reformulate_SQK2(c, false);
00045             break;
00046          case SQK3:
00047             GM.qr->reformulate_SQK3(c, false);
00048             break;
00049          case SQK2_SQK3:
00050             cons = GM.qr->reformulate_SQK2(c, false);
00051             GM.qr->reformulate_SQK3(c, false);
00052             break;*/
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++;  // function machen und friend entfernen?
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   //FIXME prio
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   //FIXME prio
00156   prio = 0;
00157   initpricing = false;
00158   newvarbuffer=new ABA_BUFFER < ABA_VARIABLE * >(master_,8);
00159 };
00160 
00161 bool
00162 subproblem::feasible ()
00163 {
00164   //cout << master_->nLp () << " LPs\n";
00165   if (master_->nLp () == 1)
00166     return false;
00167 
00168   //  if(!integerFeasible()) return false;
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   //cout << "integer Feasible\n";
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   //if(updateLP==nLP()) return;
00215 
00216   //updateLP=nLp();
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   //int
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   //cout<<t<<" Cosntraints\n";
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   //cout<<counter<<" Vars added"<<endl;
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   //cout<<counter<<" Vars added"<<endl;
00332   return counter;
00333 };
00334 
00335 
00336 void subproblem::remove_variable (var V)
00337 {
00338   /*{\Mop removes a variable for the linear program of the 
00339     current node.} */
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     // This is unsymmetric, since set_coefficient is stored in both
00349 }
00350 
00351 
00352 void subproblem::set_coefficient (var v, cons i, double d)
00353 {
00354   /*{\Mop sets the coefficient for variable $v$ and basic constraint $i$
00355     to $d$ in the LP-Matrix.} */
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   /*{\Mop {\bf better give the possibility to iterate over the variables!}} */
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   /*{\Mop returns the number of active variables in the current node.} */
00372   return ABA_SUB::nVar ();
00373 };
00374 
00375 cons subproblem::get_cons (int i)
00376 {
00377   /*{\Mop {\bf better give the possibility to iterate over the basic
00378     constraints!}} */
00379   if(i>=nCon()) return nil;
00380   return cons (((ABA_Constraint *) ABA_SUB::constraint (i))->Scons ());
00381 };
00382 
00383 int subproblem::ncons ()
00384 {
00385   /*{\Mop returns the number of active basic constraints in the current 
00386     node.} */
00387   return ABA_SUB::nCon ();
00388 };
00389 
00390 
00391 double subproblem::value (var v)
00392 {
00393   /*{\Mop returns the value of |v| of the last solved LP.} */
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   /*{\Mop returns the lower bound of the variable in the current node.} */
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   /*{\Mop returns the upper bound of the variable in the current node.} */
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   /*{\Mop returns the value of |i| of the last solved LP.} */
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 //int subproblem::separate (subproblem &); 
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   // TODO why is primal_heur not= 0 ???
00490   //cout<<&GM<<" "<<GM.primal_heur<<" master and heur\n";
00491   //if (GM.primal_heur != nil)
00492   //  GM.primal_heur->heuristic (*this);
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 //int subproblem::mf_pricing (subproblem &); 
00509 
00510 Varstat subproblem::get_varstat(var v) {
00511 
00512      ABA_FSVARSTAT::STATUS st;
00513      //st = v.Avar_pointer()->fsVarStat()->status();
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   //apply heuristic and test symbolic and basic constraints
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    //FIXME prio
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   //newsub->prio = (variable(((ABA_SETBRANCHRULE*)rule)->variable()))->obj();
00629 
00630   return newsub;
00631 };
00632 /*{\op Diese Funktion erzeugt ein neues Unterproblem. } */
00633 
00634 double subproblem::red_cost(var v) {
00635   /*{\Mop returns the value of |v| of the last solved LP.}*/
00636   return lp()->reco(v.var_pointer()->index());
00637 };
00638 
00639 //TODO remove
00640 /*list_item subproblem::first_sym_constraint_item() const { 
00641   if(sym_constraints.size()==0) return nil;
00642   return GM.myroot->sym_constraints.first(); }
00643 
00644 list_item subproblem::next_sym_constraint_item(list_item i) const {
00645   return GM.myroot->sym_constraints.succ(i);
00646 };
00647 
00648 sym_constraint* subproblem::get_sym_cons(list_item i) {
00649   if(i==nil) return nil;
00650   return GM.myroot->sym_constraints[i];
00651 };*/
00652 
00653 subproblem::~subproblem() {
00654   delete newvarbuffer;
00655 };
Generated on Mon Mar 28 22:03:50 2011 for SCIL by  doxygen 1.6.3