genmodel 0.0.42 → 0.0.44
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 +13 -5
- data/ext/Genmodel/GenModel.h +2 -0
- data/ext/Genmodel/GenModelBase.cpp +26 -6
- data/ext/Genmodel/GenModelCplex.cpp +283 -68
- data/ext/Genmodel/GenModelCplex.h +54 -1
- data/ext/Genmodel/GenModelOsi.cpp +29 -24
- data/ext/Genmodel/GenModelOsi.h +3 -0
- data/ext/Genmodel/Genmodel.cpp +11086 -6457
- metadata +4 -4
@@ -10,7 +10,7 @@ string getcplexerror(CPXENVptr env, int status)
|
|
10
10
|
char errmsg[4096];
|
11
11
|
snprintf(errmsg, 4096, "CPLEX error %d : ", status);
|
12
12
|
string prefix = string(errmsg);
|
13
|
-
|
13
|
+
CPXXgeterrorstring (env, status, errmsg);
|
14
14
|
return prefix+string(errmsg);
|
15
15
|
}
|
16
16
|
|
@@ -30,7 +30,7 @@ long GenModelCplex::WriteProblemToLpFile(string filename)
|
|
30
30
|
throw string("WriteProblemToLpFile() not available : Problem not created yet;");
|
31
31
|
|
32
32
|
CplexData* d = static_cast<CplexData*>(solverdata);
|
33
|
-
|
33
|
+
CPXXwriteprob(d->env, d->lp, filename.c_str(), "LP");
|
34
34
|
return 0;
|
35
35
|
}
|
36
36
|
|
@@ -40,39 +40,52 @@ long GenModelCplex::WriteSolutionToFile(string filename)
|
|
40
40
|
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
41
41
|
|
42
42
|
CplexData* d = static_cast<CplexData*>(solverdata);
|
43
|
-
|
43
|
+
CPXXsolwrite (d->env, d->lp, filename.c_str());
|
44
44
|
return 0;
|
45
45
|
}
|
46
46
|
|
47
47
|
long GenModelCplex::Solve()
|
48
48
|
{
|
49
|
+
|
49
50
|
if(!bcreated)
|
50
51
|
throw string("Solve() not available : Problem not created yet");
|
52
|
+
try{
|
51
53
|
CplexData* d = static_cast<CplexData*>(solverdata);
|
52
54
|
int status = 0;
|
53
55
|
if(boolParam.count("mip") > 0 && boolParam["mip"])
|
54
|
-
status =
|
56
|
+
status = CPXXmipopt(d->env, d->lp);
|
55
57
|
else if(boolParam.count("qp") > 0 && boolParam["qp"])
|
56
|
-
status =
|
58
|
+
status = CPXXqpopt(d->env, d->lp);
|
57
59
|
else if(strParam.count("algo") > 0 && strParam["algo"] == "interior")
|
58
|
-
status =
|
60
|
+
status = CPXXbaropt(d->env, d->lp);
|
59
61
|
else if(strParam.count("algo") > 0 && strParam["algo"] == "dual")
|
60
|
-
status =
|
62
|
+
status = CPXXdualopt(d->env, d->lp);
|
61
63
|
else if(strParam.count("algo") > 0 && strParam["algo"] == "primal")
|
62
|
-
status =
|
64
|
+
status = CPXXprimopt(d->env, d->lp);
|
63
65
|
else if(strParam.count("algo") > 0 && strParam["algo"] == "concurrent")
|
64
66
|
{
|
65
67
|
//printf("choosing concurrent algo\n");
|
66
|
-
|
67
|
-
status =
|
68
|
+
CPXXsetintparam (d->env, CPX_PARAM_LPMETHOD, CPX_ALG_CONCURRENT);
|
69
|
+
status = CPXXlpopt(d->env, d->lp);
|
68
70
|
}
|
69
71
|
else if(strParam.count("algo") > 0 && strParam["algo"] == "sifting")
|
70
72
|
{
|
71
|
-
|
72
|
-
status =
|
73
|
+
CPXXsetintparam (d->env, CPX_PARAM_LPMETHOD, CPX_ALG_SIFTING);
|
74
|
+
status = CPXXlpopt(d->env, d->lp);
|
73
75
|
}
|
74
76
|
else
|
75
|
-
status =
|
77
|
+
status = CPXXlpopt(d->env, d->lp);
|
78
|
+
if(status)
|
79
|
+
ThrowError(getcplexerror(d->env, status)+string(". ")+string("Solve() : Solve failed"));
|
80
|
+
}
|
81
|
+
catch(string str)
|
82
|
+
{
|
83
|
+
throw string("Solve() error : ")+str;
|
84
|
+
}
|
85
|
+
catch(...)
|
86
|
+
{
|
87
|
+
throw ThrowError(string("Solve() : Solve failed with unknown error"));
|
88
|
+
}
|
76
89
|
|
77
90
|
return 0;
|
78
91
|
}
|
@@ -81,6 +94,7 @@ long GenModelCplex::SetSol()
|
|
81
94
|
{
|
82
95
|
if(!bcreated)
|
83
96
|
throw string("SetSol() not available : Problem not created yet");
|
97
|
+
try {
|
84
98
|
vars.sol.clear();
|
85
99
|
vars.sol.resize(vars.n,0);
|
86
100
|
vars.rc.clear();
|
@@ -102,16 +116,16 @@ long GenModelCplex::SetSol()
|
|
102
116
|
d->rcost = new double[nc];
|
103
117
|
d->slack = new double[nr];
|
104
118
|
|
105
|
-
int tempstat =
|
119
|
+
int tempstat = CPXXgetstat (d->env, d->lp);
|
106
120
|
int tempfeas;
|
107
121
|
int tempdualfeas;
|
108
122
|
int temphassol;
|
109
|
-
int currmeth =
|
123
|
+
int currmeth = CPXXgetmethod(d->env, d->lp);
|
110
124
|
|
111
125
|
|
112
|
-
status =
|
126
|
+
status = CPXXsolninfo(d->env, d->lp, &currmeth, &temphassol, &tempfeas, &tempdualfeas);
|
113
127
|
if ( status )
|
114
|
-
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set set solution (
|
128
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set set solution (CPXXsolninfo)"));
|
115
129
|
|
116
130
|
feasible = static_cast<bool>(tempfeas);
|
117
131
|
dualfeasible = static_cast<bool>(tempdualfeas);
|
@@ -121,11 +135,11 @@ long GenModelCplex::SetSol()
|
|
121
135
|
return 0;
|
122
136
|
|
123
137
|
if(boolParam.count("mip") > 0 && boolParam["mip"])
|
124
|
-
status =
|
138
|
+
status = CPXXsolution (d->env, d->lp, &solstat, &objval, d->x, NULL, NULL, NULL);
|
125
139
|
else
|
126
|
-
status =
|
140
|
+
status = CPXXsolution (d->env, d->lp, &solstat, &objval, d->x, d->dual, d->slack, d->rcost);
|
127
141
|
if ( status )
|
128
|
-
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set set solution (
|
142
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set set solution (CPXXsolution)"));
|
129
143
|
|
130
144
|
solstat = tempstat;
|
131
145
|
|
@@ -143,6 +157,15 @@ long GenModelCplex::SetSol()
|
|
143
157
|
|
144
158
|
if(boolParam.count("print_version") > 0 && boolParam["print_version"])
|
145
159
|
printf("*********** Genmodel version = %s ***********\n", version.c_str());
|
160
|
+
}
|
161
|
+
catch(string str)
|
162
|
+
{
|
163
|
+
throw string("SetSol() error : ")+str;
|
164
|
+
}
|
165
|
+
catch(...)
|
166
|
+
{
|
167
|
+
throw ThrowError(string("SetSol() : Solution retrieval failed with unknown error"));
|
168
|
+
}
|
146
169
|
|
147
170
|
return 0;
|
148
171
|
}
|
@@ -162,9 +185,9 @@ long GenModelCplex::AddCut(int* cols, double* vals, int nz, double rhs, char sen
|
|
162
185
|
if(!bcreated)
|
163
186
|
return ThrowError("AddCut() not available : Problem not created yet");
|
164
187
|
CplexData* d = (CplexData*)solverdata;
|
165
|
-
|
188
|
+
int64_t rmatbeg = 0;
|
166
189
|
|
167
|
-
|
190
|
+
CPXXaddrows(d->env, d->lp, 0, 1, nz, &rhs, &sense, &rmatbeg, cols, vals, NULL, (char**)(&name));
|
168
191
|
d->nr++;
|
169
192
|
|
170
193
|
return 0;
|
@@ -175,7 +198,7 @@ long GenModelCplex::AddSolverCol(vector<int>& ind, vector<double>& val, double o
|
|
175
198
|
if(!bcreated)
|
176
199
|
return ThrowError("AddSolverCol() not available : Problem not created yet");
|
177
200
|
AddModelCol(ind, val, obj, lb, ub, name, type);
|
178
|
-
AddCol(&ind[0], &val[0],
|
201
|
+
AddCol(&ind[0], &val[0], ind.size(), obj, lb, ub, name.c_str(), type);
|
179
202
|
|
180
203
|
return 0;
|
181
204
|
}
|
@@ -185,7 +208,7 @@ long GenModelCplex::AddCol(int* newi, double* newcol, int nz, double obj, double
|
|
185
208
|
if(!bcreated)
|
186
209
|
return ThrowError("AddCol() not available : Problem not created yet");
|
187
210
|
CplexData* d = (CplexData*)solverdata;
|
188
|
-
|
211
|
+
int64_t cmatbeg = 0;
|
189
212
|
|
190
213
|
double clb = lb;
|
191
214
|
if(clb == numeric_limits<double>::infinity())
|
@@ -194,16 +217,16 @@ long GenModelCplex::AddCol(int* newi, double* newcol, int nz, double obj, double
|
|
194
217
|
clb = -CPX_INFBOUND;
|
195
218
|
|
196
219
|
double cub = ub;
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
220
|
+
if(cub == numeric_limits<double>::infinity())
|
221
|
+
cub = CPX_INFBOUND;
|
222
|
+
else if(cub == -numeric_limits<double>::infinity())
|
223
|
+
cub = -CPX_INFBOUND;
|
201
224
|
|
202
|
-
|
225
|
+
CPXXaddcols(d->env, d->lp, 1, nz, &obj, &cmatbeg, newi, newcol, &clb, &cub, (char**)(&name));
|
203
226
|
if(type != 'C')
|
204
227
|
{
|
205
228
|
int cind = d->nc;
|
206
|
-
|
229
|
+
CPXXchgctype(d->env, d->lp, 1, &cind, &type);
|
207
230
|
}
|
208
231
|
d->nc++;
|
209
232
|
|
@@ -222,9 +245,9 @@ long GenModelCplex::CreateModel()
|
|
222
245
|
d->onr = nr;
|
223
246
|
|
224
247
|
if(boolParam.count("maximize") > 0 && boolParam["maximize"])
|
225
|
-
|
248
|
+
CPXXchgobjsen (d->env, d->lp, CPX_MAX);
|
226
249
|
else
|
227
|
-
|
250
|
+
CPXXchgobjsen (d->env, d->lp, CPX_MIN);
|
228
251
|
d->lrhs = new double[nr];
|
229
252
|
d->urhs = new double[nr];
|
230
253
|
d->sense = new char[nr];
|
@@ -291,12 +314,12 @@ long GenModelCplex::CreateModel()
|
|
291
314
|
|
292
315
|
//printf("%ld (%s) -> %f %f %f %c\n", i, vars.name[i].c_str(), d->obj[i], d->lb[i], d->ub[i], d->type[i]);
|
293
316
|
}
|
294
|
-
status =
|
317
|
+
status = CPXXnewrows (d->env, d->lp, nr, d->lrhs, d->sense, d->urhs, d->rname);
|
295
318
|
if ( status )
|
296
319
|
{
|
297
320
|
char errmsg[1024];
|
298
321
|
fprintf (stderr, "Could not create new rows.\n");
|
299
|
-
|
322
|
+
CPXXgeterrorstring (d->env, status, errmsg);
|
300
323
|
fprintf (stderr, "%s", errmsg);
|
301
324
|
return 1;
|
302
325
|
}
|
@@ -304,23 +327,23 @@ long GenModelCplex::CreateModel()
|
|
304
327
|
//printf("Row added!\n");
|
305
328
|
|
306
329
|
if(boolParam.count("mip") > 0 && boolParam["mip"])
|
307
|
-
status =
|
330
|
+
status = CPXXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, d->type, d->cname);
|
308
331
|
else
|
309
|
-
status =
|
332
|
+
status = CPXXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, NULL, NULL);
|
310
333
|
if ( status )
|
311
334
|
{
|
312
335
|
char errmsg[1024];
|
313
336
|
fprintf (stderr, "Could not create new cols.\n");
|
314
|
-
|
337
|
+
CPXXgeterrorstring (d->env, status, errmsg);
|
315
338
|
fprintf (stderr, "%s", errmsg);
|
316
339
|
return 1;
|
317
340
|
}
|
318
|
-
//status =
|
341
|
+
//status = CPXXnewcols (env, lp, nc, obj, lb, ub, NULL, colname);
|
319
342
|
if ( status )
|
320
343
|
return 1;
|
321
344
|
//else
|
322
345
|
//printf("Col added!\n");
|
323
|
-
status =
|
346
|
+
status = CPXXchgcoeflist (d->env, d->lp, nz, d->mat_r, d->mat_c, d->mat_v);
|
324
347
|
if ( status )
|
325
348
|
return 1;
|
326
349
|
|
@@ -330,7 +353,7 @@ long GenModelCplex::CreateModel()
|
|
330
353
|
|
331
354
|
vector<vector<pair<int,double> > > qptemp;
|
332
355
|
qptemp.resize(nc);
|
333
|
-
|
356
|
+
int64_t* qpbeg = NULL;
|
334
357
|
int* qpnum = NULL;
|
335
358
|
int* qpind = NULL;
|
336
359
|
double* qpv = NULL;
|
@@ -339,7 +362,7 @@ long GenModelCplex::CreateModel()
|
|
339
362
|
if(!vars.qi.empty())
|
340
363
|
{
|
341
364
|
boolParam["qp"] = true;
|
342
|
-
qpbeg = new
|
365
|
+
qpbeg = new int64_t[nc];
|
343
366
|
qpnum = new int[nc];
|
344
367
|
}
|
345
368
|
if(boolParam.count("qp_mat") == 0 || boolParam["qp_mat"])
|
@@ -371,7 +394,7 @@ long GenModelCplex::CreateModel()
|
|
371
394
|
qpnz++;
|
372
395
|
}
|
373
396
|
}
|
374
|
-
status =
|
397
|
+
status = CPXXcopyquad(d->env, d->lp, qpbeg, qpnum, qpind, qpv);
|
375
398
|
delete[] qpbeg;
|
376
399
|
delete[] qpnum;
|
377
400
|
delete[] qpind;
|
@@ -390,12 +413,12 @@ long GenModelCplex::CreateModel()
|
|
390
413
|
return 0;
|
391
414
|
}
|
392
415
|
|
393
|
-
long AddQuadraticVector(vector<
|
416
|
+
long AddQuadraticVector(vector<size_t>& ind, vector<double>& val)
|
394
417
|
{
|
395
418
|
return 0;
|
396
419
|
}
|
397
420
|
|
398
|
-
long AddQuadraticMatrix(vector<
|
421
|
+
long AddQuadraticMatrix(vector<size_t>& indi, vector<size_t>& indj, vector<double>& val)
|
399
422
|
{
|
400
423
|
return 0;
|
401
424
|
}
|
@@ -430,7 +453,7 @@ long GenModelCplex::ChangeBulkBounds(int count, int * ind, char * type, double *
|
|
430
453
|
}
|
431
454
|
}
|
432
455
|
|
433
|
-
|
456
|
+
CPXXchgbds(d->env, d->lp, count, ind, type, vals);
|
434
457
|
|
435
458
|
return 0;
|
436
459
|
}
|
@@ -446,7 +469,7 @@ long GenModelCplex::ChangeBulkObjectives(int count, int * ind, double * vals)
|
|
446
469
|
vars.obj[i] = vals[i];
|
447
470
|
}
|
448
471
|
|
449
|
-
|
472
|
+
CPXXchgobj(d->env, d->lp, count, ind, vals);
|
450
473
|
|
451
474
|
return 0;
|
452
475
|
}
|
@@ -473,7 +496,7 @@ long GenModelCplex::ChangeBulkNz(int count, int* rind, int* cind, double * vals)
|
|
473
496
|
consts[rind[i]].AddNz(cind[i], vals[i]);
|
474
497
|
}
|
475
498
|
|
476
|
-
|
499
|
+
CPXXchgcoeflist(d->env, d->lp, count, rind, cind, vals);
|
477
500
|
|
478
501
|
return 0;
|
479
502
|
}
|
@@ -485,9 +508,9 @@ long GenModelCplex::DeleteMipStarts()
|
|
485
508
|
if(!bcreated)
|
486
509
|
return ThrowError("ChangeBulkNz() not available : Problem not created yet");
|
487
510
|
CplexData* d = (CplexData*)solverdata;
|
488
|
-
int n =
|
511
|
+
int n = CPXXgetnummipstarts(d->env, d->lp);
|
489
512
|
if (n > 0)
|
490
|
-
|
513
|
+
CPXXdelmipstarts(d->env, d->lp, 0, n - 1);
|
491
514
|
|
492
515
|
return 0;
|
493
516
|
}
|
@@ -498,9 +521,9 @@ double GenModelCplex::GetMIPRelativeGap()
|
|
498
521
|
return ThrowError("ChangeBulkNz() not available : Problem not created yet");
|
499
522
|
CplexData* d = (CplexData*)solverdata;
|
500
523
|
double gap = 0, bestobjval = 0;
|
501
|
-
|
502
|
-
if (bestobjval > 0) // If the optimal solution is found by the presolve, the
|
503
|
-
|
524
|
+
CPXXgetbestobjval(d->env, d->lp, &bestobjval);
|
525
|
+
if (bestobjval > 0) // If the optimal solution is found by the presolve, the CPXXgetbestobjval = 0, and the CPXXgetmiprelgap ~ 1
|
526
|
+
CPXXgetmiprelgap(d->env, d->lp, &gap);
|
504
527
|
|
505
528
|
return gap;
|
506
529
|
}
|
@@ -511,7 +534,7 @@ long GenModelCplex::SwitchToMip()
|
|
511
534
|
return ThrowError("SwitchToMip() not available : Problem not created yet");
|
512
535
|
vector<int> ind;
|
513
536
|
vector<char> type;
|
514
|
-
for(
|
537
|
+
for(size_t i = 0; i < vars.type.size(); i++)
|
515
538
|
{
|
516
539
|
if(vars.type[i] == 'B' || vars.type[i] == 'I' || vars.type[i] == 'S' || vars.type[i] == 'N')
|
517
540
|
{
|
@@ -520,7 +543,7 @@ long GenModelCplex::SwitchToMip()
|
|
520
543
|
}
|
521
544
|
}
|
522
545
|
CplexData* d = static_cast<CplexData*>(solverdata);
|
523
|
-
|
546
|
+
CPXXchgctype(d->env, d->lp, ind.size(), &(ind[0]), &(type[0]));
|
524
547
|
boolParam["mip"] = true;
|
525
548
|
|
526
549
|
return 0;
|
@@ -532,7 +555,7 @@ long GenModelCplex::SwitchToLp()
|
|
532
555
|
return ThrowError("SwitchToLp() not available : Problem not created yet");
|
533
556
|
vector<int> ind;
|
534
557
|
vector<char> type;
|
535
|
-
for(
|
558
|
+
for(size_t i = 0; i < vars.type.size(); i++)
|
536
559
|
{
|
537
560
|
if(vars.type[i] == 'B' || vars.type[i] == 'I' || vars.type[i] == 'S' || vars.type[i] == 'N')
|
538
561
|
{
|
@@ -541,12 +564,153 @@ long GenModelCplex::SwitchToLp()
|
|
541
564
|
}
|
542
565
|
}
|
543
566
|
CplexData* d = static_cast<CplexData*>(solverdata);
|
544
|
-
|
567
|
+
CPXXchgctype(d->env, d->lp, ind.size(), &(ind[0]), &(type[0]));
|
545
568
|
boolParam["mip"] = false;
|
546
569
|
|
547
570
|
return 0;
|
548
571
|
}
|
549
572
|
|
573
|
+
string SolverInfo::inspect() const
|
574
|
+
{
|
575
|
+
return to_s();
|
576
|
+
}
|
577
|
+
|
578
|
+
string SolverInfo::to_s() const
|
579
|
+
{
|
580
|
+
char tmp[10000];
|
581
|
+
string _cpx_results = cpx_results;
|
582
|
+
string _cpx_warning = cpx_warning;
|
583
|
+
string _cpx_error = cpx_error;
|
584
|
+
string _cpx_log = cpx_log;
|
585
|
+
size_t pos = 0;
|
586
|
+
while((pos = _cpx_results.find("\n", pos)) != std::string::npos) { _cpx_results.replace(pos, 1, "\\n"); pos += 2; }
|
587
|
+
pos = 0;
|
588
|
+
while((pos = _cpx_warning.find("\n", pos)) != std::string::npos) { _cpx_warning.replace(pos, 1, "\\n"); pos += 2; }
|
589
|
+
pos = 0;
|
590
|
+
while((pos = _cpx_error.find("\n", pos)) != std::string::npos) { _cpx_error.replace(pos, 1, "\\n"); pos += 2; }
|
591
|
+
pos = 0;
|
592
|
+
while((pos = _cpx_log.find("\n", pos)) != std::string::npos) { _cpx_log.replace(pos, 1, "\\n"); pos += 2; }
|
593
|
+
|
594
|
+
snprintf(tmp, 10000,
|
595
|
+
"{\n"
|
596
|
+
"\t\"relative_gap\" : \"%f\",\n"
|
597
|
+
"\t\"upper_bound\" : \"%f\",\n"
|
598
|
+
"\t\"lower_bound\" : \"%f\",\n"
|
599
|
+
"\t\"cutoff\" : \"%f\",\n"
|
600
|
+
"\t\"nb_node_solved\" : %lu,\n"
|
601
|
+
"\t\"nb_node_left\" : %lu,\n"
|
602
|
+
"\t\"nb_threads\" : %lu,\n"
|
603
|
+
"\t\"nb_iters\" : %lu,\n"
|
604
|
+
"\t\"nb_solutions\" : %lu,\n"
|
605
|
+
"\t\"nb_clique_cuts\" : %lu,\n"
|
606
|
+
"\t\"nb_cover_cuts\" : %lu,\n"
|
607
|
+
"\t\"nb_disjcut_cuts\" : %lu,\n"
|
608
|
+
"\t\"nb_flow_cover_cuts\" : %lu,\n"
|
609
|
+
"\t\"nb_flow_path_cuts\" : %lu,\n"
|
610
|
+
"\t\"nb_fractionnal_cuts\" : %lu,\n"
|
611
|
+
"\t\"nb_gub_cover_cuts\" : %lu,\n"
|
612
|
+
"\t\"nb_implied_bound_cuts\" : %lu,\n"
|
613
|
+
"\t\"nb_lift_project_cuts\" : %lu,\n"
|
614
|
+
"\t\"nb_flow_mc_flow_cuts\" : %lu,\n"
|
615
|
+
"\t\"nb_flow_mir_cuts\" : %lu,\n"
|
616
|
+
"\t\"nb_zero_half_cuts\" : %lu,\n"
|
617
|
+
"\t\"nb_user_cuts\" : %lu,\n"
|
618
|
+
"\t\"nb_lazy_cuts\" : %lu,\n"
|
619
|
+
"\t\"nb_soln_pool_cuts\" : %lu,\n"
|
620
|
+
"\t\"cpx_results\" : \"%s\",\n"
|
621
|
+
"\t\"cpx_warning\" : \"%s\",\n"
|
622
|
+
"\t\"cpx_error\" : \"%s\",\n"
|
623
|
+
"\t\"cpx_log\" : \"%s\",\n"
|
624
|
+
"\t\"status_str\" : \"%s\""
|
625
|
+
"}\n",
|
626
|
+
relative_gap,upper_bound,lower_bound,cutoff,nb_node_solved,nb_node_left,nb_threads,nb_iters,nb_solutions,nb_clique_cuts,nb_cover_cuts,nb_disjcut_cuts,
|
627
|
+
nb_flow_cover_cuts,nb_flow_path_cuts,nb_fractionnal_cuts,nb_gub_cover_cuts,nb_implied_bound_cuts,nb_lift_project_cuts,nb_flow_mc_flow_cuts,nb_flow_mir_cuts,
|
628
|
+
nb_zero_half_cuts,nb_user_cuts,nb_lazy_cuts,nb_soln_pool_cuts,_cpx_results.c_str(),_cpx_warning.c_str(),_cpx_error.c_str(),_cpx_log.c_str(), status_str.c_str()
|
629
|
+
);
|
630
|
+
|
631
|
+
return string(tmp);
|
632
|
+
}
|
633
|
+
|
634
|
+
SolverInfo GenModelCplex::GetSolverInfo()
|
635
|
+
{
|
636
|
+
if(!bcreated)
|
637
|
+
{
|
638
|
+
ThrowError("GetSolverInfo() not available : Problem not created yet");
|
639
|
+
return SolverInfo();
|
640
|
+
}
|
641
|
+
CplexData* d = static_cast<CplexData*>(solverdata);
|
642
|
+
printf("solstat = %ld\n", solstat);
|
643
|
+
if(solstat == numeric_limits<int>::infinity())
|
644
|
+
d->solver_info.status_str = "No status assigned.";
|
645
|
+
else
|
646
|
+
{
|
647
|
+
char status_str[CPXMESSAGEBUFSIZE];
|
648
|
+
char* _status = CPXXgetstatstring(d->env, solstat, status_str);
|
649
|
+
if (_status == NULL)
|
650
|
+
ThrowError(string("Failure to get the status string"));
|
651
|
+
d->solver_info.status_str = status_str;
|
652
|
+
printf("GetSolverInfo : status = %s [%s] [%s]\n", _status, status_str, d->solver_info.status_str.c_str());
|
653
|
+
}
|
654
|
+
|
655
|
+
return d->solver_info;
|
656
|
+
}
|
657
|
+
|
658
|
+
int mip_cb(CPXCENVptr env, void *cbdata, int wherefrom, void *cbhandle)
|
659
|
+
{
|
660
|
+
printf("Callback called\n");
|
661
|
+
GenModelCplex* pgm = static_cast<GenModelCplex*>(cbhandle);
|
662
|
+
CplexData* d = static_cast<CplexData*>(pgm->solverdata);
|
663
|
+
|
664
|
+
vector<vector<double> > solutions;
|
665
|
+
vector<double> solution_objvals;
|
666
|
+
|
667
|
+
if(pgm->boolParam.count("maximize") > 0 && pgm->boolParam["maximize"])
|
668
|
+
{
|
669
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_INTEGER, &(d->solver_info.lower_bound));
|
670
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_REMAINING, &(d->solver_info.upper_bound));
|
671
|
+
}
|
672
|
+
else
|
673
|
+
{
|
674
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_REMAINING, &(d->solver_info.lower_bound));
|
675
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_BEST_INTEGER, &(d->solver_info.upper_bound));
|
676
|
+
}
|
677
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_NODE_COUNT_LONG, &(d->solver_info.nb_node_solved));
|
678
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_NODES_LEFT_LONG, &(d->solver_info.nb_node_left));
|
679
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_MIP_REL_GAP, &(d->solver_info.relative_gap));
|
680
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_CUTOFF, &(d->solver_info.cutoff));
|
681
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_MIP_ITERATIONS_LONG, &(d->solver_info.nb_iters));
|
682
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_USER_THREADS, &(d->solver_info.nb_threads));
|
683
|
+
|
684
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_CLIQUE_COUNT, &(d->solver_info.nb_clique_cuts));
|
685
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_COVER_COUNT, &(d->solver_info.nb_cover_cuts));
|
686
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_DISJCUT_COUNT, &(d->solver_info.nb_disjcut_cuts));
|
687
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_FLOWCOVER_COUNT, &(d->solver_info.nb_flow_cover_cuts));
|
688
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_FLOWPATH_COUNT, &(d->solver_info.nb_flow_path_cuts));
|
689
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_FRACCUT_COUNT, &(d->solver_info.nb_fractionnal_cuts));
|
690
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_GUBCOVER_COUNT, &(d->solver_info.nb_gub_cover_cuts));
|
691
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_IMPLBD_COUNT, &(d->solver_info.nb_implied_bound_cuts));
|
692
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_LANDPCUT_COUNT, &(d->solver_info.nb_lift_project_cuts));
|
693
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_MCFCUT_COUNT, &(d->solver_info.nb_flow_mc_flow_cuts));
|
694
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_MIRCUT_COUNT, &(d->solver_info.nb_flow_mir_cuts));
|
695
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_ZEROHALFCUT_COUNT, &(d->solver_info.nb_zero_half_cuts));
|
696
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_USERCUT_COUNT, &(d->solver_info.nb_user_cuts));
|
697
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_TABLECUT_COUNT, &(d->solver_info.nb_lazy_cuts));
|
698
|
+
CPXXgetcallbackinfo(d->env, cbdata, wherefrom, CPX_CALLBACK_INFO_SOLNPOOLCUT_COUNT, &(d->solver_info.nb_soln_pool_cuts));
|
699
|
+
|
700
|
+
if(d->stop_solver)
|
701
|
+
return 1;
|
702
|
+
|
703
|
+
d->solver_info.nb_solutions = CPXXgetsolnpoolnumsolns(d->env, d->lp);
|
704
|
+
|
705
|
+
return d->original_mip_cb(env, cbdata, wherefrom, d->original_handle);
|
706
|
+
}
|
707
|
+
|
708
|
+
void msg_function(void* cbhandle, const char* msg)
|
709
|
+
{
|
710
|
+
string* p_str = static_cast<string*>(cbhandle);
|
711
|
+
(*p_str) += msg;
|
712
|
+
}
|
713
|
+
|
550
714
|
long GenModelCplex::Init(string name)
|
551
715
|
{
|
552
716
|
|
@@ -579,7 +743,7 @@ long GenModelCplex::Init(string name)
|
|
579
743
|
CplexData* d = static_cast<CplexData*>(solverdata);
|
580
744
|
int status = 0;
|
581
745
|
|
582
|
-
d->env =
|
746
|
+
d->env = CPXXopenCPLEX (&status);
|
583
747
|
|
584
748
|
// If an error occurs
|
585
749
|
if ( d->env == NULL )
|
@@ -591,11 +755,45 @@ long GenModelCplex::Init(string name)
|
|
591
755
|
// Log file
|
592
756
|
if(strParam.count("log_file") > 0)
|
593
757
|
{
|
594
|
-
d->cpxfileptr =
|
595
|
-
status =
|
596
|
-
if (
|
758
|
+
d->cpxfileptr = CPXXfopen(strParam["log_file"].c_str(), "w");
|
759
|
+
status = CPXXsetlogfile(d->env, d->cpxfileptr);
|
760
|
+
if (status)
|
597
761
|
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the log file"));
|
598
762
|
}
|
763
|
+
|
764
|
+
if(boolParam.count("fill_solver_info") > 0)
|
765
|
+
{
|
766
|
+
printf("solver_info ON\n");
|
767
|
+
/*status = CPXXgetmipcallbackfunc(d->env, &(d->original_mip_cb), &(d->original_handle));
|
768
|
+
if (status)
|
769
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to get the default mip callback function"));
|
770
|
+
|
771
|
+
status = CPXXsetmipcallbackfunc(d->env, mip_cb, this);
|
772
|
+
if (status)
|
773
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the mip callback function"));
|
774
|
+
*/
|
775
|
+
|
776
|
+
CPXCHANNELptr cpxresults, cpxwarning, cpxerror, cpxlog;
|
777
|
+
status = CPXXgetchannels(d->env, &cpxresults, &cpxwarning, &cpxerror, &cpxlog);
|
778
|
+
if (status)
|
779
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to get the solver channels"));
|
780
|
+
|
781
|
+
status = CPXXaddfuncdest(d->env, cpxresults, &(d->solver_info.cpx_results), msg_function);
|
782
|
+
if (status)
|
783
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the results channel callback function"));
|
784
|
+
|
785
|
+
status = CPXXaddfuncdest(d->env, cpxwarning, &(d->solver_info.cpx_warning), msg_function);
|
786
|
+
if (status)
|
787
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the warning channel callback function"));
|
788
|
+
|
789
|
+
status = CPXXaddfuncdest(d->env, cpxerror, &(d->solver_info.cpx_error), msg_function);
|
790
|
+
if (status)
|
791
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the error channel callback function"));
|
792
|
+
|
793
|
+
status = CPXXaddfuncdest(d->env, cpxlog, &(d->solver_info.cpx_log), msg_function);
|
794
|
+
if (status)
|
795
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the log channel callback function"));
|
796
|
+
}
|
599
797
|
|
600
798
|
// General settings
|
601
799
|
//boolParam["log_output_stdout"] = true;
|
@@ -627,6 +825,19 @@ long GenModelCplex::Init(string name)
|
|
627
825
|
}
|
628
826
|
|
629
827
|
// Tolerance and limits
|
828
|
+
|
829
|
+
SetParam("memory_emphasis", CPX_PARAM_MEMORYEMPHASIS, "bool", "Failure to set memory emphasis");
|
830
|
+
SetParam("node_file_memory_mode", CPX_PARAM_NODEFILEIND, "long", "Failure to set node file memory mode");
|
831
|
+
/*
|
832
|
+
0 No node file
|
833
|
+
1 Node file in memory and compressed; default
|
834
|
+
2 Node file on disk
|
835
|
+
3 Node file on disk and compressed
|
836
|
+
*/
|
837
|
+
SetParam("tree_memory_limit", CPX_PARAM_TRELIM, "dbl", "Failure to set tree memory limit"); // In megabytes
|
838
|
+
SetParam("work_memory_limit", CPX_PARAM_WORKMEM, "dbl", "Failure to set work memory limit"); // In megabytes
|
839
|
+
|
840
|
+
|
630
841
|
SetParam("time_limit", CPX_PARAM_TILIM, "dbl", "Failure to set time limit");
|
631
842
|
SetParam("max_iteration_limit", CPX_PARAM_ITLIM, "long", "Failure to set the maximal number of simplex iterations");
|
632
843
|
SetParam("bounds_feasibility_tolerance", CPX_PARAM_EPRHS, "dbl", "Failure to set bounds feasibility tolerance");
|
@@ -641,7 +852,7 @@ long GenModelCplex::Init(string name)
|
|
641
852
|
|
642
853
|
|
643
854
|
// Create the problem
|
644
|
-
d->lp =
|
855
|
+
d->lp = CPXXcreateprob (d->env, &status, name.c_str());
|
645
856
|
if ( d->lp == NULL )
|
646
857
|
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to create Cplex optimization problem"));
|
647
858
|
|
@@ -654,11 +865,11 @@ long GenModelCplex::SetDirectParam(int whichparam, genmodel_param value, string
|
|
654
865
|
{
|
655
866
|
int status = 0;
|
656
867
|
if(type == "dbl")
|
657
|
-
status =
|
868
|
+
status = CPXXsetdblparam (static_cast<CplexData*>(solverdata)->env, whichparam, value.dblval);
|
658
869
|
else if(type == "long")
|
659
|
-
status =
|
870
|
+
status = CPXXsetintparam (static_cast<CplexData*>(solverdata)->env, whichparam, value.longval);
|
660
871
|
else if(type == "str")
|
661
|
-
status =
|
872
|
+
status = CPXXsetstrparam (static_cast<CplexData*>(solverdata)->env, whichparam, value.strval);
|
662
873
|
if ( status )
|
663
874
|
return ThrowError(getcplexerror(static_cast<CplexData*>(solverdata)->env, status)+string(". ")+message);
|
664
875
|
|
@@ -721,7 +932,7 @@ long GenModelCplex::Init(string name) {return cpx_not_implemented();}
|
|
721
932
|
long GenModelCplex::CreateModel(string filename, int type, string dn) {return cpx_not_implemented();}
|
722
933
|
long GenModelCplex::CreateModel() {return cpx_not_implemented();}
|
723
934
|
long GenModelCplex::AddSolverCol(vector<int>& ind, vector<double>& val, double obj, double lb, double ub, string name, char type) {return cpx_not_implemented();}
|
724
|
-
long GenModelCplex::AddSolverRow(vector<
|
935
|
+
long GenModelCplex::AddSolverRow(vector<size_t>& ind, vector<double>& val, double rhs, char sense, string name) {return cpx_not_implemented();}
|
725
936
|
long GenModelCplex::AddCol(int* newi, double* newcol, int nz, double obj, double lb, double ub, const char* name, char type) {return cpx_not_implemented();}
|
726
937
|
long GenModelCplex::AddCut(int* cols, double* vals, int nz, double rhs, char sense, const char* name) {return cpx_not_implemented();}
|
727
938
|
long GenModelCplex::ChangeBulkBounds(int count, int * ind, char * type, double * vals) {return cpx_not_implemented();}
|
@@ -761,6 +972,9 @@ long CplexData::Reset()
|
|
761
972
|
env = NULL;
|
762
973
|
lp = NULL;
|
763
974
|
cpxfileptr = NULL;
|
975
|
+
stop_solver = false;
|
976
|
+
original_mip_cb = NULL;
|
977
|
+
original_handle = NULL;
|
764
978
|
|
765
979
|
return 0;
|
766
980
|
}
|
@@ -817,6 +1031,7 @@ long CplexData::ClearStructure()
|
|
817
1031
|
delete[] rname[i];
|
818
1032
|
delete[] rname;
|
819
1033
|
}
|
1034
|
+
|
820
1035
|
Reset();
|
821
1036
|
|
822
1037
|
return 0;
|
@@ -827,15 +1042,15 @@ long CplexData::Delete()
|
|
827
1042
|
#ifdef CPLEX_MODULE
|
828
1043
|
if(lp != NULL)
|
829
1044
|
{
|
830
|
-
|
1045
|
+
CPXXfreeprob(env, &lp);
|
831
1046
|
}
|
832
1047
|
if(env != NULL)
|
833
1048
|
{
|
834
|
-
|
1049
|
+
CPXXcloseCPLEX(&env);
|
835
1050
|
}
|
836
1051
|
if(cpxfileptr != NULL)
|
837
1052
|
{
|
838
|
-
|
1053
|
+
CPXXfclose(cpxfileptr);
|
839
1054
|
}
|
840
1055
|
|
841
1056
|
ClearStructure();
|