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
00012
00013
00014 #define SMALL(A,B) ((A) < (B) && (A) > -(B))
00015
00016
00017 using namespace SCIL;
00018
00019 int main(int argc, char **argv) {
00020
00021 int num_vars;
00022 int num_edges;
00023 int num_sams;
00024
00025 int *head,*tail;
00026 double **coeff;
00027 double *m;
00028
00029 double cuteps = 0;
00030 double cst;
00031
00032
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
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
00089
00090 ILP_Problem IP(Optsense_Min);
00091
00092 var *lvar = new var[num_vars];
00093
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 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
00124
00125 IP.optimize();
00126
00127
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
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
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
00162
00163 return 0;
00164 }