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

quadref.cc

00001 #include <scil/constraints/quadref.h>
00002 #include <boost/unordered_map.hpp>
00003 #include <scil/core/monomial.h>
00004 #include <sstream>
00005 
00006 using namespace SCIL;
00007 using namespace std;
00008 
00009 //inserts a pair of variables with corresponding linearization variable into the hashmap
00010 void QuadRef::hashPair(var& x, var& y, var& l){
00011    int index1, index2;
00012    if(x.var_pointer()->index() < y.var_pointer()->index()){
00013       index1 = x.var_pointer()->index();
00014       index2 = y.var_pointer()->index();
00015    } else {
00016       index1 = y.var_pointer()->index();
00017       index2 = x.var_pointer()->index();
00018    }
00019    std::stringstream ss;
00020    ss<<index1<<'#'<<index2;
00021    string newKey = ss.str();
00022    hashmap.insert(make_pair(newKey, l));
00023 }
00024 
00025 //adds a constraint to the internal constraint list
00026 void QuadRef::addCons(cons_obj * c){
00027    cons_list.push_back(c);
00028 }
00029 
00030 //reformulates every constraint which has a reformulation flag given by the user
00031 void QuadRef::reformulate_forced_constraints(){
00032    std::list<cons_obj*>::reverse_iterator rit;
00033    for(rit=cons_list.rbegin(); rit != cons_list.rend(); ++rit){
00034       cons_obj * cons = NULL;
00035       switch ((*rit)->get_qrStatus()){
00036          case SQK2:
00037             cons = reformulate_SQK2(*rit, true);
00038             break;
00039          case SQK3:
00040             reformulate_SQK3(*rit, true);
00041             break;
00042          case SQK2_SQK3:
00043             cons = reformulate_SQK2(*rit, true);
00044             reformulate_SQK3(*rit, true);
00045             break;
00046          default:
00047             break;
00048       }
00049       if(cons != NULL){
00050          IP.add_basic_constraint(cons, (*rit)->get_Act());
00051       }
00052    }
00053 }
00054 
00055 //checks every constraint in cons_list for reformulation without adding new variables
00056 void QuadRef::check_and_reformulate(){
00057    std::list<cons_obj*>::reverse_iterator rit;
00058    for(rit=cons_list.rbegin(); rit != cons_list.rend(); ++rit){
00059       cons_obj * cons = NULL;
00060       if ((*rit)->get_qrStatus() == CHECK){
00061          switch (IP.get_qrType()){
00062             case SQK2:
00063                cons = reformulate_SQK2(*rit, false);
00064                break;
00065             case SQK3:
00066                reformulate_SQK3(*rit, false);
00067                break;
00068             case SQK2_SQK3:
00069                cons = reformulate_SQK2(*rit, false);
00070                reformulate_SQK3(*rit, false);
00071                break;
00072             default:
00073                break;
00074          }
00075          if (cons != NULL)
00076             IP.add_basic_constraint(cons, (*rit)->get_Act());
00077       }
00078    }
00079 }
00080 
00081 //constructs SQK2 constraint and returns it
00082 cons_obj* QuadRef::reformulate_SQK2(cons_obj* c, bool force) {
00083 
00084    int index1, index2;
00085    string hashkey;
00086    boost::unordered_map<string, var>::iterator it;
00087    
00088    row r, q;
00089    c->non_zero_entries(r);
00090    r.normalize();
00091   
00092    //do not reformulate trivial constraints
00093    if(r.size() == 1 && (c->rhs() == 1 || c->rhs() == 0))
00094       return NULL;
00095 
00096    //construct quadratic constraint
00097    bool cancel = false;
00098    row_entry::list_iterator ri,rj;
00099    foreach(ri, r) {
00100       foreach(rj, r) {
00101          if(ri->Var == rj->Var){
00102             //linear case
00103             q += ri->Var * (ri->coeff * ri->coeff);
00104          } else {
00105             if((ri->Var).var_pointer()->index() < (rj->Var).var_pointer()->index()){
00106                index1 = (ri->Var).var_pointer()->index();
00107                index2 = (rj->Var).var_pointer()->index();
00108             } else {
00109                index1 = (rj->Var).var_pointer()->index();
00110                index2 = (ri->Var).var_pointer()->index();
00111             }
00112             std::stringstream ss;
00113             ss<<index1<<'#'<<index2;
00114             hashkey = ss.str();
00115             //search for already existing linearization variables
00116             it = hashmap.find(hashkey);
00117             if(force && it == hashmap.end()){
00118                //create new linearization variable
00119                q += IP.add_polynomial(ri->Var * rj->Var * ri->coeff * rj->coeff, false);
00120             } 
00121             else if(it != hashmap.end()){
00122                //use existing linearization variable
00123                q += (it->second) * (ri->coeff * rj->coeff);
00124             } 
00125             else{
00126                //if the reformulation is not forced and if no lin. variable is found cancel the reformulation
00127                cancel = true;
00128                break;
00129             }
00130          }       
00131       }
00132       if(cancel)
00133          break;
00134    }
00135 
00136    if(cancel)
00137       return NULL;
00138    
00139    double rhs = c->rhs() * c->rhs();
00140 
00141    q.normalize();
00142 
00143    //correction terms for coeffs < 0
00144    double d = 0.;
00145    foreach(ri, r) {
00146       if( ri->coeff < 0. )
00147          d += ri->coeff;
00148    }
00149    q += -2. * d * r;
00150    rhs += -2. * d * c->rhs();
00151    q.normalize();
00152 
00153    cons_obj* quad_cons;
00154    if( c->sense() == Less)
00155       quad_cons = (q<=rhs);
00156    else if( c->sense() == Greater )
00157       quad_cons = (q>=rhs);
00158    else
00159       quad_cons = (q==rhs);
00160 
00161    //set qrStatus for the reformulated constraint to NONE to avoid second reformulation
00162    quad_cons->set_qrStatus(NONE);
00163 
00164    return quad_cons;
00165 }
00166 
00167 //constructs SQK3 constraints and adds them to the internal list
00168 void QuadRef::reformulate_SQK3(cons_obj* c, bool force) {
00169    int index1, index2;
00170    string hashkey;
00171    boost::unordered_map<string, var>::iterator it;
00172 
00173    row r, s;
00174 
00175    c->non_zero_entries(r);
00176    r.normalize();
00177 
00178    //do not reformulate trivial constraints
00179    if(r.size() == 1 && (c->rhs() == 1 || c->rhs() == 0))
00180       return;
00181 
00182    //construct quadratic constraints
00183    bool cancel;
00184    row_entry::list_iterator ri,rj;
00185    foreach(ri, r) {
00186       row t;
00187       cancel = false;
00188       foreach(rj, r) {
00189          if(ri->Var == rj->Var){
00190             //linear case
00191             t += ri->Var * (ri->coeff - c->rhs());
00192          }
00193          else {
00194             if((ri->Var).var_pointer()->index() < (rj->Var).var_pointer()->index()){
00195                index1 = (ri->Var).var_pointer()->index();
00196                index2 = (rj->Var).var_pointer()->index();
00197             } else {
00198                index1 = (rj->Var).var_pointer()->index();
00199                index2 = (ri->Var).var_pointer()->index();
00200             }
00201             std::stringstream ss;
00202             ss<<index1<<'#'<<index2;
00203             hashkey = ss.str();
00204             //search for already existing linearization variables
00205             it = hashmap.find(hashkey);
00206             if(force && it == hashmap.end()) {
00207                //create new linearization variable
00208                t += IP.add_polynomial(ri->Var * rj->Var * rj->coeff, false);
00209             }
00210             else if(it != hashmap.end()){
00211                //use existing linearization variable
00212                t += (it->second) * rj->coeff;
00213             }
00214             else{
00215                //if the reformulation is not forced and if no lin. variable is found cancel the reformulation
00216                cancel = true;
00217                break;
00218             }
00219          }
00220       }
00221       if(cancel)
00222          continue;
00223       if( ri->Var == r.begin()->Var) {
00224          s -= t;
00225          s += r;
00226          s.normalize();
00227          //add constraint to internal list (for later separation)
00228          if( c->sense() == Less)
00229             lc.push_back(s<=c->rhs());
00230          else if( c->sense() == Greater )
00231             lc.push_back(s>=c->rhs());
00232          else
00233             lc.push_back(s==c->rhs());
00234       }
00235       //add constraint to internal list (for later separation)
00236       if( c->sense() == Less )
00237          lc.push_back(t<=0.);
00238       else if( c->sense() == Greater )
00239          lc.push_back(t>=0.);
00240       else
00241          lc.push_back(t==0.);
00242    }
00243 }
00244 
00245 //separates SQK3 constraints
00246 QuadRef::status QuadRef::standard_separation(subproblem& S) {
00247    std::list<cons_obj*>::iterator c;
00248    int num = 0;
00249    cons_obj* cons;
00250    foreach(c, lc) {
00251       if( (*c)->violation(S) > 1.0e-4 ) {
00252          row r;
00253          (*c)->non_zero_entries(r);
00254          if( (*c)->sense() == Less )
00255             cons = r<=(*c)->rhs();
00256          else if( (*c)->sense() == Greater )
00257             cons = r>=(*c)->rhs();
00258          else
00259             cons = r==(*c)->rhs();
00260          //sets qrStatus to NONE to avoid second reformulation
00261          cons->set_qrStatus(NONE);
00262          S.add_basic_constraint(cons);
00263          num++;
00264       }
00265    }
00266    if( num ) {
00267       return constraint_found;
00268    }
00269 
00270    return no_constraint_found;
00271 }
Generated on Mon Mar 28 22:03:49 2011 for SCIL by  doxygen 1.6.3