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
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
00026 void QuadRef::addCons(cons_obj * c){
00027 cons_list.push_back(c);
00028 }
00029
00030
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
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
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
00093 if(r.size() == 1 && (c->rhs() == 1 || c->rhs() == 0))
00094 return NULL;
00095
00096
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
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
00116 it = hashmap.find(hashkey);
00117 if(force && it == hashmap.end()){
00118
00119 q += IP.add_polynomial(ri->Var * rj->Var * ri->coeff * rj->coeff, false);
00120 }
00121 else if(it != hashmap.end()){
00122
00123 q += (it->second) * (ri->coeff * rj->coeff);
00124 }
00125 else{
00126
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
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
00162 quad_cons->set_qrStatus(NONE);
00163
00164 return quad_cons;
00165 }
00166
00167
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
00179 if(r.size() == 1 && (c->rhs() == 1 || c->rhs() == 0))
00180 return;
00181
00182
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
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
00205 it = hashmap.find(hashkey);
00206 if(force && it == hashmap.end()) {
00207
00208 t += IP.add_polynomial(ri->Var * rj->Var * rj->coeff, false);
00209 }
00210 else if(it != hashmap.end()){
00211
00212 t += (it->second) * rj->coeff;
00213 }
00214 else{
00215
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
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
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
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
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 }