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

QuadFit.cc

00001 
00002 #include<scil/scil.h>
00003 #include<scil/core/monomial.h>
00004 #include<list>
00005 
00006 #include<iostream>
00007 #include<stdio.h>
00008 #include<vector>
00009 
00010 #define SHIFT 0.5
00011 // when deleting a monomial X*Y with coefficient CF, 
00012 // increase coefficients of X and Y by SHIFT*CF each
00013 
00014 #define SMALL(A,B) ((A) < (B) && (A) > -(B))
00015 // is |A| < B ?
00016 
00017 using namespace SCIL;
00018 
00019 int main(int argc, char **argv) {
00020 
00021   int num_vars;       // number of variables (positions)
00022   int num_edges;      // number of edges (pairs with interaction)
00023   int num_sams;       // number of scenarios
00024 
00025   int *head,*tail;    // end nodes of edges
00026   double **coeff;     // coefficients
00027   double *m;          // target values
00028 
00029   double cuteps = 0;  // delete monomials with smaller coefficients
00030   double cst;         // constant part of the objective function
00031 
00032   // read data
00033 
00034   if(argc > 1) cuteps = atof(argv[1]);
00035 
00036   cin>>num_vars>>num_edges>>num_sams;
00037 
00038   head = new int[num_edges];
00039   tail = new int[num_edges];
00040   coeff = new double*[num_edges];
00041   for(int e = 0; e < num_edges; e++) coeff[e] = new double[num_sams];
00042   for(int e = 0; e < num_edges; e++) {
00043     cin>>head[e]>>tail[e];
00044     head[e]--;
00045     tail[e]--;
00046     for(int s = 0; s < num_sams; s++) cin>>coeff[e][s];
00047   }
00048 
00049   cst = 0;
00050   m = new double[num_sams];
00051   for(int s = 0; s < num_sams; s++) {
00052     cin>>m[s];
00053     cst += m[s]*m[s];
00054   }
00055 
00056   // determine coefficients for linear and quadratic monomials
00057 
00058   double *lobj = new double[num_vars];
00059   double *qobj = new double[num_edges];
00060 
00061   double cf;
00062   for(int v = 0; v < num_vars; v++) lobj[v] = 0;
00063   for(int e = 0; e < num_edges; e++) {
00064     cf = 0;
00065     for(int s = 0; s < num_sams; s++) {
00066       cf -= 2.0*m[s]*coeff[e][s];
00067       cf += coeff[e][s]*coeff[e][s];
00068     }
00069     qobj[e] = cf;
00070   }
00071   for(int e1 = 0; e1 < num_edges-1; e1++) {
00072     for(int e2 = e1+1; e2 < num_edges; e2++) {
00073       cf = 0;
00074       for(int s = 0; s < num_sams; s++) cf += 2.0*coeff[e1][s]*coeff[e2][s];
00075       if(SMALL(cf,cuteps)) {
00076         qobj[e1] += SHIFT*cf;
00077         qobj[e2] += SHIFT*cf;
00078       }
00079     }
00080   }
00081   for(int e = 0; e < num_edges; e++) {
00082     if(SMALL(qobj[e],cuteps)) {
00083       lobj[head[e]] += SHIFT*qobj[e];
00084       lobj[tail[e]] += SHIFT*qobj[e];
00085     }
00086   }
00087 
00088   // set up polynomial problem
00089   
00090   ILP_Problem IP(Optsense_Min);
00091 
00092   var *lvar = new var[num_vars];
00093   //var *qvar = new var[num_edges];
00094   std::vector<var> mon(4);
00095 
00096   for(int v = 0; v < num_vars; v++) 
00097     lvar[v] = IP.add_binary_variable(lobj[v]);
00098   for(int e = 0; e < num_edges; e++) {
00099     if(!SMALL(qobj[e],cuteps))
00100       /*qvar[e] = */ IP.add_polynomial(lvar[head[e]]*lvar[tail[e]]*qobj[e]);
00101   }
00102   monomial *nm;
00103   std::list<monomial*> lm;
00104   for(int e1 = 0; e1 < num_edges-1; e1++) {
00105     for(int e2 = e1+1; e2 < num_edges; e2++) {
00106       cf = 0;
00107       for(int s = 0; s < num_sams; s++) cf += 2.0*coeff[e1][s]*coeff[e2][s];
00108       if(!SMALL(cf,cuteps)) {
00109         mon[0] = lvar[head[e1]];
00110         mon[1] = lvar[tail[e1]];
00111         mon[2] = lvar[head[e2]];
00112         mon[3] = lvar[tail[e2]];
00113         nm = new monomial(cf,mon);
00114         IP.add_polynomial(*nm);
00115         lm.push_back(nm);
00116       }
00117     }
00118   }
00119 
00120   delete[] lobj;
00121   delete[] qobj;
00122 
00123   // optimize
00124 
00125   IP.optimize();
00126 
00127   // print solution
00128 
00129   bool *opt = new bool[num_vars];
00130   for(int v = 0; v < num_vars; v++)
00131     opt[v] = (IP.get_solution(lvar[v]) > 0.5);
00132   double robj = 0;
00133   for(int s = 0; s < num_sams; s++) {
00134     cf = m[s];
00135     for(int e = 0; e < num_edges; e++) 
00136       if(opt[head[e]] && opt[tail[e]]) cf -= coeff[e][s];
00137     robj += cf*cf;
00138   }
00139   cout<<"solution:";
00140   for(int v = 0; v < num_vars; v++) if(opt[v]) cout<<" "<<v;
00141   cout<<endl;
00142   cout<<"approximate objective value: "<<IP.get_optimum()+cst<<endl; 
00143   cout<<"real objective value:        "<<robj<<endl;
00144  
00145   // free
00146   list<monomial*>::iterator it;
00147   for( it = lm.begin(); it != lm.end(); it++ )
00148   delete (*it);
00149 
00150   delete[] opt;
00151          
00152   delete[] lvar;
00153   //delete[] qvar;
00154 
00155   delete[] head;
00156   delete[] tail;
00157   for(int e = 0; e < num_edges; e++) delete[] coeff[e];
00158   delete[] coeff;
00159   delete[] m;
00160 
00161   // return
00162 
00163   return 0;
00164 }
Generated on Mon Mar 28 22:03:49 2011 for SCIL by  doxygen 1.6.3