00001
00002
00003
00004
00005
00006
00007
00008
00009
00010 #include <stdio.h>
00011 #include <string.h>
00012 #include <OsiCuts.hpp>
00013 #include <OsiSolverInterface.hpp>
00014 #include <CoinMpsIO.hpp>
00015 #include <populate.hpp>
00016
00017 #define indexQ(i,j,n) ((n) + (i) * (2*(n)-1-(i)) / 2 + (j))
00018
00019
00020 int getFirstIdx(const char *colName);
00021 int getSecondIdx(const char *colName);
00022 double _mul(double a, double b, double infinity);
00023
00024
00025 int populateProblem (
00026 const char *filename,
00027 int *nptr,
00028 int *tptr,
00029 int *consptr,
00030 double **bptr,
00031 double **cptr,
00032 double ***Qptr,
00033 double *constantptr,
00034 double ***origmatptr,
00035 double **origrhsptr,
00036 char **origsenseptr,
00037 double **xlbptr,
00038 double **xubptr,
00039 double **ylbptr,
00040 double **yubptr,
00041 OsiSolverInterface *si ) {
00042
00043
00044
00045
00046
00047
00048 double _constant = 0.0;
00049 char tempstring[1024];
00050 FILE *mpsfile = NULL;
00051 mpsfile = fopen(filename,"r");
00052 if (mpsfile != NULL) {
00053 fscanf(mpsfile,"%s",tempstring);
00054 fscanf(mpsfile,"%s",tempstring);
00055 if (char *tempstring2 = strstr(tempstring,"@objconst=")) {
00056 _constant= - atof(tempstring2+10);
00057 }
00058 fclose(mpsfile);
00059 } else {
00060 printf("File %s does not exist !\n",filename);
00061 return 1;
00062 }
00063
00064
00065 *constantptr = _constant;
00066
00067 CoinMpsIO cmpsio;
00068 cmpsio.messageHandler()->setLogLevel(0);
00069 cmpsio.readMps(filename,"mps");
00070
00071 const CoinPackedMatrix *problemMatrixByCol = cmpsio.getMatrixByCol();
00072
00073 const double *rowlb,*rowub,*objcoeff,*collb,*colub;
00074
00075 rowlb = cmpsio.getRowLower();
00076 rowub = cmpsio.getRowUpper();
00077 objcoeff = cmpsio.getObjCoefficients();
00078 collb = cmpsio.getColLower();
00079 colub = cmpsio.getColUpper();
00080
00081
00082
00083 int origVars=0;
00084 for (int i=0;i<cmpsio.getNumCols();i++) {
00085 if (getSecondIdx(cmpsio.columnName(i)) == -1)
00086 origVars++;
00087 }
00088
00089
00090 bool *inBilinear;
00091 inBilinear = new bool[origVars];
00092 for (int i=0;i<origVars;i++)
00093 inBilinear[i] = false;
00094
00095 int origBilinearVars = 0;
00096 int elimVars = 0;
00097 for(int i=0;i<cmpsio.getNumCols();i++) {
00098 if (getSecondIdx(cmpsio.columnName(i)) >= 0) {
00099 int firstIdx = getFirstIdx(cmpsio.columnName(i));
00100 int secondIdx = getSecondIdx(cmpsio.columnName(i));
00101 if ((problemMatrixByCol->getVector(i).getNumElements() > 0) ||
00102 (objcoeff[i] != 0.0)) {
00103
00104 inBilinear[firstIdx] = true;
00105 inBilinear[secondIdx] = true;
00106 origBilinearVars++;
00107 }
00108 else
00109 elimVars++;
00110 }
00111 }
00112
00113 int n = 0;
00114 int t = 0;
00115 for(int i=0;i<origVars;i++){
00116 if (inBilinear[i])
00117 n++;
00118 else
00119 t++;
00120 }
00121
00122 int N = n*(n+3)/2;
00123 int totVars = N + t;
00124 assert(origVars = (elimVars + n + t +origBilinearVars));
00125
00126
00127 #ifdef TRACE
00128 printf("populate:: MPS file : vars=%d cons=%d\n",cmpsio.getNumCols(),cmpsio.getNumRows());
00129 if (elimVars)
00130 printf("populate:: eliminated %d bilinear vars (0.0 obj coefficient AND empty column)\n",elimVars);
00131 printf("populate:: original problem : n=%d t=%d bilinearVars=%d total=%d\n",
00132 n,t,origBilinearVars, n+t+origBilinearVars);
00133 printf("populate:: sdp formulation : n=%d N=n*(n+3)/2=%d t=%d totVars=(N+t)=%d\n",n,N,t,totVars);
00134 #endif
00135
00136
00137 int *lookupIdx = new int[n+t];
00138 for(int i=0;i<n+t;i++)
00139 lookupIdx[i] = -1;
00140 int xcnt = 0;
00141 int ycnt = 0;
00142 for(int i=0;i<cmpsio.getNumCols();i++) {
00143 int firstIdx = getFirstIdx(cmpsio.columnName(i));
00144 int secondIdx = getSecondIdx(cmpsio.columnName(i));
00145 if (secondIdx == -1){
00146 if (inBilinear[firstIdx]) {
00147 lookupIdx[firstIdx] = xcnt;
00148 xcnt++;
00149 }
00150 else {
00151 lookupIdx[firstIdx] = ycnt;
00152 ycnt++;
00153 }
00154 }
00155 }
00156 #ifdef CHECK
00157 for(int i=0;i<n+t;i++)
00158 if(lookupIdx[i] == -1)
00159 printf("populate::WARNING: variable x_%d not found in the original problem\n",i);
00160 #endif
00161
00162
00163 double *lb,*ub;
00164 lb = new double[totVars];
00165 ub = new double[totVars];
00166 for(int i=0;i<totVars;i++) {
00167 lb[i] = - si->getInfinity();
00168 ub[i] = si->getInfinity();
00169 }
00170
00171
00172 for (int i=totVars; i--;)
00173 si -> addCol (0, NULL, NULL, - si->getInfinity(), si->getInfinity(), 0);
00174
00175
00176 int *indices;
00177 indices = new int[N+t];
00178
00179 #define OBJ_FUNCTION_MULTIPLIER -1.0
00180 for(int i=0;i<cmpsio.getNumCols();i++) {
00181 int firstIdx = getFirstIdx(cmpsio.columnName(i));
00182 int secondIdx = getSecondIdx(cmpsio.columnName(i));
00183 if (secondIdx >= 0){
00184 if ((inBilinear[firstIdx]) && (inBilinear[secondIdx])) {
00185 indices[i] = indexQ(lookupIdx[firstIdx],lookupIdx[secondIdx],n);
00186 }
00187 else
00188 indices[i] = -1;
00189 }
00190 else {
00191 if (inBilinear[firstIdx]) {
00192 indices[i] = lookupIdx[i];
00193 }
00194 else {
00195 indices[i] = N + lookupIdx[i];
00196 }
00197 }
00198 if (indices[i] >= 0) {
00199 lb[indices[i]] = collb[i];
00200 ub[indices[i]] = colub[i];
00201 si->setColLower(indices[i],collb[i]);
00202 si->setColUpper(indices[i],colub[i]);
00203 si->setObjCoeff(indices[i], OBJ_FUNCTION_MULTIPLIER * objcoeff[i]);
00204 }
00205 }
00206
00207
00208
00209
00210 double min;
00211 double max;
00212 for(int i=0;i<n;i++)
00213 for(int j=i;j<n;j++) {
00214 min = + si->getInfinity();
00215 max = - si->getInfinity();
00216 double tempval;
00217 tempval = _mul(lb[i],lb[j],si->getInfinity());
00218 if (tempval < min)
00219 min = tempval;
00220 tempval = _mul(lb[i],ub[j],si->getInfinity());
00221 if (tempval < min)
00222 min = tempval;
00223 tempval = _mul(ub[i],lb[j],si->getInfinity());
00224 if (tempval < min)
00225 min = tempval;
00226 tempval = _mul(ub[i],ub[j],si->getInfinity());
00227 if (tempval < min)
00228 min = tempval;
00229
00230 tempval = _mul(lb[i],lb[j],si->getInfinity());
00231 if (tempval > max)
00232 max = tempval;
00233 tempval = _mul(lb[i],ub[j],si->getInfinity());
00234 if (tempval > max)
00235 max = tempval;
00236 tempval = _mul(ub[i],lb[j],si->getInfinity());
00237 if (tempval > max)
00238 max = tempval;
00239 tempval = _mul(ub[i],ub[j],si->getInfinity());
00240 if (tempval > max)
00241 max = tempval;
00242
00243
00244
00245
00246
00247
00248
00249 #ifdef ZERO_LB_DIAGONAL
00250 if (i==j) {
00251 if (min < 0)
00252 min = 0;
00253 }
00254
00255 #endif
00256 si->setColLower(indexQ(i,j,n),min);
00257 si->setColUpper(indexQ(i,j,n),max);
00258 }
00259
00260 OsiCuts cs;
00261
00262
00263
00264 const CoinPackedMatrix *problemMatrixByRow = cmpsio.getMatrixByRow();
00265 for(int i=0;i<cmpsio.getNumRows();i++) {
00266 CoinPackedVector currRow = (CoinPackedVector) problemMatrixByRow->getVector(i);
00267 int *currRowIdx = (int*) currRow.getIndices();
00268 double *currRowElem = (double*) currRow.getElements();
00269 OsiRowCut *cut = new OsiRowCut;
00270
00271 double *newRowElem = new double[currRow.getNumElements()];
00272 int *newRowIdx = new int[currRow.getNumElements()];
00273
00274 for (int j=0;j<currRow.getNumElements();j++) {
00275 assert(indices[currRowIdx[j]] != -1);
00276 newRowIdx[j]=indices[currRowIdx[j]];
00277 newRowElem[j]=currRowElem[j];
00278 }
00279 cut->setRow (currRow.getNumElements(), newRowIdx, newRowElem);
00280 cut->setLb(rowlb[i]);
00281 cut->setUb(rowub[i]);
00282 delete [] newRowElem;
00283 delete [] newRowIdx;
00284
00285 cs.insert(cut);
00286 }
00287
00288
00289
00290 int idx;
00291 #ifdef RLT_CUTS
00292 #ifndef RLT_SEPARATION
00293
00294
00295 for(int i=0;i<n;i++) {
00296 idx = indexQ(i,i,n);
00297
00298 if (lb[i] != 0.0)
00299 createCut(cs,lb[i]*lb[i], -1,idx,-1.0,i,2 * lb[i]);
00300
00301
00302
00303 if (ub[i] != 0.0)
00304 createCut(cs,ub[i]*ub[i], -1,idx,-1.0,i,2 * ub[i]);
00305
00306
00307
00308 createCut(cs,-lb[i]*ub[i],-1,idx, 1.0,i, - lb[i]-ub[i] );
00309
00310
00311 }
00312
00313 for(int i=0;i<n;i++)
00314 for(int j=i+1;j<n;j++) {
00315 idx = indexQ(i,j,n);
00316
00317 createCut(cs,lb[i]*lb[j],-1,idx,-1.0,i,lb[j],j,lb[i]);
00318
00319 createCut(cs,ub[i]*ub[j],-1,idx,-1.0,i,ub[j],j,ub[i]);
00320
00321 createCut(cs,-lb[i]*ub[j],-1,idx,1.0,i,-ub[j],j,-lb[i]);
00322
00323 createCut(cs,-ub[i]*lb[j],-1,idx,1.0,i,-lb[j],j,-ub[i]);
00324
00325 }
00326 #endif // #RLT_SEPARATION
00327 #endif //#ifdef RLT_CUTS
00328
00329
00330
00331 si -> applyCuts (cs);
00332
00333 si -> setObjSense(-1);
00334
00335 #ifdef TRACE_RLT_MPS
00336
00337
00338 char **varNames = new char*[N+t];
00339 for(int j=0;j<N+t;j++)
00340 varNames[j] = new char[20];
00341
00342 for (int i=0; i<n; i++) {
00343 sprintf(varNames[i],"x_%d",i);
00344 }
00345 for (int i=0; i<n; i++) {
00346 sprintf(varNames[indexQ (i,i,n)],"x_%d_%d",i,i);
00347 for (int j=i+1; j<n; j++) {
00348 sprintf(varNames[indexQ (i,j,n)],"x_%d_%d",i,j);
00349 }
00350 }
00351 for(int i=0; i<t; i++)
00352 sprintf(varNames[N+i],"y_%d",i);
00353
00354 char **conNames = new char*[si->getNumRows()];
00355 for (int j=0;j<si->getNumRows();j++)
00356 conNames[j] = new char[20];
00357
00358 for(int j=0;j<cmpsio.getNumRows();j++)
00359 sprintf(conNames[j],"orig_%d",j);
00360 for(int j=cmpsio.getNumRows();j<si->getNumRows();j++)
00361 sprintf(conNames[j],"rlt_%d",j-cmpsio.getNumRows());
00362
00363 si->writeMpsNative("rlt.mps",
00364 const_cast <const char **> (conNames),
00365 const_cast <const char **> (varNames),
00366 0,1,1.0);
00367
00368 for(int j=0;j<N+t;j++)
00369 delete [] varNames[j];
00370 delete [] varNames;
00371 for(int j=0;j<si->getNumRows();j++)
00372 delete [] conNames[j];
00373 delete [] conNames;
00374 #endif
00375
00376 delete [] lookupIdx;
00377 delete [] inBilinear;
00378
00379 delete [] lb;
00380 delete [] ub;
00381
00382 delete [] indices;
00383
00384
00385
00386
00387
00388
00389 double *b;
00390 double *c;
00391 double **Q;
00392 double **origmat;
00393 double *origrhs;
00394 char *origsense;
00395 double *xlb;
00396 double *xub;
00397 double *ylb;
00398 double *yub;
00399 int cons;
00400 cons = cmpsio.getNumRows();
00401 *consptr = cons;
00402
00403 *nptr = n;
00404 *tptr = t;
00405
00406 const double *tmp_objcoeff = si->getObjCoefficients();
00407 const double *tmp_lb = si->getColLower();
00408 const double *tmp_ub = si->getColUpper();
00409 const double *tmp_rhs = si->getRightHandSide();
00410 const char *tmp_sense = si->getRowSense();
00411
00412 xlb = new double[n+t];
00413 *xlbptr = xlb;
00414 xub = new double[n+t];
00415 *xubptr = xub;
00416 ylb = new double[n+t];
00417 *ylbptr = ylb;
00418 yub = new double[n+t];
00419 *yubptr = yub;
00420
00421 b = new double[n];
00422 *bptr = b;
00423 for (int i=0; i<n; i++) {
00424 b[i]=tmp_objcoeff[i];
00425 xlb[i] = tmp_lb[i];
00426 xub[i] = tmp_ub[i];
00427 }
00428
00429 Q = new double*[n];
00430 for (int i=0; i<n; i++)
00431 Q[i] = new double[n];
00432 *Qptr = Q;
00433 for (int i=0; i<n; i++)
00434 for (int j=i; j<n; j++) {
00435 Q[i][j] = tmp_objcoeff[indexQ(i,j,n)] / 2;
00436 Q[j][i] = tmp_objcoeff[indexQ(i,j,n)] / 2;
00437
00438
00439
00440
00441 }
00442
00443
00444 c = new double[t];
00445 *cptr = c;
00446 for (int i=0;i<t;i++) {
00447 c[i]=tmp_objcoeff[i+N];
00448 ylb[i] = tmp_lb[i+N];
00449 yub[i] = tmp_ub[i+N];
00450 }
00451
00452
00453 origmat = new double*[cmpsio.getNumRows()];
00454 for (int i=0;i<cmpsio.getNumRows();i++)
00455 origmat[i] = new double[N + t];
00456 for (int i=0;i<cmpsio.getNumRows();i++)
00457 for(int j=0;j<N+t;j++)
00458 origmat[i][j] = 0.0;
00459 *origmatptr = origmat;
00460
00461 origrhs = new double[cmpsio.getNumRows()];
00462 origsense = new char[cmpsio.getNumRows()];
00463 for (int i=0;i<cmpsio.getNumRows();i++) {
00464 origrhs[i]= tmp_rhs[i];
00465 origsense[i] = tmp_sense[i];
00466 }
00467 *origrhsptr = origrhs;
00468 *origsenseptr = origsense;
00469
00470 const CoinPackedMatrix* tmp_matbyrow = si->getMatrixByRow ();
00471 for(int i=0;i<cons;i++) {
00472 CoinPackedVector tmp_currRow = (CoinPackedVector) tmp_matbyrow->getVector(i);
00473 int *tmpRowIdx = (int*) tmp_currRow.getIndices();
00474 double *tmpRowElem = (double*) tmp_currRow.getElements();
00475
00476 for(int j=0;j<tmp_currRow.getNumElements();j++) {
00477 origmat[i][tmpRowIdx[j]] = tmpRowElem[j];
00478 }
00479 }
00480
00481 return 0;
00482 }
00483
00484
00485
00486
00487 int createCut (OsiCuts &cs,
00488 double rhs,
00489 int sign,
00490
00491
00492 int i1, double c1,
00493 int i2, double c2,
00494 int i3, double c3,
00495 int i4, double c4,
00496 bool is_global) {
00497
00498 int nterms = 0;
00499
00500 if ((i1 >= 0) && (c1 != 0.0)) nterms++; else c1 =0;
00501 if ((i2 >= 0) && (c2 != 0.0)) nterms++; else c2 =0;
00502 if ((i3 >= 0) && (c3 != 0.0)) nterms++; else c3 =0;
00503 if ((i4 >= 0) && (c4 != 0.0)) nterms++; else c4 =0;
00504
00505 if (!nterms)
00506 return 0;
00507 int tmpcnt = 0;
00508
00509 double *coeff = new double [nterms];
00510 int *index = new int [nterms];
00511 OsiRowCut *cut = new OsiRowCut;
00512
00513 if ((i1 >= 0) && (c1 != 0.0))
00514 {
00515 coeff[tmpcnt] = c1;
00516 index[tmpcnt] = i1;
00517 tmpcnt++;
00518 }
00519 if ((i2 >= 0) && (c2 != 0.0))
00520 {
00521 coeff[tmpcnt] = c2;
00522 index[tmpcnt] = i2;
00523 tmpcnt++;
00524 }
00525 if ((i3 >= 0) && (c3 != 0.0))
00526 {
00527 coeff[tmpcnt] = c3;
00528 index[tmpcnt] = i3;
00529 tmpcnt++;
00530 }
00531 if ((i4 >= 0) && (c4 != 0.0))
00532 {
00533 coeff[tmpcnt] = c4;
00534 index[tmpcnt] = i4;
00535 tmpcnt++;
00536 }
00537
00538 if (sign <= 0) cut -> setUb (rhs);
00539 if (sign >= 0) cut -> setLb (rhs);
00540
00541 cut -> setRow (nterms, index, coeff);
00542
00543 delete [] coeff;
00544 delete [] index;
00545
00546 cut -> setGloballyValid (is_global);
00547
00548
00549 cs.insertIfNotDuplicate(*cut,CoinAbsFltEq(1.0e-12));
00550
00551
00552 delete cut;
00553
00554 return 1;
00555 }
00556
00557
00558
00559
00560 int getFirstIdx(const char *colName) {
00561
00562 char *temp = new char[strlen(colName)+1];
00563 char *idx1,*idx2;
00564 int idx1int;
00565 strcpy(temp,colName);
00566 idx1 = temp;
00567 idx1 += 2;
00568 idx2 = strchr(idx1,'_');
00569 if (idx2 != NULL)
00570 *idx2 = '\0';
00571 idx1int = atoi(idx1);
00572 delete [] temp;
00573 return idx1int;
00574 }
00575
00576
00577
00578 int getSecondIdx(const char *colName) {
00579
00580
00581 char *temp = new char[strlen(colName)+1];
00582 char *idx1,*idx2;
00583 int idx2int =-1;
00584 strcpy(temp,colName);
00585 idx1 = temp;
00586 idx1 += 2;
00587 idx2 = strchr(idx1,'_');
00588 if (idx2 != NULL){
00589 *idx2 = '\0';
00590 idx2++;
00591 idx2int = atoi(idx2);
00592 }
00593 else
00594 idx2int = -1;
00595 delete [] temp;
00596 return idx2int;
00597 }
00598
00599
00600 double _mul(double a, double b, double infinity) {
00601 if ((a==0.0) || (b==0.0))
00602 return 0.0;
00603
00604 if ((a >= infinity) && (b > 0))
00605 return infinity;
00606 if ((a > 0) && (b >= infinity))
00607 return infinity;
00608 if ((a >= infinity) && (b < 0))
00609 return - infinity;
00610 if ((a < 0) && (b >= infinity))
00611 return - infinity;
00612
00613 if ((a <= -infinity) && (b > 0))
00614 return - infinity;
00615 if ((a > 0) && (b <= -infinity))
00616 return - infinity;
00617 if ((a <= -infinity) && (b < 0))
00618 return infinity;
00619 if ((a < 0) && (b <= -infinity))
00620 return - infinity;
00621
00622 return a*b;
00623 }
00624