genmodel 0.0.20 → 0.0.21
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/ext/Genmodel/GenModel.h +152 -0
- data/ext/Genmodel/GenModelBase.cpp +389 -0
- data/ext/Genmodel/GenModelCplex.cpp +814 -0
- data/ext/Genmodel/GenModelCplex.h +85 -0
- data/ext/Genmodel/GenModelOsi.cpp +892 -0
- data/ext/Genmodel/GenModelOsi.h +96 -0
- data/ext/Genmodel/GenModelOsiInterface.cpp +143 -0
- data/ext/Genmodel/GenModelOsiInterface.h +43 -0
- data/ext/Genmodel/Genmodel.cpp +10789 -0
- data/ext/Genmodel/InterfaceObject.cpp +68 -0
- data/ext/Genmodel/InterfaceObject.h +28 -0
- data/ext/Genmodel/ProblemReaderOsi.cpp +78 -0
- data/ext/Genmodel/ProblemReaderOsi.h +31 -0
- data/ext/Genmodel/extconf.rb +162 -0
- data/lib/Genmodel.rb +5 -0
- metadata +25 -13
- data/lib/genmodel.bundle +0 -0
- data/lib/genmodel.so +0 -0
@@ -0,0 +1,892 @@
|
|
1
|
+
/*
|
2
|
+
* GenModelOsi.cpp
|
3
|
+
*
|
4
|
+
* Created on: 2012-10-01
|
5
|
+
* Author: mbouchard
|
6
|
+
*/
|
7
|
+
|
8
|
+
#include "GenModelOsi.h"
|
9
|
+
#include "ProblemReaderOsi.h"
|
10
|
+
#include "CbcHeuristicFPump.hpp"
|
11
|
+
#include "CbcHeuristicRINS.hpp"
|
12
|
+
#include "CbcHeuristicLocal.hpp"
|
13
|
+
#include "CbcHeuristicDiveCoefficient.hpp"
|
14
|
+
#include "CbcHeuristicDiveFractional.hpp"
|
15
|
+
#include <limits>
|
16
|
+
|
17
|
+
using namespace std;
|
18
|
+
|
19
|
+
long GenModelOsi::WriteProblemToLpFile(string filename)
|
20
|
+
{
|
21
|
+
if(!bcreated)
|
22
|
+
throw string("WriteProblemToLpFile() not available : Problem not created yet;");
|
23
|
+
|
24
|
+
OsiData* d = static_cast<OsiData*>(solverdata);
|
25
|
+
d->model->writeLp(filename.c_str());
|
26
|
+
return 0;
|
27
|
+
}
|
28
|
+
|
29
|
+
long GenModelOsi::WriteSolutionToFile(string filename)
|
30
|
+
{
|
31
|
+
if(!bcreated)
|
32
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
33
|
+
|
34
|
+
FILE* f = fopen(filename.c_str(), "w");
|
35
|
+
for(long i = 0; i < long(vars.n); i++)
|
36
|
+
{
|
37
|
+
if(fabs(vars.sol[i]) > 0.000001)
|
38
|
+
fprintf(f, "%s : %f\n", vars.name[i].c_str(), vars.sol[i]);
|
39
|
+
}
|
40
|
+
|
41
|
+
fclose(f);
|
42
|
+
return 0;
|
43
|
+
}
|
44
|
+
|
45
|
+
long GenModelOsi::Solve()
|
46
|
+
{
|
47
|
+
if(!bcreated)
|
48
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
49
|
+
OsiData* d = static_cast<OsiData*>(solverdata);
|
50
|
+
d->model->setHintParam(OsiDoReducePrint,true,OsiHintTry);
|
51
|
+
|
52
|
+
|
53
|
+
/*
|
54
|
+
if(boolParam.count("mip") > 0 && boolParam["mip"])
|
55
|
+
{
|
56
|
+
printf("********* OSI Branch and bounds **************\n");
|
57
|
+
d->model->branchAndBound();
|
58
|
+
}
|
59
|
+
else if(boolParam.count("notroot") > 0 && boolParam["notroot"])
|
60
|
+
{
|
61
|
+
printf("********* OSI Resolve **************\n");
|
62
|
+
d->model->resolve();
|
63
|
+
}
|
64
|
+
else
|
65
|
+
{
|
66
|
+
printf("********* OSI Initial Solve **************\n");
|
67
|
+
d->model->initialSolve();
|
68
|
+
}
|
69
|
+
*/
|
70
|
+
|
71
|
+
d->model->setHintParam(OsiDoReducePrint,true,OsiHintTry);
|
72
|
+
|
73
|
+
// Set up some cut generators and defaults
|
74
|
+
// Probing first as gets tight bounds on continuous
|
75
|
+
|
76
|
+
CglProbing generator1;
|
77
|
+
// can not use objective
|
78
|
+
generator1.setUsingObjective(false);
|
79
|
+
generator1.setMaxPass(3);
|
80
|
+
generator1.setMaxProbe(100);
|
81
|
+
generator1.setMaxLook(50);
|
82
|
+
generator1.setRowCuts(3);
|
83
|
+
|
84
|
+
CglGomory generator2;
|
85
|
+
// try larger limit
|
86
|
+
generator2.setLimit(30000);
|
87
|
+
|
88
|
+
CglKnapsackCover generator3;
|
89
|
+
|
90
|
+
CglOddHole generator4;
|
91
|
+
generator4.setMinimumViolation(0.005);
|
92
|
+
generator4.setMinimumViolationPer(0.00002);
|
93
|
+
// try larger limit
|
94
|
+
generator4.setMaximumEntries(50); //(200); //maybe originally 50
|
95
|
+
|
96
|
+
CglClique generator5;
|
97
|
+
generator5.setStarCliqueReport(false);
|
98
|
+
generator5.setRowCliqueReport(false);
|
99
|
+
|
100
|
+
CglMixedIntegerRounding mixedGen;
|
101
|
+
CglFlowCover flowGen;
|
102
|
+
// Add in generators (just at root)
|
103
|
+
|
104
|
+
d->mipmodel = new CbcModel(*(d->model));
|
105
|
+
// Add in generators
|
106
|
+
// Only some generators work (and even then try without first)
|
107
|
+
|
108
|
+
|
109
|
+
d->mipmodel->addCutGenerator(&generator1,1,"Probing");
|
110
|
+
// Allow rounding heuristic
|
111
|
+
|
112
|
+
d->mipmodel->addCutGenerator(&generator1,-99,"Probing",true,false,false,-1);
|
113
|
+
d->mipmodel->addCutGenerator(&generator2,-99,"Gomory",true,false,false,-99);
|
114
|
+
d->mipmodel->addCutGenerator(&generator3,-99,"Knapsack",true,false,false,-99);
|
115
|
+
d->mipmodel->addCutGenerator(&generator4,-99,"OddHole",true,false,false,-99);
|
116
|
+
d->mipmodel->addCutGenerator(&generator5,-99,"Clique",true,false,false,-99);
|
117
|
+
d->mipmodel->addCutGenerator(&flowGen,-99,"FlowCover",true,false,false,-99);
|
118
|
+
d->mipmodel->addCutGenerator(&mixedGen,-99,"MixedIntegerRounding",true,false,false,-100);
|
119
|
+
|
120
|
+
CbcRounding rounding(*(d->mipmodel));
|
121
|
+
rounding.setHeuristicName("Rounding");
|
122
|
+
// do not add yet as don't know how to deal with quadratic objective
|
123
|
+
d->mipmodel->addHeuristic(&rounding);
|
124
|
+
rounding.setHeuristicName("Greedy cover");
|
125
|
+
CbcHeuristicGreedyCover greedy(*(d->mipmodel));
|
126
|
+
// Use original upper and perturb more
|
127
|
+
greedy.setAlgorithm(11);
|
128
|
+
greedy.setHeuristicName("Greedy cover");
|
129
|
+
d->mipmodel->addHeuristic(&greedy);
|
130
|
+
|
131
|
+
// Redundant definition of default branching (as Default == User)
|
132
|
+
//CbcBranchUserDecision branch;
|
133
|
+
//d->mipmodel->setBranchingMethod(&branch);
|
134
|
+
|
135
|
+
// Definition of node choice
|
136
|
+
//CbcCompareUser compare;
|
137
|
+
// breadth first
|
138
|
+
//compare.setWeight(0.0);
|
139
|
+
//d->mipmodel->setNodeComparison(compare);
|
140
|
+
|
141
|
+
|
142
|
+
// Do initial solve to continuous
|
143
|
+
d->mipmodel->initialSolve();
|
144
|
+
|
145
|
+
double objValue = d->mipmodel->getObjValue();
|
146
|
+
|
147
|
+
CbcHeuristicDiveCoefficient heuristicDC(*(d->mipmodel));
|
148
|
+
heuristicDC.setHeuristicName("DiveCoefficient");
|
149
|
+
// allow to exit if close enough to optimum
|
150
|
+
heuristicDC.setSwitches(1);
|
151
|
+
d->mipmodel->addHeuristic(&heuristicDC);
|
152
|
+
CbcHeuristicDiveFractional heuristicDF(*(d->mipmodel));
|
153
|
+
heuristicDF.setHeuristicName("DiveFractional");
|
154
|
+
heuristicDF.setSwitches(1);
|
155
|
+
d->mipmodel->addHeuristic(&heuristicDF);
|
156
|
+
CbcHeuristicFPump pump(*(d->mipmodel));
|
157
|
+
// allow to exit if close enough to optimum
|
158
|
+
// plus some dubious options
|
159
|
+
pump.setSwitches(1+4+8);
|
160
|
+
pump.setMaximumTime(3600);
|
161
|
+
pump.setMaximumPasses(50); //100);
|
162
|
+
pump.setMaximumRetries(10); //(1);
|
163
|
+
pump.setFixOnReducedCosts(1);
|
164
|
+
pump.setHeuristicName("Feasibility pump 1");
|
165
|
+
pump.setFractionSmall(1.0);
|
166
|
+
pump.setWhen(13);
|
167
|
+
pump.setFakeCutoff(objValue+0.01*fabs(objValue));
|
168
|
+
pump.setReducedCostMultiplier(0.1);
|
169
|
+
pump.setFeasibilityPumpOptions(80);
|
170
|
+
d->mipmodel->addHeuristic(&pump);
|
171
|
+
pump.setHeuristicName("Feasibility pump 2");
|
172
|
+
pump.setFakeCutoff(objValue+0.05*fabs(objValue));
|
173
|
+
pump.setFeasibilityPumpOptions(80);
|
174
|
+
d->mipmodel->addHeuristic(&pump);
|
175
|
+
pump.setHeuristicName("Feasibility pump 3");
|
176
|
+
pump.setFakeCutoff(objValue+0.01*fabs(objValue));
|
177
|
+
pump.setReducedCostMultiplier(0.1);
|
178
|
+
pump.setFeasibilityPumpOptions(80);
|
179
|
+
d->mipmodel->addHeuristic(&pump);
|
180
|
+
pump.setHeuristicName("Feasibility pump 4");
|
181
|
+
pump.setFakeCutoff(objValue+0.05*fabs(objValue));
|
182
|
+
pump.setReducedCostMultiplier(1.0);
|
183
|
+
pump.setFeasibilityPumpOptions(80);
|
184
|
+
pump.setMaximumTime(200);
|
185
|
+
d->mipmodel->addHeuristic(&pump);
|
186
|
+
CbcHeuristicRINS rins(*(d->mipmodel));
|
187
|
+
rins.setHeuristicName("RINS");
|
188
|
+
rins.setFractionSmall(0.5);
|
189
|
+
rins.setDecayFactor(5.0);
|
190
|
+
d->mipmodel->addHeuristic(&rins) ;
|
191
|
+
CbcHeuristicLocal local(*(d->mipmodel));
|
192
|
+
local.setHeuristicName("LOCAL");
|
193
|
+
local.setFractionSmall(0.5);
|
194
|
+
local.setSearchType(1);
|
195
|
+
d->mipmodel->addHeuristic(&local) ;
|
196
|
+
if(longParam.count("nb_threads") == 0 && longParam["nb_threads"] >= 1)
|
197
|
+
{
|
198
|
+
d->mipmodel->setThreadMode(7);
|
199
|
+
d->mipmodel->setNumberThreads(longParam["nb_threads"]);
|
200
|
+
}
|
201
|
+
|
202
|
+
// Could tune more
|
203
|
+
d->mipmodel->setMinimumDrop(CoinMin(1.0, fabs(d->mipmodel->getMinimizationObjValue())*1.0e-3+1.0e-4));
|
204
|
+
|
205
|
+
d->mipmodel->setMaximumCutPassesAtRoot(1); // (50);
|
206
|
+
d->mipmodel->setMaximumCutPasses(10); //(100);
|
207
|
+
|
208
|
+
// Switch off strong branching if wanted
|
209
|
+
//d->mipmodel->setNumberStrong(5);
|
210
|
+
|
211
|
+
d->mipmodel->solver()->setIntParam(OsiMaxNumIterationHotStart,10000);
|
212
|
+
|
213
|
+
// If time is given then stop after that number of minutes
|
214
|
+
if (dblParam.count("time_limit") > 0)
|
215
|
+
{
|
216
|
+
printf("Stopping after %f seconds\n", dblParam["time_limit"]);
|
217
|
+
d->mipmodel->setDblParam(CbcModel::CbcMaximumSeconds, dblParam["time_limit"]);
|
218
|
+
}
|
219
|
+
|
220
|
+
// Switch off most output
|
221
|
+
if (d->mipmodel->getNumCols()<3000)
|
222
|
+
{
|
223
|
+
d->mipmodel->messageHandler()->setLogLevel(1);
|
224
|
+
//d->model->solver()->messageHandler()->setLogLevel(0);
|
225
|
+
}
|
226
|
+
else
|
227
|
+
{
|
228
|
+
d->mipmodel->messageHandler()->setLogLevel(2);
|
229
|
+
d->mipmodel->solver()->messageHandler()->setLogLevel(1);
|
230
|
+
}
|
231
|
+
d->mipmodel->setPrintFrequency(1);//(50);
|
232
|
+
|
233
|
+
double time1 = CoinCpuTime();
|
234
|
+
|
235
|
+
// Do complete search
|
236
|
+
d->mipmodel->branchAndBound();
|
237
|
+
|
238
|
+
printf(" took %f seconds, %d nodes with objective %f, %s\n",
|
239
|
+
CoinCpuTime()-time1, d->mipmodel->getNodeCount(), d->mipmodel->getObjValue(), (!d->mipmodel->status() ? " Finished" : " Not finished"));
|
240
|
+
|
241
|
+
// Print more statistics
|
242
|
+
printf("Cuts at root node changed objective from %f to %f\n", d->mipmodel->getContinuousObjective(), d->mipmodel->rootObjectiveAfterCuts());
|
243
|
+
|
244
|
+
int numberGenerators = d->mipmodel->numberCutGenerators();
|
245
|
+
for (int iGenerator=0;iGenerator<numberGenerators;iGenerator++)
|
246
|
+
{
|
247
|
+
CbcCutGenerator * generator = d->mipmodel->cutGenerator(iGenerator);
|
248
|
+
printf("%s was tried %d times and created %d cuts of which %d were active after adding rounds of cuts\n", generator->cutGeneratorName(),
|
249
|
+
generator->numberTimesEntered(),generator->numberCutsInTotal(), generator->numberCutsActive());
|
250
|
+
}
|
251
|
+
|
252
|
+
hassolution = d->mipmodel->getIntParam(CbcModel::CbcMaxNumSol) > 0;
|
253
|
+
objval = d->mult*d->mipmodel->getObjValue();
|
254
|
+
|
255
|
+
d->model = d->mipmodel->solver();
|
256
|
+
|
257
|
+
/* CoinData* d = static_cast<CoinData*>(solverdata);
|
258
|
+
|
259
|
+
if(strParam.count("algo") > 0 && strParam["algo"] == "interior")
|
260
|
+
{
|
261
|
+
ClpInterior intmod;
|
262
|
+
if(boolParam.count("qp") > 0 && boolParam["qp"])
|
263
|
+
{
|
264
|
+
ClpCholeskyBase * cholesky = new ClpCholeskyBase();
|
265
|
+
cholesky->setKKT(true);
|
266
|
+
intmod.borrowModel(*(d->model));
|
267
|
+
intmod.setCholesky(cholesky);
|
268
|
+
intmod.primalDual();
|
269
|
+
intmod.returnModel(*(d->model));
|
270
|
+
}
|
271
|
+
else
|
272
|
+
{
|
273
|
+
printf("interior\n");
|
274
|
+
ClpCholeskyBase * cholesky = new ClpCholeskyBase();
|
275
|
+
intmod.borrowModel(*(d->model));
|
276
|
+
intmod.setCholesky(cholesky);
|
277
|
+
intmod.primalDual();
|
278
|
+
intmod.returnModel(*(d->model));
|
279
|
+
}
|
280
|
+
}
|
281
|
+
else if(strParam.count("algo") > 0 && strParam["algo"] == "dual")
|
282
|
+
d->model->dual();
|
283
|
+
else
|
284
|
+
d->model->primal();*/
|
285
|
+
|
286
|
+
return 0;
|
287
|
+
}
|
288
|
+
|
289
|
+
long GenModelOsi::SetSol()
|
290
|
+
{
|
291
|
+
if(!bcreated)
|
292
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
293
|
+
OsiData* d = static_cast<OsiData*>(solverdata);
|
294
|
+
|
295
|
+
vars.sol.clear();
|
296
|
+
vars.sol.resize(vars.n,0);
|
297
|
+
vars.rc.clear();
|
298
|
+
vars.rc.resize(vars.n,0);
|
299
|
+
|
300
|
+
if(!hassolution)
|
301
|
+
return 1;
|
302
|
+
|
303
|
+
const double* sol;
|
304
|
+
const double* act;
|
305
|
+
|
306
|
+
sol = d->model->getColSolution();
|
307
|
+
act = d->model->getRowActivity();
|
308
|
+
|
309
|
+
if(boolParam.count("mip") == 0 || !boolParam["mip"])
|
310
|
+
{
|
311
|
+
const double* dual = d->model->getRowPrice();
|
312
|
+
const double* rc = d->model->getReducedCost();
|
313
|
+
for (unsigned int i = 0; i < vars.n; i++)
|
314
|
+
vars.rc[i] = rc[i];
|
315
|
+
for(long i = 0; i < long(nr); i++)
|
316
|
+
consts[i].dual = dual[i];
|
317
|
+
}
|
318
|
+
|
319
|
+
for (unsigned int i = 0; i < vars.n; i++)
|
320
|
+
vars.sol[i] = sol[i];
|
321
|
+
for(long i = 0; i < long(nr); i++)
|
322
|
+
{
|
323
|
+
switch (consts[i].sense)
|
324
|
+
{
|
325
|
+
case 'L': consts[i].slack = consts[i].lrhs-act[i]; break;
|
326
|
+
case 'G': consts[i].slack = act[i]-consts[i].lrhs; break;
|
327
|
+
default: consts[i].slack = act[i]; break;
|
328
|
+
}
|
329
|
+
}
|
330
|
+
|
331
|
+
solstat = d->model->isProvenOptimal();
|
332
|
+
if (d->model->isProvenOptimal())
|
333
|
+
solstat = 1;
|
334
|
+
if (d->model->isProvenPrimalInfeasible())
|
335
|
+
solstat = 2;
|
336
|
+
if (d->model->isProvenDualInfeasible())
|
337
|
+
solstat = 3;
|
338
|
+
if (d->model->isIterationLimitReached())
|
339
|
+
solstat = 4;
|
340
|
+
|
341
|
+
if(boolParam.count("print_version") > 0 && boolParam["print_version"])
|
342
|
+
printf("*********** Genmodel version = %s ***********\n", version.c_str());
|
343
|
+
|
344
|
+
//objval = (dynamic_cast<OsiClpSolverInterface*>(d->model))->getModelPtr()->objectiveValue();
|
345
|
+
|
346
|
+
delete[] sol;
|
347
|
+
delete[] act;
|
348
|
+
|
349
|
+
return 0;
|
350
|
+
}
|
351
|
+
|
352
|
+
long GenModelOsi::CreateModel()
|
353
|
+
{
|
354
|
+
if(!binit)
|
355
|
+
return ThrowError("CreateModel() not available : Problem not initialized yet");
|
356
|
+
|
357
|
+
OsiData* d = static_cast<OsiData*>(solverdata);
|
358
|
+
|
359
|
+
d->nc = nc;
|
360
|
+
d->nr = nr;
|
361
|
+
|
362
|
+
d->lrhs = new double[nr];
|
363
|
+
d->urhs = new double[nr];
|
364
|
+
d->ub = new double[nc];
|
365
|
+
d->lb = new double[nc];
|
366
|
+
d->obj = new double[nc];
|
367
|
+
d->typei = new int[nc];
|
368
|
+
d->typec = new int[nc];
|
369
|
+
d->mat_r = new int[nz];
|
370
|
+
d->mat_beg = new CoinBigIndex[nc+1];
|
371
|
+
d->mat_v = new double[nz];
|
372
|
+
d->cname = new char*[nc];
|
373
|
+
d->rname = new char*[nr];
|
374
|
+
d->nq = 0;
|
375
|
+
memset(d->mat_beg, 0, (nc+1)*sizeof(CoinBigIndex));
|
376
|
+
|
377
|
+
d->mult = 1.0;
|
378
|
+
if(boolParam.count("maximize") > 0 && boolParam["maximize"])
|
379
|
+
d->mult = -1.0;
|
380
|
+
|
381
|
+
int numint = 0;
|
382
|
+
int numcont = 0;
|
383
|
+
|
384
|
+
vector<vector<pair<int,double> > > tvect;
|
385
|
+
tvect.resize(nc);
|
386
|
+
for(unsigned long i = 0; i < nr; i++)
|
387
|
+
{
|
388
|
+
d->rname[i] = new char[consts[i].name.length()+1];
|
389
|
+
snprintf(d->rname[i], consts[i].name.length()+1, "%s", consts[i].name.c_str());
|
390
|
+
for(unsigned long j = 0; j < consts[i].nz; j++)
|
391
|
+
{
|
392
|
+
d->mat_beg[consts[i].cols[j]]++;
|
393
|
+
tvect[consts[i].cols[j]].push_back(pair<int,double>(i,consts[i].coefs[j]));
|
394
|
+
}
|
395
|
+
|
396
|
+
if(consts[i].lrhs == numeric_limits<double>::infinity())
|
397
|
+
d->lrhs[i] = COIN_DBL_MAX;
|
398
|
+
else if(consts[i].lrhs == -numeric_limits<double>::infinity())
|
399
|
+
d->lrhs[i] = -COIN_DBL_MAX;
|
400
|
+
else
|
401
|
+
d->lrhs[i] = consts[i].lrhs;
|
402
|
+
if(consts[i].urhs == numeric_limits<double>::infinity())
|
403
|
+
d->urhs[i] = COIN_DBL_MAX;
|
404
|
+
else if(consts[i].urhs == -numeric_limits<double>::infinity())
|
405
|
+
d->urhs[i] = -COIN_DBL_MAX;
|
406
|
+
else
|
407
|
+
d->urhs[i] = consts[i].urhs;
|
408
|
+
if(consts[i].sense == 'G')
|
409
|
+
{
|
410
|
+
//d->lrhs[i] = d->lrhs[i];
|
411
|
+
d->urhs[i] = COIN_DBL_MAX;
|
412
|
+
}
|
413
|
+
else if(consts[i].sense == 'L')
|
414
|
+
{
|
415
|
+
d->urhs[i] = d->lrhs[i];
|
416
|
+
d->lrhs[i] = -COIN_DBL_MAX;
|
417
|
+
}
|
418
|
+
else if(consts[i].sense == 'E')
|
419
|
+
{
|
420
|
+
d->urhs[i] = d->lrhs[i];
|
421
|
+
//d->lrhs[i] = d->lrhs[i];
|
422
|
+
}
|
423
|
+
}
|
424
|
+
int begcsum = 0;
|
425
|
+
long oldnz = nz;
|
426
|
+
nz=0;
|
427
|
+
for(unsigned long i = 0; i < nc; i++)
|
428
|
+
{
|
429
|
+
int temp = begcsum;
|
430
|
+
begcsum+=d->mat_beg[i];
|
431
|
+
d->mat_beg[i]=temp;
|
432
|
+
|
433
|
+
for(unsigned int k = 0; k < (unsigned int)(tvect[i].size()); k++)
|
434
|
+
{
|
435
|
+
d->mat_r[nz] = tvect[i][k].first;
|
436
|
+
d->mat_v[nz] = tvect[i][k].second;
|
437
|
+
nz++;
|
438
|
+
}
|
439
|
+
|
440
|
+
d->cname[i] = new char[vars.name[i].length()+1];
|
441
|
+
snprintf(d->cname[i], vars.name[i].length()+1, "%s", vars.name[i].c_str());
|
442
|
+
d->obj[i] = d->mult*vars.obj[i];
|
443
|
+
if(vars.ub[i] == numeric_limits<double>::infinity())
|
444
|
+
d->ub[i] = COIN_DBL_MAX;
|
445
|
+
else if(vars.ub[i] == -numeric_limits<double>::infinity())
|
446
|
+
d->ub[i] = -COIN_DBL_MAX;
|
447
|
+
else
|
448
|
+
d->ub[i] = vars.ub[i];
|
449
|
+
if(vars.lb[i] == numeric_limits<double>::infinity())
|
450
|
+
d->lb[i] = COIN_DBL_MAX;
|
451
|
+
else if(vars.lb[i] == -numeric_limits<double>::infinity())
|
452
|
+
d->lb[i] = -COIN_DBL_MAX;
|
453
|
+
else
|
454
|
+
d->lb[i] = vars.lb[i];
|
455
|
+
//d->type[i] = vars.type[i];
|
456
|
+
if(vars.type[i] == 'B')
|
457
|
+
{
|
458
|
+
if(d->lb[i] < 0.0)
|
459
|
+
d->lb[i] = 0.0;
|
460
|
+
if(d->ub[i] > 1.0)
|
461
|
+
d->ub[i] = 1.0;
|
462
|
+
d->typei[numint] = i;
|
463
|
+
numint++;
|
464
|
+
}
|
465
|
+
else if(vars.type[i] == 'I')
|
466
|
+
{
|
467
|
+
d->typei[numint] = i;
|
468
|
+
numint++;
|
469
|
+
}
|
470
|
+
else
|
471
|
+
{
|
472
|
+
d->typec[numcont] = i;
|
473
|
+
numcont++;
|
474
|
+
}
|
475
|
+
}
|
476
|
+
|
477
|
+
d->mat_beg[nc]=begcsum;
|
478
|
+
|
479
|
+
d->model->loadProblem(nc,nr,d->mat_beg,d->mat_r,d->mat_v, d->lb,d->ub,d->obj,d->lrhs, d->urhs);
|
480
|
+
|
481
|
+
d->model->setContinuous(d->typec, numcont);
|
482
|
+
d->model->setInteger (d->typei, numint);
|
483
|
+
|
484
|
+
/*if(boolParam.count("maximize") > 0 && boolParam["maximize"])
|
485
|
+
{
|
486
|
+
d->model->setObjSense(-1.0);
|
487
|
+
d->model->writeMps("tmp/test", "mps", -1.0);
|
488
|
+
}
|
489
|
+
else
|
490
|
+
{*/
|
491
|
+
d->model->setObjSense(1.0);
|
492
|
+
// d->model->writeMps("tmp/test", "mps", 1.0);
|
493
|
+
//}
|
494
|
+
|
495
|
+
/*d->nq = 0;
|
496
|
+
if(boolParam.count("qp_mat") > 0 && boolParam["qp_mat"] && !vars.qi.empty())
|
497
|
+
{
|
498
|
+
boolParam["qp"] = true;
|
499
|
+
vector<long>::iterator iti;
|
500
|
+
vector<long>::iterator itj = vars.qj.begin();
|
501
|
+
vector<double>::iterator itv = vars.qobj.begin();
|
502
|
+
vector<vector<pair<int,double> > > tvect;
|
503
|
+
for(iti = vars.qi.begin(); iti != vars.qi.end(); iti++, itj++, itv++)
|
504
|
+
{
|
505
|
+
if(*iti )
|
506
|
+
tvect[*iti]
|
507
|
+
d->Q_beg[i]++;
|
508
|
+
d->Q_r[d->nq] = *iti;
|
509
|
+
d->Q_v[d->nq] = *itv;
|
510
|
+
d->nq++;
|
511
|
+
}
|
512
|
+
int Qcsum = 0;
|
513
|
+
for(unsigned long i = 0; i < nc; i++)
|
514
|
+
{
|
515
|
+
int temp = Qcsum;
|
516
|
+
Qcsum += d->Q_beg[i];
|
517
|
+
d->Q_beg[i] = temp;
|
518
|
+
}
|
519
|
+
d->Q_beg[nc] = Qcsum;
|
520
|
+
|
521
|
+
printf("Adding quadratic obj\n");
|
522
|
+
(dynamic_cast<GenModelOsiInterface*>(d->model))->setQuadraticObjective(d->nc,d->Q_beg,d->Q_r,d->Q_v);
|
523
|
+
//(dynamic_cast<OsiClpSolverInterface*>(d->model))->getModelPtr()->loadQuadraticObjective(d->nc,d->Q_beg,d->Q_r,d->Q_v);
|
524
|
+
}*/
|
525
|
+
|
526
|
+
if(boolParam.count("qp_mat") == 0 || boolParam["qp_mat"])
|
527
|
+
{
|
528
|
+
vector<vector<pair<int,double> > > qptemp;
|
529
|
+
qptemp.resize(nc);
|
530
|
+
int* qpbeg = NULL;
|
531
|
+
CoinBigIndex* qpind = NULL;
|
532
|
+
double* qpv = NULL;
|
533
|
+
int qpnz = 0;
|
534
|
+
|
535
|
+
vector<long>::iterator iti;
|
536
|
+
vector<long>::iterator itj = vars.qj.begin();
|
537
|
+
vector<double>::iterator itv = vars.qobj.begin();
|
538
|
+
|
539
|
+
for(iti = vars.qi.begin(); iti != vars.qi.end(); iti++, itj++, itv++)
|
540
|
+
{
|
541
|
+
qptemp[*iti].push_back(pair<int, double>(*itj,*itv));
|
542
|
+
qpnz++;
|
543
|
+
if(*iti != *itj)
|
544
|
+
{
|
545
|
+
qptemp[*itj].push_back(pair<int, double>(*iti,*itv));
|
546
|
+
qpnz++;
|
547
|
+
}
|
548
|
+
}
|
549
|
+
if(!vars.qi.empty())
|
550
|
+
{
|
551
|
+
boolParam["qp"] = true;
|
552
|
+
qpbeg = new int[nc+1];
|
553
|
+
|
554
|
+
qpv = new double[qpnz];
|
555
|
+
qpind = new CoinBigIndex[qpnz];
|
556
|
+
|
557
|
+
qpnz=0;
|
558
|
+
for(int i = 0; i < int(nc); i++)
|
559
|
+
{
|
560
|
+
qpbeg[i] = qpnz;
|
561
|
+
for(int j = 0; j < int(qptemp[i].size()); j++)
|
562
|
+
{
|
563
|
+
qpind[qpnz] = qptemp[i][j].first;
|
564
|
+
qpv[qpnz] = d->mult*2*qptemp[i][j].second;
|
565
|
+
qpnz++;
|
566
|
+
}
|
567
|
+
}
|
568
|
+
qpbeg[nc] = qpnz;
|
569
|
+
printf("Adding quadratic obj\n");
|
570
|
+
(dynamic_cast<GenModelOsiInterface*>(d->model))->setQuadraticObjective(nc,qpbeg,qpind,qpv);
|
571
|
+
//(dynamic_cast<OsiClpSolverInterface*>(d->model))->getModelPtr()->loadQuadraticObjective(nc,qpbeg,qpind,qpv);
|
572
|
+
d->nq = qpnz;
|
573
|
+
|
574
|
+
delete[] qpbeg;
|
575
|
+
delete[] qpind;
|
576
|
+
delete[] qpv;
|
577
|
+
}
|
578
|
+
}
|
579
|
+
nz = oldnz;
|
580
|
+
|
581
|
+
bcreated = true;
|
582
|
+
|
583
|
+
return 0;
|
584
|
+
}
|
585
|
+
|
586
|
+
long GenModelOsi::CreateModel(string filename, int type, string dn)
|
587
|
+
{
|
588
|
+
OsiData* d = static_cast<OsiData*>(solverdata);
|
589
|
+
|
590
|
+
switch (type)
|
591
|
+
{
|
592
|
+
case 0: d->model->readMps(filename.c_str()); break;
|
593
|
+
case 1: d->model->readLp(filename.c_str()); break;
|
594
|
+
case 2: d->model->readGMPL(filename.c_str(), (dn == "" ? NULL : dn.c_str())); break;
|
595
|
+
default: d->model->readMps(filename.c_str()); break;
|
596
|
+
}
|
597
|
+
|
598
|
+
//ReadFromObject(this, d->model);
|
599
|
+
|
600
|
+
//ReadFromFile(static_cast<GenModel*>(this), filename, type);
|
601
|
+
//SetNumbers();
|
602
|
+
//CreateModel();
|
603
|
+
bcreated = true;
|
604
|
+
|
605
|
+
return 0;
|
606
|
+
}
|
607
|
+
|
608
|
+
long GenModelOsi::Init(string name) //, int type)
|
609
|
+
{
|
610
|
+
try {
|
611
|
+
int type = 0;
|
612
|
+
if(solverdata == NULL)
|
613
|
+
solverdata = new OsiData();
|
614
|
+
else
|
615
|
+
{
|
616
|
+
static_cast<OsiData*>(solverdata)->Delete();
|
617
|
+
static_cast<OsiData*>(solverdata)->Reset();
|
618
|
+
}
|
619
|
+
|
620
|
+
OsiData* d = static_cast<OsiData*>(solverdata);
|
621
|
+
|
622
|
+
d->solvertype = type;
|
623
|
+
if(type==0)
|
624
|
+
{
|
625
|
+
if(boolParam.count("qp_mat") > 0 && boolParam["qp_mat"] && !vars.qi.empty())
|
626
|
+
d->model = new GenModelOsiInterface();
|
627
|
+
else
|
628
|
+
d->model = new OsiClpSolverInterface();
|
629
|
+
}
|
630
|
+
/*else if(type==1)
|
631
|
+
d->model = new OsiVolSolverInterface();
|
632
|
+
else if(type==2)
|
633
|
+
d->model = new OsiGlpkSolverInterface();
|
634
|
+
else if(type==3)
|
635
|
+
d->model = new OsiSpxSolverInterface();
|
636
|
+
else if(type==4)
|
637
|
+
d->model = new OsiCpxSolverInterface();
|
638
|
+
else if(type==5)
|
639
|
+
d->model = new OsiGrbSolverInterface();
|
640
|
+
else
|
641
|
+
d->model = new OsiClpSolverInterface();*/
|
642
|
+
|
643
|
+
d->model->setStrParam(OsiProbName, name);
|
644
|
+
|
645
|
+
|
646
|
+
SetParam("log_file", 0, "str", "Failure to set the log file", false);
|
647
|
+
|
648
|
+
// General settings
|
649
|
+
SetParam("log_output_stdout", 0, "bool", "Failure to turn on/off log output to stdout", false);
|
650
|
+
SetParam("log_level", 0, "long", "Failure to set log level", false);
|
651
|
+
SetParam("use_data_checking", 0, "bool", "Failure to turn on/off data checking", false);
|
652
|
+
//SetParam("nb_threads", 0, "long", "Failure to set the number of threads", false);
|
653
|
+
SetParam("use_preprocessor", 0, "bool", "Failure to use preprocessor", false);
|
654
|
+
|
655
|
+
// MIP settings
|
656
|
+
SetParam("nb_cut_pass", 0, "long", "Failure to set the number of cut pass", false);
|
657
|
+
SetParam("feasibility_pump_level", 0, "long", "Failure to set the feasibility pump level", false);
|
658
|
+
SetParam("probing_level", 0, "long", "Failure to set the probing level", false);
|
659
|
+
SetParam("mip_emphasis", 0, "long", "Failure to set the MIP emphasis", false);
|
660
|
+
SetParam("use_cut_callback", 0, "bool", "Failure to use preprocessor", false);
|
661
|
+
|
662
|
+
// Tolerance and limits
|
663
|
+
|
664
|
+
if(longParam.count("max_iteration_limit") == 0) longParam["max_iteration_limit"] = 99999999;
|
665
|
+
SetParam("max_iteration_limit", OsiMaxNumIteration, "long", "Failure to set the maximal number of simplex iterations");
|
666
|
+
if(dblParam.count("bounds_feasibility_tolerance") == 0) dblParam["bounds_feasibility_tolerance"] = 1e-9;
|
667
|
+
SetParam("bounds_feasibility_tolerance", OsiPrimalTolerance, "dbl", "Failure to set bounds feasibility tolerance");
|
668
|
+
SetParam("bounds_feasibility_tolerance", OsiDualTolerance, "dbl", "Failure to set bounds feasibility tolerance");
|
669
|
+
SetParam("optimality_tolerance", 0, "dbl", "Failure to set optimality tolerance", false);
|
670
|
+
SetParam("markowitz_tolerance", 0, "dbl", "Failure to set Markowitz tolerance", false);
|
671
|
+
SetParam("absolute_mip_gap_tolerance", 0, "dbl", "Failure to set absolute gap tolerance", false);
|
672
|
+
SetParam("relative_mip_gap_tolerance", 0, "dbl", "Failure to set relative gap tolerance", false);
|
673
|
+
SetParam("lp_objective_limit", OsiPrimalObjectiveLimit, "dbl", "Failure to set lp objective limit");
|
674
|
+
SetParam("lp_objective_limit", OsiDualObjectiveLimit, "dbl", "Failure to set lp objective limit");
|
675
|
+
|
676
|
+
// int params
|
677
|
+
//ClpMaxNumIterationHotStart : The maximum number of iterations Clp can execute in hotstart before terminating
|
678
|
+
|
679
|
+
// double params
|
680
|
+
// ClpDualObjectiveLimit : Set Dual objective limit. This is to be used as a termination criteria in methods where the dual objective monotonically changes (dual simplex)
|
681
|
+
// ClpObjOffset : Objective function constant. This the value of the constant term in the objective function
|
682
|
+
|
683
|
+
// OsiHintParam {
|
684
|
+
// OsiDoPresolveInInitial = 0, OsiDoDualInInitial, OsiDoPresolveInResolve, OsiDoDualInResolve,
|
685
|
+
// OsiDoScale, OsiDoCrash, OsiDoReducePrint, OsiDoInBranchAndCut,
|
686
|
+
// OsiLastHintParam
|
687
|
+
//}
|
688
|
+
// OsiHintStrength { OsiHintIgnore = 0, OsiHintTry, OsiHintDo, OsiForceDo }
|
689
|
+
|
690
|
+
|
691
|
+
// http://www.coin-or.org/Cbc/cbcuserguide.html
|
692
|
+
|
693
|
+
} catch (string e) {
|
694
|
+
printf("Error : %s\n", e.c_str());
|
695
|
+
}
|
696
|
+
|
697
|
+
binit = true;
|
698
|
+
|
699
|
+
return 0;
|
700
|
+
}
|
701
|
+
|
702
|
+
long GenModelOsi::SetDirectParam(int whichparam, genmodel_param value, string type, string message)
|
703
|
+
{
|
704
|
+
bool status = true;
|
705
|
+
if(type == "dbl")
|
706
|
+
status = (static_cast<OsiData*>(solverdata))->model->setDblParam(OsiDblParam(whichparam), value.dblval);
|
707
|
+
else if(type == "long")
|
708
|
+
status = (static_cast<OsiData*>(solverdata))->model->setIntParam(OsiIntParam(whichparam), value.longval);
|
709
|
+
else if(type == "str")
|
710
|
+
status = (static_cast<OsiData*>(solverdata))->model->setStrParam(OsiStrParam(whichparam), value.strval);
|
711
|
+
if ( !status )
|
712
|
+
return ThrowError(message);
|
713
|
+
return 0;
|
714
|
+
}
|
715
|
+
|
716
|
+
long GenModelOsi::SetParam(string param, int whichparam, string type, string message, bool implemented)
|
717
|
+
{
|
718
|
+
bool notimplmessage = boolParam.count("throw_on_unimplemeted_option") > 0 && boolParam["throw_on_unimplemeted_option"];
|
719
|
+
|
720
|
+
if(type == "dbl")
|
721
|
+
{
|
722
|
+
if(dblParam.count(param) > 0 && implemented)
|
723
|
+
SetDirectParam(whichparam, dbl2param(dblParam[param]), type, message);
|
724
|
+
else if(notimplmessage && !implemented && dblParam.count(param) > 0)
|
725
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
726
|
+
}
|
727
|
+
else if(type == "long")
|
728
|
+
{
|
729
|
+
if(longParam.count(param) > 0 && implemented)
|
730
|
+
SetDirectParam(whichparam, long2param(longParam[param]), type, message);
|
731
|
+
else if(notimplmessage && !implemented && longParam.count(param) > 0)
|
732
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
733
|
+
}
|
734
|
+
else if(type == "str")
|
735
|
+
{
|
736
|
+
if(strParam.count(param) > 0 && implemented)
|
737
|
+
SetDirectParam(whichparam, str2param(strParam[param]), type, message);
|
738
|
+
else if(notimplmessage && !implemented && strParam.count(param) > 0)
|
739
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
740
|
+
}
|
741
|
+
else if(type == "bool")
|
742
|
+
{
|
743
|
+
if(boolParam.count(param) > 0 && implemented)
|
744
|
+
{
|
745
|
+
if(boolParam[param])
|
746
|
+
SetDirectParam(whichparam, long2param(0), "long", message);
|
747
|
+
else
|
748
|
+
SetDirectParam(whichparam, long2param(1), "long", message);
|
749
|
+
}
|
750
|
+
else if(notimplmessage && !implemented && boolParam.count(param) > 0)
|
751
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
752
|
+
}
|
753
|
+
|
754
|
+
return 0;
|
755
|
+
}
|
756
|
+
|
757
|
+
long GenModelOsi::AddSolverRow(vector<int>& ind, vector<double>& val, double rhs, char sense, string name)
|
758
|
+
{
|
759
|
+
if(!bcreated)
|
760
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
761
|
+
|
762
|
+
AddModelRow(ind, val, rhs, sense, name);
|
763
|
+
AddCut(&ind[0], &val[0], int(ind.size()), rhs, sense, name.c_str());
|
764
|
+
|
765
|
+
return 0;
|
766
|
+
}
|
767
|
+
|
768
|
+
long GenModelOsi::AddCut(int* cols, double* vals, int nz, double rhs, char sense, const char* name)
|
769
|
+
{
|
770
|
+
if(!bcreated)
|
771
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
772
|
+
|
773
|
+
OsiData* d = (OsiData*)solverdata;
|
774
|
+
|
775
|
+
double lb = rhs;
|
776
|
+
double ub = rhs;
|
777
|
+
|
778
|
+
if(sense == 'L')
|
779
|
+
lb = -COIN_DBL_MAX;
|
780
|
+
else if(sense == 'G')
|
781
|
+
ub = COIN_DBL_MAX;
|
782
|
+
|
783
|
+
d->model->addRow(nz, cols, vals, lb, ub);
|
784
|
+
d->nr++;
|
785
|
+
|
786
|
+
return 0;
|
787
|
+
}
|
788
|
+
|
789
|
+
long GenModelOsi::AddSolverCol(vector<int>& ind, vector<double>& val, double obj, double lb, double ub, string name, char type)
|
790
|
+
{
|
791
|
+
if(!bcreated)
|
792
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
793
|
+
|
794
|
+
AddModelCol(ind, val, obj, lb, ub, name, type);
|
795
|
+
AddCol(&ind[0], &val[0], int(ind.size()), obj, lb, ub, name.c_str(), type);
|
796
|
+
|
797
|
+
return 0;
|
798
|
+
}
|
799
|
+
|
800
|
+
|
801
|
+
long GenModelOsi::AddCol(int* newi, double* newcol, int nz, double obj, double lb, double ub, const char* name, char type)
|
802
|
+
{
|
803
|
+
if(!bcreated)
|
804
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
805
|
+
|
806
|
+
OsiData* d = (OsiData*)solverdata;
|
807
|
+
d->model->addCol(nz, newi, newcol, lb, ub, obj);
|
808
|
+
d->nc++;
|
809
|
+
|
810
|
+
return 0;
|
811
|
+
}
|
812
|
+
|
813
|
+
long GenModelOsi::Clean()
|
814
|
+
{
|
815
|
+
if(solverdata != NULL)
|
816
|
+
delete static_cast<OsiData*>(solverdata);
|
817
|
+
|
818
|
+
return 0;
|
819
|
+
}
|
820
|
+
|
821
|
+
long OsiData::Reset()
|
822
|
+
{
|
823
|
+
model = NULL;
|
824
|
+
mipmodel = NULL;
|
825
|
+
mat_beg = NULL;
|
826
|
+
/*Q_beg = NULL;
|
827
|
+
Q_r = NULL;
|
828
|
+
Q_v = NULL;*/
|
829
|
+
mat_r = NULL;
|
830
|
+
mat_v = NULL;
|
831
|
+
lrhs = NULL;
|
832
|
+
urhs = NULL;
|
833
|
+
ub = NULL;
|
834
|
+
lb = NULL;
|
835
|
+
typei = NULL;
|
836
|
+
typec = NULL;
|
837
|
+
obj = NULL;
|
838
|
+
cname = NULL;
|
839
|
+
rname = NULL;
|
840
|
+
|
841
|
+
return 0;
|
842
|
+
}
|
843
|
+
|
844
|
+
OsiData::OsiData()
|
845
|
+
{
|
846
|
+
Reset();
|
847
|
+
}
|
848
|
+
|
849
|
+
OsiData::~OsiData()
|
850
|
+
{
|
851
|
+
Delete();
|
852
|
+
}
|
853
|
+
long OsiData::Delete()
|
854
|
+
{
|
855
|
+
//if(model != NULL)
|
856
|
+
// delete[] model;
|
857
|
+
if(mat_beg != NULL)
|
858
|
+
delete[] mat_beg;
|
859
|
+
if(mat_r != NULL)
|
860
|
+
delete[] mat_r;
|
861
|
+
if(mat_v != NULL)
|
862
|
+
delete[] mat_v;
|
863
|
+
if(lrhs != NULL)
|
864
|
+
delete[] lrhs;
|
865
|
+
if(obj != NULL)
|
866
|
+
delete[] obj;
|
867
|
+
if(urhs != NULL)
|
868
|
+
delete[] urhs;
|
869
|
+
if(ub != NULL)
|
870
|
+
delete[] ub;
|
871
|
+
if(lb != NULL)
|
872
|
+
delete[] lb;
|
873
|
+
if(typei != NULL)
|
874
|
+
delete[] typei;
|
875
|
+
if(typec != NULL)
|
876
|
+
delete[] typec;
|
877
|
+
|
878
|
+
if(cname != NULL)
|
879
|
+
{
|
880
|
+
for(long i = 0; i < nc; i++)
|
881
|
+
delete[] cname[i];
|
882
|
+
}
|
883
|
+
delete[] cname;
|
884
|
+
if(rname != NULL)
|
885
|
+
{
|
886
|
+
for(long i = 0; i < nr; i++)
|
887
|
+
delete[] rname[i];
|
888
|
+
}
|
889
|
+
delete[] rname;
|
890
|
+
|
891
|
+
return 0;
|
892
|
+
}
|