00001 #include <cassert>
00002
00003 #include "ClpSimplexPrimal.hpp"
00004 #include "ClpFactorization.hpp"
00005 #include "ClpPresolve.hpp"
00006 #include "ekk_c_api.h"
00007
00008 extern "C"{
00009 OSLLIBAPI void * OSLLINKAGE ekk_compressModel(EKKModel * model);
00010 OSLLIBAPI void OSLLINKAGE ekk_decompressModel(EKKModel * model,
00011 void * compressInfo);
00012 }
00013
00014 static ClpPresolve * presolveInfo=NULL;
00015
00016 static ClpSimplex * clpmodel(EKKModel * model,int startup)
00017 {
00018 ClpSimplex * clp = new ClpSimplex();;
00019 int numberRows=ekk_getInumrows(model);
00020 int numberColumns= ekk_getInumcols(model);
00021 clp->loadProblem(numberColumns,numberRows,ekk_blockColumn(model,0),
00022 ekk_blockRow(model,0),ekk_blockElement(model,0),
00023 ekk_collower(model),ekk_colupper(model),
00024 ekk_objective(model),
00025 ekk_rowlower(model),ekk_rowupper(model));
00026 clp->setOptimizationDirection((int) ekk_getRmaxmin(model));
00027 clp->setPrimalTolerance(ekk_getRtolpinf(model));
00028 if (ekk_getRpweight(model)!=0.1)
00029 clp->setInfeasibilityCost(1.0/ekk_getRpweight(model));
00030 clp->setDualTolerance(ekk_getRtoldinf(model));
00031 if (ekk_getRdweight(model)!=0.1)
00032 clp->setDualBound(1.0/ekk_getRdweight(model));
00033 clp->setDblParam(ClpObjOffset,ekk_getRobjectiveOffset(model));
00034 const int * rowStatus = ekk_rowstat(model);
00035 const double * rowSolution = ekk_rowacts(model);
00036 int i;
00037 clp->createStatus();
00038 double * clpSolution;
00039 clpSolution = clp->primalRowSolution();
00040 memcpy(clpSolution,rowSolution,numberRows*sizeof(double));
00041 const double * rowLower = ekk_rowlower(model);
00042 const double * rowUpper = ekk_rowupper(model);
00043 for (i=0;i<numberRows;i++) {
00044 ClpSimplex::Status status;
00045 if ((rowStatus[i]&0x80000000)!=0) {
00046 status = ClpSimplex::basic;
00047 } else {
00048 if (!startup) {
00049
00050 int ikey = rowStatus[i]&0x60000000;
00051 if (ikey==0x40000000) {
00052
00053 status = ClpSimplex::atUpperBound;
00054 clpSolution[i]=rowUpper[i];
00055 } else if (ikey==0x20000000) {
00056
00057 status = ClpSimplex::atLowerBound;
00058 clpSolution[i]=rowLower[i];
00059 } else if (ikey==0x60000000) {
00060
00061 status = ClpSimplex::isFree;
00062 clpSolution[i]=0.0;
00063 } else {
00064
00065 status = ClpSimplex::atLowerBound;
00066 clpSolution[i]=rowLower[i];
00067 }
00068 } else {
00069 status = ClpSimplex::superBasic;
00070 }
00071 }
00072 clp->setRowStatus(i,status);
00073 }
00074
00075 const int * columnStatus = ekk_colstat(model);
00076 const double * columnSolution = ekk_colsol(model);
00077 clpSolution = clp->primalColumnSolution();
00078 memcpy(clpSolution,columnSolution,numberColumns*sizeof(double));
00079 const double * columnLower = ekk_collower(model);
00080 const double * columnUpper = ekk_colupper(model);
00081 for (i=0;i<numberColumns;i++) {
00082 ClpSimplex::Status status;
00083 if ((columnStatus[i]&0x80000000)!=0) {
00084 status = ClpSimplex::basic;
00085 } else {
00086 if (!startup) {
00087
00088 int ikey = columnStatus[i]&0x60000000;
00089 if (ikey==0x40000000) {
00090
00091 status = ClpSimplex::atUpperBound;
00092 clpSolution[i]=columnUpper[i];
00093 } else if (ikey==0x20000000) {
00094
00095 status = ClpSimplex::atLowerBound;
00096 clpSolution[i]=columnLower[i];
00097 } else if (ikey==0x60000000) {
00098
00099 status = ClpSimplex::isFree;
00100 clpSolution[i]=0.0;
00101 } else {
00102
00103 status = ClpSimplex::atLowerBound;
00104 clpSolution[i]=columnLower[i];
00105 }
00106 } else {
00107 status = ClpSimplex::superBasic;
00108 }
00109 }
00110 clp->setColumnStatus(i,status);
00111 }
00112 return clp;
00113 }
00114
00115 static int solve(EKKModel * model, int startup,int algorithm,
00116 int presolve)
00117 {
00118
00119 if (startup)
00120 startup=1;
00121
00122 bool scaled = ekk_scaling(model)==1;
00123 if (scaled)
00124 ekk_scaleRim(model,1);
00125 void * compressInfo=NULL;
00126 ClpSimplex * clp;
00127 if (!presolve||!presolveInfo) {
00128
00129 compressInfo=ekk_compressModel(model);
00130 clp = clpmodel(model,startup);;
00131 } else {
00132
00133 clp = presolveInfo->model();
00134 }
00135
00136
00137 if (scaled)
00138 clp->scaling(false);
00139 if (clp->numberRows()>10000)
00140 clp->factorization()->maximumPivots(100+clp->numberRows()/100);
00141 if (algorithm>0)
00142 clp->primal(startup);
00143 else
00144 clp->dual();
00145
00146 int numberIterations = clp->numberIterations();
00147 if (presolve&&presolveInfo) {
00148
00149 ClpSimplex * clpOriginal = clpmodel(model,0);
00150 presolveInfo->setOriginalModel(clpOriginal);
00151
00152 presolveInfo->postsolve(true);
00153 delete clp;
00154 delete presolveInfo;
00155 presolveInfo=NULL;
00156 clp = clpOriginal;
00157 if (presolve==3||(presolve==2&&clp->status())) {
00158 printf("Resolving from postsolved model\n");
00159 clp->primal(1);
00160 numberIterations += clp->numberIterations();
00161 }
00162 }
00163
00164
00165
00166 double * rowDual = (double *) ekk_rowduals(model);
00167 int numberRows=ekk_getInumrows(model);
00168 int numberColumns= ekk_getInumcols(model);
00169 int * rowStatus = (int *) ekk_rowstat(model);
00170 double * rowSolution = (double *) ekk_rowacts(model);
00171 int i;
00172 int * columnStatus = (int *) ekk_colstat(model);
00173 double * columnSolution = (double *) ekk_colsol(model);
00174 memcpy(rowSolution,clp->primalRowSolution(),numberRows*sizeof(double));
00175 memcpy(rowDual,clp->dualRowSolution(),numberRows*sizeof(double));
00176 for (i=0;i<numberRows;i++) {
00177 if (clp->getRowStatus(i)==ClpSimplex::basic)
00178 rowStatus[i]=0x80000000;
00179 else
00180 rowStatus[i]=0;
00181 }
00182
00183 double * columnDual = (double *) ekk_colrcosts(model);
00184 memcpy(columnSolution,clp->primalColumnSolution(),
00185 numberColumns*sizeof(double));
00186 memcpy(columnDual,clp->dualColumnSolution(),numberColumns*sizeof(double));
00187 for (i=0;i<numberColumns;i++) {
00188 if (clp->getColumnStatus(i)==ClpSimplex::basic)
00189 columnStatus[i]=0x80000000;
00190 else
00191 columnStatus[i]=0;
00192 }
00193 ekk_setIprobstat(model,clp->status());
00194 ekk_setRobjvalue(model,clp->objectiveValue());
00195 ekk_setInumpinf(model,clp->numberPrimalInfeasibilities());
00196 ekk_setInumdinf(model,clp->numberDualInfeasibilities());
00197 ekk_setIiternum(model,numberIterations);
00198 ekk_setRsumpinf(model,clp->sumPrimalInfeasibilities());
00199 ekk_setRsumdinf(model,clp->sumDualInfeasibilities());
00200 delete clp;
00201 if (compressInfo )
00202 ekk_decompressModel(model,compressInfo);
00203
00204 if (scaled)
00205 ekk_scaleRim(model,2);
00206 return 0;
00207 }
00208
00209
00210
00211
00212
00213 extern "C" int ekk_primalClp(EKKModel * model, int startup, int presolve)
00214 {
00215 if (presolveInfo) {
00216 if (!presolve)
00217 presolve=3;
00218 return solve(model,startup,1, presolve);
00219 } else {
00220 return solve(model,startup,1, 0);
00221 }
00222 }
00223
00224
00225
00226
00227
00228
00229 extern "C" int ekk_dualClp(EKKModel * model, int presolve)
00230 {
00231 if (presolveInfo) {
00232 if (!presolve)
00233 presolve=3;
00234 return solve(model,0,-1, presolve);
00235 } else {
00236 return solve(model,0,-1, 0);
00237 }
00238 }
00239
00240
00241
00242
00243
00244
00245 extern "C" int ekk_preSolveClp(EKKModel * model, bool keepIntegers,
00246 int pass)
00247 {
00248 delete presolveInfo;
00249 presolveInfo = new ClpPresolve();
00250 bool scaled = ekk_scaling(model)==1;
00251 if (scaled)
00252 ekk_scaleRim(model,1);
00253 if (!pass)
00254 pass=5;
00255
00256
00257 ClpSimplex * clp = clpmodel(model,1);
00258
00259 ClpSimplex * newModel =
00260 presolveInfo->presolvedModel(*clp,
00261 ekk_getRtolpinf(model),
00262 keepIntegers,pass,true);
00263 delete clp;
00264 presolveInfo->setOriginalModel(NULL);
00265 if (scaled)
00266 ekk_scaleRim(model,2);
00267 if (newModel) {
00268 return 0;
00269 } else {
00270 delete presolveInfo;
00271 presolveInfo=NULL;
00272 return 1;
00273 }
00274 }