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,814 @@
|
|
1
|
+
#include "GenModelCplex.h"
|
2
|
+
#ifdef OSI_MODULE
|
3
|
+
#include "ProblemReaderOsi.h"
|
4
|
+
#endif
|
5
|
+
#include <limits>
|
6
|
+
|
7
|
+
string getcplexerror(CPXENVptr env, int status)
|
8
|
+
{
|
9
|
+
char errmsg[4096];
|
10
|
+
snprintf(errmsg, 4096, "CPLEX error %d : ", status);
|
11
|
+
string prefix = string(errmsg);
|
12
|
+
CPXgeterrorstring (env, status, errmsg);
|
13
|
+
return prefix+string(errmsg);
|
14
|
+
}
|
15
|
+
|
16
|
+
GenModelCplex::~GenModelCplex()
|
17
|
+
{
|
18
|
+
if (solverdata != NULL) delete static_cast<CplexData*>(solverdata);
|
19
|
+
}
|
20
|
+
|
21
|
+
GenModelCplex::GenModelCplex() {
|
22
|
+
|
23
|
+
}
|
24
|
+
|
25
|
+
long GenModelCplex::WriteProblemToLpFile(string filename)
|
26
|
+
{
|
27
|
+
if(!bcreated)
|
28
|
+
throw string("WriteProblemToLpFile() not available : Problem not created yet;");
|
29
|
+
|
30
|
+
CplexData* d = static_cast<CplexData*>(solverdata);
|
31
|
+
CPXwriteprob(d->env, d->lp, filename.c_str(), "LP");
|
32
|
+
return 0;
|
33
|
+
}
|
34
|
+
|
35
|
+
long GenModelCplex::WriteSolutionToFile(string filename)
|
36
|
+
{
|
37
|
+
if(!bcreated)
|
38
|
+
throw string("WriteSolutionToFile() not available : Problem not created yet;");
|
39
|
+
|
40
|
+
CplexData* d = static_cast<CplexData*>(solverdata);
|
41
|
+
CPXsolwrite (d->env, d->lp, filename.c_str());
|
42
|
+
return 0;
|
43
|
+
}
|
44
|
+
|
45
|
+
long GenModelCplex::Solve()
|
46
|
+
{
|
47
|
+
if(!bcreated)
|
48
|
+
throw string("Solve() not available : Problem not created yet");
|
49
|
+
CplexData* d = static_cast<CplexData*>(solverdata);
|
50
|
+
int status = 0;
|
51
|
+
if(boolParam.count("mip") > 0 && boolParam["mip"])
|
52
|
+
status = CPXmipopt(d->env, d->lp);
|
53
|
+
else if(boolParam.count("qp") > 0 && boolParam["qp"])
|
54
|
+
status = CPXqpopt(d->env, d->lp);
|
55
|
+
else if(strParam.count("algo") > 0 && strParam["algo"] == "interior")
|
56
|
+
status = CPXbaropt(d->env, d->lp);
|
57
|
+
else if(strParam.count("algo") > 0 && strParam["algo"] == "dual")
|
58
|
+
status = CPXdualopt(d->env, d->lp);
|
59
|
+
else if(strParam.count("algo") > 0 && strParam["algo"] == "primal")
|
60
|
+
status = CPXprimopt(d->env, d->lp);
|
61
|
+
else if(strParam.count("algo") > 0 && strParam["algo"] == "concurrent")
|
62
|
+
{
|
63
|
+
//printf("choosing concurrent algo\n");
|
64
|
+
CPXsetintparam (d->env, CPX_PARAM_LPMETHOD, CPX_ALG_CONCURRENT);
|
65
|
+
status = CPXlpopt(d->env, d->lp);
|
66
|
+
}
|
67
|
+
else if(strParam.count("algo") > 0 && strParam["algo"] == "sifting")
|
68
|
+
{
|
69
|
+
CPXsetintparam (d->env, CPX_PARAM_LPMETHOD, CPX_ALG_SIFTING);
|
70
|
+
status = CPXlpopt(d->env, d->lp);
|
71
|
+
}
|
72
|
+
else
|
73
|
+
status = CPXlpopt(d->env, d->lp);
|
74
|
+
|
75
|
+
return 0;
|
76
|
+
}
|
77
|
+
|
78
|
+
long GenModelCplex::SetSol()
|
79
|
+
{
|
80
|
+
if(!bcreated)
|
81
|
+
throw string("SetSol() not available : Problem not created yet");
|
82
|
+
vars.sol.clear();
|
83
|
+
vars.sol.resize(vars.n,0);
|
84
|
+
vars.rc.clear();
|
85
|
+
vars.rc.resize(vars.n,0);
|
86
|
+
CplexData* d = (CplexData*)solverdata;
|
87
|
+
int status = 0;
|
88
|
+
|
89
|
+
if(d->x != NULL)
|
90
|
+
delete[] d->x;
|
91
|
+
if(d->dual != NULL)
|
92
|
+
delete[] d->dual;
|
93
|
+
if(d->rcost != NULL)
|
94
|
+
delete[] d->rcost;
|
95
|
+
if(d->slack != NULL)
|
96
|
+
delete[] d->slack;
|
97
|
+
|
98
|
+
d->x = new double[nc];
|
99
|
+
d->dual = new double[nr];
|
100
|
+
d->rcost = new double[nc];
|
101
|
+
d->slack = new double[nr];
|
102
|
+
|
103
|
+
int tempstat = CPXgetstat (d->env, d->lp);
|
104
|
+
int tempfeas;
|
105
|
+
int tempdualfeas;
|
106
|
+
int temphassol;
|
107
|
+
int currmeth = CPXgetmethod(d->env, d->lp);
|
108
|
+
|
109
|
+
|
110
|
+
status = CPXsolninfo(d->env, d->lp, &currmeth, &temphassol, &tempfeas, &tempdualfeas);
|
111
|
+
if ( status )
|
112
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set set solution (CPXsolninfo)"));
|
113
|
+
|
114
|
+
feasible = static_cast<bool>(tempfeas);
|
115
|
+
dualfeasible = static_cast<bool>(tempdualfeas);
|
116
|
+
hassolution= static_cast<bool>(temphassol);
|
117
|
+
|
118
|
+
if(!hassolution)
|
119
|
+
return 0;
|
120
|
+
|
121
|
+
if(boolParam.count("mip") > 0 && boolParam["mip"])
|
122
|
+
status = CPXsolution (d->env, d->lp, &solstat, &objval, d->x, NULL, NULL, NULL);
|
123
|
+
else
|
124
|
+
status = CPXsolution (d->env, d->lp, &solstat, &objval, d->x, d->dual, d->slack, d->rcost);
|
125
|
+
if ( status )
|
126
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set set solution (CPXsolution)"));
|
127
|
+
|
128
|
+
solstat = tempstat;
|
129
|
+
|
130
|
+
for(long i = 0; i < long(nc); i++)
|
131
|
+
{
|
132
|
+
vars.sol[i] = d->x[i];
|
133
|
+
vars.rc[i] = d->rcost[i];
|
134
|
+
}
|
135
|
+
|
136
|
+
for(long i = 0; i < long(nr); i++)
|
137
|
+
{
|
138
|
+
consts[i].dual = d->dual[i];
|
139
|
+
consts[i].slack = d->slack[i];
|
140
|
+
}
|
141
|
+
|
142
|
+
if(boolParam.count("print_version") > 0 && boolParam["print_version"])
|
143
|
+
printf("*********** Genmodel version = %s ***********\n", version.c_str());
|
144
|
+
|
145
|
+
return 0;
|
146
|
+
}
|
147
|
+
|
148
|
+
long GenModelCplex::AddSolverRow(vector<int>& ind, vector<double>& val, double rhs, char sense, string name)
|
149
|
+
{
|
150
|
+
if(!bcreated)
|
151
|
+
return ThrowError("AddSolverRow() not available : Problem not created yet");
|
152
|
+
AddModelRow(ind, val, rhs, sense, name);
|
153
|
+
AddCut(&ind[0], &val[0], int(ind.size()), rhs, sense, name.c_str());
|
154
|
+
|
155
|
+
return 0;
|
156
|
+
}
|
157
|
+
|
158
|
+
long GenModelCplex::AddCut(int* cols, double* vals, int nz, double rhs, char sense, const char* name)
|
159
|
+
{
|
160
|
+
if(!bcreated)
|
161
|
+
return ThrowError("AddCut() not available : Problem not created yet");
|
162
|
+
CplexData* d = (CplexData*)solverdata;
|
163
|
+
int rmatbeg = 0;
|
164
|
+
|
165
|
+
CPXaddrows(d->env, d->lp, 0, 1, nz, &rhs, &sense, &rmatbeg, cols, vals, NULL, (char**)(&name));
|
166
|
+
d->nr++;
|
167
|
+
|
168
|
+
return 0;
|
169
|
+
}
|
170
|
+
|
171
|
+
long GenModelCplex::AddSolverCol(vector<int>& ind, vector<double>& val, double obj, double lb, double ub, string name, char type)
|
172
|
+
{
|
173
|
+
if(!bcreated)
|
174
|
+
return ThrowError("AddSolverCol() not available : Problem not created yet");
|
175
|
+
AddModelCol(ind, val, obj, lb, ub, name, type);
|
176
|
+
AddCol(&ind[0], &val[0], int(ind.size()), obj, lb, ub, name.c_str(), type);
|
177
|
+
|
178
|
+
return 0;
|
179
|
+
}
|
180
|
+
|
181
|
+
long GenModelCplex::AddCol(int* newi, double* newcol, int nz, double obj, double lb, double ub, const char* name, char type)
|
182
|
+
{
|
183
|
+
if(!bcreated)
|
184
|
+
return ThrowError("AddCol() not available : Problem not created yet");
|
185
|
+
CplexData* d = (CplexData*)solverdata;
|
186
|
+
int cmatbeg = 0;
|
187
|
+
|
188
|
+
double clb = lb;
|
189
|
+
if(clb == numeric_limits<double>::infinity())
|
190
|
+
clb = CPX_INFBOUND;
|
191
|
+
else if(clb == -numeric_limits<double>::infinity())
|
192
|
+
clb = -CPX_INFBOUND;
|
193
|
+
|
194
|
+
double cub = ub;
|
195
|
+
if(cub == numeric_limits<double>::infinity())
|
196
|
+
cub = CPX_INFBOUND;
|
197
|
+
else if(cub == -numeric_limits<double>::infinity())
|
198
|
+
cub = -CPX_INFBOUND;
|
199
|
+
|
200
|
+
CPXaddcols(d->env, d->lp, 1, nz, &obj, &cmatbeg, newi, newcol, &clb, &cub, (char**)(&name));
|
201
|
+
if(type != 'C')
|
202
|
+
{
|
203
|
+
int cind = d->nc;
|
204
|
+
CPXchgctype(d->env, d->lp, 1, &cind, &type);
|
205
|
+
}
|
206
|
+
d->nc++;
|
207
|
+
|
208
|
+
return 0;
|
209
|
+
}
|
210
|
+
|
211
|
+
long GenModelCplex::CreateModel()
|
212
|
+
{
|
213
|
+
if(!binit)
|
214
|
+
return ThrowError("CreateModel() not available : Problem not initialized yet");
|
215
|
+
CplexData* d = (CplexData*)solverdata;
|
216
|
+
int status = 0;
|
217
|
+
d->nc = nc;
|
218
|
+
d->nc = nc;
|
219
|
+
d->onc = nc;
|
220
|
+
d->onr = nr;
|
221
|
+
|
222
|
+
if(boolParam.count("maximize") > 0 && boolParam["maximize"])
|
223
|
+
CPXchgobjsen (d->env, d->lp, CPX_MAX);
|
224
|
+
else
|
225
|
+
CPXchgobjsen (d->env, d->lp, CPX_MIN);
|
226
|
+
d->lrhs = new double[nr];
|
227
|
+
d->urhs = new double[nr];
|
228
|
+
d->sense = new char[nr];
|
229
|
+
d->ub = new double[nc];
|
230
|
+
d->lb = new double[nc];
|
231
|
+
d->obj = new double[nc];
|
232
|
+
d->type = new char[nc];
|
233
|
+
d->mat_r = new int[nz];
|
234
|
+
d->mat_c = new int[nz];
|
235
|
+
d->mat_v = new double[nz];
|
236
|
+
d->cname = new char*[nc];
|
237
|
+
d->rname = new char*[nr];
|
238
|
+
|
239
|
+
|
240
|
+
nz=0;
|
241
|
+
for(unsigned long i = 0; i < nr; i++)
|
242
|
+
{
|
243
|
+
d->rname[i] = new char[consts[i].name.length()+1];
|
244
|
+
snprintf(d->rname[i], consts[i].name.length()+1, "%s", consts[i].name.c_str());
|
245
|
+
//printf("%ld %s: ", i, consts[i].name.c_str());
|
246
|
+
for(unsigned long j = 0; j < consts[i].nz; j++)
|
247
|
+
{
|
248
|
+
d->mat_r[nz] = i;
|
249
|
+
d->mat_c[nz] = consts[i].cols[j];
|
250
|
+
d->mat_v[nz] = consts[i].coefs[j];
|
251
|
+
//if(i >= 198)
|
252
|
+
//printf("(%ld,%ld(%s),%f) ", d->mat_r[nz], d->mat_c[nz], vars.name[d->mat_c[nz]].c_str(), d->mat_v[nz]);
|
253
|
+
nz++;
|
254
|
+
}
|
255
|
+
|
256
|
+
if(consts[i].lrhs == numeric_limits<double>::infinity())
|
257
|
+
d->lrhs[i] = CPX_INFBOUND;
|
258
|
+
else if(consts[i].lrhs == -numeric_limits<double>::infinity())
|
259
|
+
d->lrhs[i] = -CPX_INFBOUND;
|
260
|
+
else
|
261
|
+
d->lrhs[i] = consts[i].lrhs;
|
262
|
+
if(consts[i].urhs == numeric_limits<double>::infinity())
|
263
|
+
d->urhs[i] = CPX_INFBOUND;
|
264
|
+
else if(consts[i].urhs == -numeric_limits<double>::infinity())
|
265
|
+
d->urhs[i] = -CPX_INFBOUND;
|
266
|
+
else
|
267
|
+
d->urhs[i] = consts[i].urhs-consts[i].lrhs;
|
268
|
+
d->sense[i] = consts[i].sense;
|
269
|
+
// printf("%ld/%ld -> %c\n", i, nr, d->sense[i]);
|
270
|
+
}
|
271
|
+
for(unsigned long i = 0; i < nc; i++)
|
272
|
+
{
|
273
|
+
d->cname[i] = new char[vars.name[i].length()+1];
|
274
|
+
snprintf(d->cname[i], vars.name[i].length()+1, "%s", vars.name[i].c_str());
|
275
|
+
d->obj[i] = vars.obj[i];
|
276
|
+
if(vars.ub[i] == numeric_limits<double>::infinity())
|
277
|
+
d->ub[i] = CPX_INFBOUND;
|
278
|
+
else if(vars.ub[i] == -numeric_limits<double>::infinity())
|
279
|
+
d->ub[i] = -CPX_INFBOUND;
|
280
|
+
else
|
281
|
+
d->ub[i] = vars.ub[i];
|
282
|
+
if(vars.lb[i] == numeric_limits<double>::infinity())
|
283
|
+
d->lb[i] = CPX_INFBOUND;
|
284
|
+
else if(vars.lb[i] == -numeric_limits<double>::infinity())
|
285
|
+
d->lb[i] = -CPX_INFBOUND;
|
286
|
+
else
|
287
|
+
d->lb[i] = vars.lb[i];
|
288
|
+
d->type[i] = vars.type[i];
|
289
|
+
|
290
|
+
//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]);
|
291
|
+
}
|
292
|
+
status = CPXnewrows (d->env, d->lp, nr, d->lrhs, d->sense, d->urhs, d->rname);
|
293
|
+
if ( status )
|
294
|
+
{
|
295
|
+
char errmsg[1024];
|
296
|
+
fprintf (stderr, "Could not create new rows.\n");
|
297
|
+
CPXgeterrorstring (d->env, status, errmsg);
|
298
|
+
fprintf (stderr, "%s", errmsg);
|
299
|
+
return 1;
|
300
|
+
}
|
301
|
+
//else
|
302
|
+
//printf("Row added!\n");
|
303
|
+
|
304
|
+
if(boolParam.count("mip") > 0 && boolParam["mip"])
|
305
|
+
status = CPXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, d->type, d->cname);
|
306
|
+
else
|
307
|
+
status = CPXnewcols (d->env, d->lp, nc, d->obj, d->lb, d->ub, NULL, NULL);
|
308
|
+
if ( status )
|
309
|
+
{
|
310
|
+
char errmsg[1024];
|
311
|
+
fprintf (stderr, "Could not create new cols.\n");
|
312
|
+
CPXgeterrorstring (d->env, status, errmsg);
|
313
|
+
fprintf (stderr, "%s", errmsg);
|
314
|
+
return 1;
|
315
|
+
}
|
316
|
+
//status = CPXnewcols (env, lp, nc, obj, lb, ub, NULL, colname);
|
317
|
+
if ( status )
|
318
|
+
return 1;
|
319
|
+
//else
|
320
|
+
//printf("Col added!\n");
|
321
|
+
status = CPXchgcoeflist (d->env, d->lp, nz, d->mat_r, d->mat_c, d->mat_v);
|
322
|
+
if ( status )
|
323
|
+
return 1;
|
324
|
+
|
325
|
+
vector<long>::iterator iti;
|
326
|
+
vector<long>::iterator itj = vars.qj.begin();
|
327
|
+
vector<double>::iterator itv = vars.qobj.begin();
|
328
|
+
|
329
|
+
vector<vector<pair<int,double> > > qptemp;
|
330
|
+
qptemp.resize(nc);
|
331
|
+
int* qpbeg = NULL;
|
332
|
+
int* qpnum = NULL;
|
333
|
+
int* qpind = NULL;
|
334
|
+
double* qpv = NULL;
|
335
|
+
int qpnz = 0;
|
336
|
+
|
337
|
+
if(!vars.qi.empty())
|
338
|
+
{
|
339
|
+
boolParam["qp"] = true;
|
340
|
+
qpbeg = new int[nc];
|
341
|
+
qpnum = new int[nc];
|
342
|
+
}
|
343
|
+
if(boolParam.count("qp_mat") == 0 || boolParam["qp_mat"])
|
344
|
+
{
|
345
|
+
for(iti = vars.qi.begin(); iti != vars.qi.end(); iti++, itj++, itv++)
|
346
|
+
{
|
347
|
+
qptemp[*iti].push_back(pair<int, double>(*itj,*itv));
|
348
|
+
qpnz++;
|
349
|
+
if(*iti != *itj)
|
350
|
+
{
|
351
|
+
qptemp[*itj].push_back(pair<int, double>(*iti,*itv));
|
352
|
+
qpnz++;
|
353
|
+
}
|
354
|
+
}
|
355
|
+
if(!vars.qi.empty())
|
356
|
+
{
|
357
|
+
qpv = new double[qpnz];
|
358
|
+
qpind = new int[qpnz];
|
359
|
+
|
360
|
+
qpnz=0;
|
361
|
+
for(int i = 0; i < int(nc); i++)
|
362
|
+
{
|
363
|
+
qpbeg[i] = qpnz;
|
364
|
+
qpnum[i] = int(qptemp[i].size());
|
365
|
+
for(int j = 0; j < int(qptemp[i].size()); j++)
|
366
|
+
{
|
367
|
+
qpind[qpnz] = qptemp[i][j].first;
|
368
|
+
qpv[qpnz] = 2.0*qptemp[i][j].second;
|
369
|
+
qpnz++;
|
370
|
+
}
|
371
|
+
}
|
372
|
+
status = CPXcopyquad(d->env, d->lp, qpbeg, qpnum, qpind, qpv);
|
373
|
+
delete[] qpbeg;
|
374
|
+
delete[] qpnum;
|
375
|
+
delete[] qpind;
|
376
|
+
delete[] qpv;
|
377
|
+
}
|
378
|
+
if ( status )
|
379
|
+
{
|
380
|
+
printf("QP problem!\n");
|
381
|
+
return 1;
|
382
|
+
}
|
383
|
+
}
|
384
|
+
//else
|
385
|
+
//printf("Coefs added!\n");
|
386
|
+
bcreated = true;
|
387
|
+
|
388
|
+
return 0;
|
389
|
+
}
|
390
|
+
|
391
|
+
long AddQuadraticVector(vector<int>& ind, vector<double>& val)
|
392
|
+
{
|
393
|
+
return 0;
|
394
|
+
}
|
395
|
+
|
396
|
+
long AddQuadraticMatrix(vector<int>& indi, vector<int>& indj, vector<double>& val)
|
397
|
+
{
|
398
|
+
return 0;
|
399
|
+
}
|
400
|
+
|
401
|
+
long GenModelCplex::CreateModel(string filename, int type, string dn)
|
402
|
+
{
|
403
|
+
#ifdef OSI_MODULE
|
404
|
+
ReadFromFile(static_cast<GenModel*>(this), filename, type);
|
405
|
+
SetNumbers();
|
406
|
+
CreateModel();
|
407
|
+
#else
|
408
|
+
return ThrowError("Cannot use CreateModel(filenamem, type, dn) : Osi Module not present");
|
409
|
+
#endif
|
410
|
+
return 0;
|
411
|
+
}
|
412
|
+
|
413
|
+
long GenModelCplex::ChangeBulkBounds(int count, int * ind, char * type, double * vals)
|
414
|
+
{
|
415
|
+
if(!bcreated)
|
416
|
+
return ThrowError("ChangeBulkBounds not available : Problem not created yet");
|
417
|
+
CplexData* d = (CplexData*)solverdata;
|
418
|
+
|
419
|
+
for(long i = 0; i < count; i++)
|
420
|
+
{
|
421
|
+
if (type[i] == 'L' || type[i] == 'B')
|
422
|
+
{
|
423
|
+
vars.lb[i] = vals[i];
|
424
|
+
}
|
425
|
+
if (type[i] == 'U' || type[i] == 'B')
|
426
|
+
{
|
427
|
+
vars.ub[i] = vals[i];
|
428
|
+
}
|
429
|
+
}
|
430
|
+
|
431
|
+
CPXchgbds(d->env, d->lp, count, ind, type, vals);
|
432
|
+
|
433
|
+
return 0;
|
434
|
+
}
|
435
|
+
|
436
|
+
long GenModelCplex::ChangeBulkObjectives(int count, int * ind, double * vals)
|
437
|
+
{
|
438
|
+
if(!bcreated)
|
439
|
+
return ThrowError("ChangeBulkObjectives() not available : Problem not created yet");
|
440
|
+
CplexData* d = (CplexData*)solverdata;
|
441
|
+
|
442
|
+
for(long i = 0; i < count; i++)
|
443
|
+
{
|
444
|
+
vars.obj[i] = vals[i];
|
445
|
+
}
|
446
|
+
|
447
|
+
CPXchgobj(d->env, d->lp, count, ind, vals);
|
448
|
+
|
449
|
+
return 0;
|
450
|
+
}
|
451
|
+
|
452
|
+
long GenModelCplex::ChangeBulkNz(int count, int* rind, int* cind, double * vals)
|
453
|
+
{
|
454
|
+
if(!bcreated)
|
455
|
+
return ThrowError("ChangeBulkNz() not available : Problem not created yet");
|
456
|
+
CplexData* d = (CplexData*)solverdata;
|
457
|
+
|
458
|
+
for(long i = 0; i < count; i++)
|
459
|
+
{
|
460
|
+
bool found = false;
|
461
|
+
for(long j = 0; j < int(consts[rind[i]].cols.size()); j++)
|
462
|
+
{
|
463
|
+
if(consts[rind[i]].cols[j] == cind[i])
|
464
|
+
{
|
465
|
+
consts[rind[i]].coefs[j] = vals[i];
|
466
|
+
found = true;
|
467
|
+
break;
|
468
|
+
}
|
469
|
+
}
|
470
|
+
if(!found)
|
471
|
+
consts[rind[i]].AddNz(cind[i], vals[i]);
|
472
|
+
}
|
473
|
+
|
474
|
+
CPXchgcoeflist(d->env, d->lp, count, rind, cind, vals);
|
475
|
+
|
476
|
+
return 0;
|
477
|
+
}
|
478
|
+
|
479
|
+
|
480
|
+
|
481
|
+
long GenModelCplex::DeleteMipStarts()
|
482
|
+
{
|
483
|
+
if(!bcreated)
|
484
|
+
return ThrowError("ChangeBulkNz() not available : Problem not created yet");
|
485
|
+
CplexData* d = (CplexData*)solverdata;
|
486
|
+
int n = CPXgetnummipstarts(d->env, d->lp);
|
487
|
+
if (n > 0)
|
488
|
+
CPXdelmipstarts(d->env, d->lp, 0, n - 1);
|
489
|
+
|
490
|
+
return 0;
|
491
|
+
}
|
492
|
+
|
493
|
+
double GenModelCplex::GetMIPRelativeGap()
|
494
|
+
{
|
495
|
+
if(!bcreated)
|
496
|
+
return ThrowError("ChangeBulkNz() not available : Problem not created yet");
|
497
|
+
CplexData* d = (CplexData*)solverdata;
|
498
|
+
double gap = 0, bestobjval = 0;
|
499
|
+
CPXgetbestobjval(d->env, d->lp, &bestobjval);
|
500
|
+
if (bestobjval > 0) // If the optimal solution is found by the presolve, the CPXgetbestobjval = 0, and the CPXgetmiprelgap ~ 1
|
501
|
+
CPXgetmiprelgap(d->env, d->lp, &gap);
|
502
|
+
|
503
|
+
return gap;
|
504
|
+
}
|
505
|
+
|
506
|
+
long GenModelCplex::SwitchToMip()
|
507
|
+
{
|
508
|
+
if(!bcreated)
|
509
|
+
return ThrowError("SwitchToMip() not available : Problem not created yet");
|
510
|
+
vector<int> ind;
|
511
|
+
vector<char> type;
|
512
|
+
for(int i = 0; i < int(vars.type.size()); i++)
|
513
|
+
{
|
514
|
+
if(vars.type[i] == 'B' || vars.type[i] == 'I' || vars.type[i] == 'S' || vars.type[i] == 'N')
|
515
|
+
{
|
516
|
+
ind.push_back(i);
|
517
|
+
type.push_back(vars.type[i]);
|
518
|
+
}
|
519
|
+
}
|
520
|
+
CplexData* d = static_cast<CplexData*>(solverdata);
|
521
|
+
CPXchgctype(d->env, d->lp, int(ind.size()), &(ind[0]), &(type[0]));
|
522
|
+
boolParam["mip"] = true;
|
523
|
+
|
524
|
+
return 0;
|
525
|
+
}
|
526
|
+
|
527
|
+
long GenModelCplex::SwitchToLp()
|
528
|
+
{
|
529
|
+
if(!bcreated)
|
530
|
+
return ThrowError("SwitchToLp() not available : Problem not created yet");
|
531
|
+
vector<int> ind;
|
532
|
+
vector<char> type;
|
533
|
+
for(int i = 0; i < int(vars.type.size()); i++)
|
534
|
+
{
|
535
|
+
if(vars.type[i] == 'B' || vars.type[i] == 'I' || vars.type[i] == 'S' || vars.type[i] == 'N')
|
536
|
+
{
|
537
|
+
ind.push_back(i);
|
538
|
+
type.push_back('C');
|
539
|
+
}
|
540
|
+
}
|
541
|
+
CplexData* d = static_cast<CplexData*>(solverdata);
|
542
|
+
CPXchgctype(d->env, d->lp, int(ind.size()), &(ind[0]), &(type[0]));
|
543
|
+
boolParam["mip"] = false;
|
544
|
+
|
545
|
+
return 0;
|
546
|
+
}
|
547
|
+
|
548
|
+
long GenModelCplex::Init(string name)
|
549
|
+
{
|
550
|
+
|
551
|
+
//strParam.count("log_file")
|
552
|
+
//dblParam.count("relative_mip_gap_tolerance")
|
553
|
+
//dblParam.count("absolute_mip_gap_tolerance")
|
554
|
+
//dblParam.count("time_limit")
|
555
|
+
//dblParam.count("bounds_feasibility_tolerance")
|
556
|
+
//dblParam.count("optimality_tolerance")
|
557
|
+
//dblParam.count("markowitz_tolerance"))
|
558
|
+
//longParam.count("threads")
|
559
|
+
//longParam.count("cutpass")
|
560
|
+
//longParam.count("pumplevel")
|
561
|
+
//longParam.count("mipemphasis")
|
562
|
+
//longParam.count("probinglevel")
|
563
|
+
//longParam.count("max_iteration_limit");
|
564
|
+
//boolParam.count("preprocoff") : turn on/off preprocessing
|
565
|
+
//boolParam.count("datacheckoff")
|
566
|
+
//boolParam.count("screen_output")
|
567
|
+
//boolParam.count("usecutcb")
|
568
|
+
|
569
|
+
if(solverdata == NULL)
|
570
|
+
solverdata = new CplexData();
|
571
|
+
else
|
572
|
+
{
|
573
|
+
static_cast<CplexData*>(solverdata)->Delete();
|
574
|
+
static_cast<CplexData*>(solverdata)->Reset();
|
575
|
+
}
|
576
|
+
|
577
|
+
CplexData* d = static_cast<CplexData*>(solverdata);
|
578
|
+
int status = 0;
|
579
|
+
|
580
|
+
d->env = CPXopenCPLEX (&status);
|
581
|
+
|
582
|
+
// If an error occurs
|
583
|
+
if ( d->env == NULL )
|
584
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Could not open CPLEX environment"));
|
585
|
+
|
586
|
+
|
587
|
+
hassolution = false;
|
588
|
+
|
589
|
+
// Log file
|
590
|
+
if(strParam.count("log_file") > 0)
|
591
|
+
{
|
592
|
+
d->cpxfileptr = CPXfopen(strParam["log_file"].c_str(), "w");
|
593
|
+
status = CPXsetlogfile(d->env, d->cpxfileptr);
|
594
|
+
if ( status )
|
595
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to set the log file"));
|
596
|
+
}
|
597
|
+
|
598
|
+
// General settings
|
599
|
+
boolParam["log_output_stdout"] = true;
|
600
|
+
SetParam("log_output_stdout", CPX_PARAM_SCRIND, "bool", "Failure to turn on/off log output to stdout");
|
601
|
+
SetParam("log_level", 0, "long", "Failure to set log level", false);
|
602
|
+
SetParam("use_data_checking", CPX_PARAM_DATACHECK, "bool", "Failure to turn on/off data checking");
|
603
|
+
SetParam("nb_threads", CPX_PARAM_THREADS, "long", "Failure to set the number of threads");
|
604
|
+
if(boolParam.count("use_preprocessor") > 0 && !boolParam["use_preprocessor"])
|
605
|
+
{
|
606
|
+
SetDirectParam(CPX_PARAM_AGGFILL, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_AGGFILL)");
|
607
|
+
SetDirectParam(CPX_PARAM_PREPASS, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_PREPASS)");
|
608
|
+
SetDirectParam(CPX_PARAM_AGGIND, long2param(CPX_OFF), "long", "Failure to use preprocessor (CPX_PARAM_AGGIND)");
|
609
|
+
SetDirectParam(CPX_PARAM_DEPIND, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_DEPIND)");
|
610
|
+
SetDirectParam(CPX_PARAM_PRELINEAR, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_PRELINEAR)");
|
611
|
+
SetDirectParam(CPX_PARAM_PREDUAL, long2param(-1), "long", "Failure to use preprocessor (CPX_PARAM_PREDUAL)");
|
612
|
+
SetDirectParam(CPX_PARAM_REDUCE, long2param(0), "long", "Failure to use preprocessor (CPX_PARAM_REDUCE)");
|
613
|
+
SetDirectParam(CPX_PARAM_PREIND, long2param(CPX_OFF), "long", "Failure to use preprocessor (CPX_PARAM_PREIND)");
|
614
|
+
}
|
615
|
+
|
616
|
+
// MIP settings
|
617
|
+
SetParam("nb_cut_pass", CPX_PARAM_CUTPASS, "long", "Failure to set the number of cut pass");
|
618
|
+
SetParam("feasibility_pump_level", CPX_PARAM_FPHEUR, "long", "Failure to set the feasibility pump level");
|
619
|
+
SetParam("probing_level", CPX_PARAM_PROBE, "long", "Failure to set the probing level");
|
620
|
+
SetParam("mip_emphasis", CPX_PARAM_MIPEMPHASIS, "long", "Failure to set the MIP emphasis");
|
621
|
+
if(boolParam.count("use_cut_callback") > 0 && boolParam["use_cut_callback"])
|
622
|
+
{
|
623
|
+
SetDirectParam(CPX_PARAM_PRELINEAR, long2param(0), "long", "Failure to use cut callback (CPX_PARAM_PRELINEAR)");
|
624
|
+
SetDirectParam(CPX_PARAM_MIPCBREDLP, long2param(0), "long", "Failure to use cut callback (CPX_PARAM_MIPCBREDLP)");
|
625
|
+
}
|
626
|
+
|
627
|
+
// Tolerance and limits
|
628
|
+
SetParam("time_limit", CPX_PARAM_TILIM, "dbl", "Failure to set time limit");
|
629
|
+
SetParam("max_iteration_limit", CPX_PARAM_ITLIM, "long", "Failure to set the maximal number of simplex iterations");
|
630
|
+
SetParam("bounds_feasibility_tolerance", CPX_PARAM_EPRHS, "dbl", "Failure to set bounds feasibility tolerance");
|
631
|
+
SetParam("optimality_tolerance", CPX_PARAM_EPOPT, "dbl", "Failure to set optimality tolerance");
|
632
|
+
SetParam("markowitz_tolerance", CPX_PARAM_EPMRK, "dbl", "Failure to set Markowitz tolerance");
|
633
|
+
SetParam("absolute_mip_gap_tolerance", CPX_PARAM_EPAGAP, "dbl", "Failure to set absolute gap tolerance");
|
634
|
+
SetParam("relative_mip_gap_tolerance", CPX_PARAM_EPGAP, "dbl", "Failure to set relative gap tolerance");
|
635
|
+
if(boolParam.count("maximize") > 0 && boolParam["maximize"])
|
636
|
+
SetParam("lp_objective_limit", CPX_PARAM_OBJULIM, "dbl", "Failure to set lp objective limit");
|
637
|
+
else
|
638
|
+
SetParam("lp_objective_limit", CPX_PARAM_OBJLLIM, "dbl", "Failure to set lp objective limit");
|
639
|
+
|
640
|
+
|
641
|
+
// Create the problem
|
642
|
+
d->lp = CPXcreateprob (d->env, &status, name.c_str());
|
643
|
+
if ( d->lp == NULL )
|
644
|
+
return ThrowError(getcplexerror(d->env, status)+string(". ")+string("Failure to create Cplex optimization problem"));
|
645
|
+
|
646
|
+
binit = true;
|
647
|
+
|
648
|
+
return 0;
|
649
|
+
}
|
650
|
+
|
651
|
+
long GenModelCplex::SetDirectParam(int whichparam, genmodel_param value, string type, string message)
|
652
|
+
{
|
653
|
+
int status = 0;
|
654
|
+
if(type == "dbl")
|
655
|
+
status = CPXsetdblparam (static_cast<CplexData*>(solverdata)->env, whichparam, value.dblval);
|
656
|
+
else if(type == "long")
|
657
|
+
status = CPXsetintparam (static_cast<CplexData*>(solverdata)->env, whichparam, value.longval);
|
658
|
+
else if(type == "str")
|
659
|
+
status = CPXsetstrparam (static_cast<CplexData*>(solverdata)->env, whichparam, value.strval);
|
660
|
+
if ( status )
|
661
|
+
return ThrowError(getcplexerror(static_cast<CplexData*>(solverdata)->env, status)+string(". ")+message);
|
662
|
+
|
663
|
+
return 0;
|
664
|
+
}
|
665
|
+
|
666
|
+
long GenModelCplex::SetParam(string param, int whichparam, string type, string message, bool implemented)
|
667
|
+
{
|
668
|
+
bool notimplmessage = boolParam.count("throw_on_unimplemeted_option") > 0 && boolParam["throw_on_unimplemeted_option"];
|
669
|
+
|
670
|
+
if(type == "dbl")
|
671
|
+
{
|
672
|
+
if(dblParam.count(param) > 0 && implemented)
|
673
|
+
SetDirectParam(whichparam, dbl2param(dblParam[param]), type, message);
|
674
|
+
else if(notimplmessage && !implemented && dblParam.count(param) > 0)
|
675
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
676
|
+
}
|
677
|
+
else if(type == "long")
|
678
|
+
{
|
679
|
+
if(longParam.count(param) > 0 && implemented)
|
680
|
+
SetDirectParam(whichparam, long2param(longParam[param]), type, message);
|
681
|
+
else if(notimplmessage && !implemented && longParam.count(param) > 0)
|
682
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
683
|
+
}
|
684
|
+
else if(type == "str")
|
685
|
+
{
|
686
|
+
if(strParam.count(param) > 0 && implemented)
|
687
|
+
SetDirectParam(whichparam, str2param(strParam[param]), type, message);
|
688
|
+
else if(notimplmessage && !implemented && strParam.count(param) > 0)
|
689
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
690
|
+
}
|
691
|
+
else if(type == "bool")
|
692
|
+
{
|
693
|
+
if(boolParam.count(param) > 0 && implemented)
|
694
|
+
{
|
695
|
+
if(boolParam[param])
|
696
|
+
SetDirectParam(whichparam, long2param(CPX_ON), "long", message);
|
697
|
+
else
|
698
|
+
SetDirectParam(whichparam, long2param(CPX_OFF), "long", message);
|
699
|
+
}
|
700
|
+
else if(notimplmessage && !implemented && boolParam.count(param) > 0)
|
701
|
+
throw (string("Parameter ")+param+" not implemented in GenModelOsi");
|
702
|
+
}
|
703
|
+
return 0;
|
704
|
+
}
|
705
|
+
|
706
|
+
long GenModelCplex::Clean()
|
707
|
+
{
|
708
|
+
if(solverdata != NULL)
|
709
|
+
delete static_cast<CplexData*>(solverdata);
|
710
|
+
|
711
|
+
return 0;
|
712
|
+
}
|
713
|
+
|
714
|
+
long CplexData::Reset()
|
715
|
+
{
|
716
|
+
mat_c = NULL;
|
717
|
+
mat_r = NULL;
|
718
|
+
mat_v = NULL;
|
719
|
+
lrhs = NULL;
|
720
|
+
urhs = NULL;
|
721
|
+
sense = NULL;
|
722
|
+
ub = NULL;
|
723
|
+
lb = NULL;
|
724
|
+
type = NULL;
|
725
|
+
obj = NULL;
|
726
|
+
x = NULL;
|
727
|
+
dual = NULL;;
|
728
|
+
rcost = NULL;
|
729
|
+
slack = NULL;
|
730
|
+
cname = NULL;
|
731
|
+
rname = NULL;
|
732
|
+
env = NULL;
|
733
|
+
lp = NULL;
|
734
|
+
cpxfileptr = NULL;
|
735
|
+
|
736
|
+
return 0;
|
737
|
+
}
|
738
|
+
|
739
|
+
CplexData::CplexData()
|
740
|
+
{
|
741
|
+
Reset();
|
742
|
+
}
|
743
|
+
|
744
|
+
CplexData::~CplexData()
|
745
|
+
{
|
746
|
+
Delete();
|
747
|
+
}
|
748
|
+
|
749
|
+
long CplexData::ClearStructure()
|
750
|
+
{
|
751
|
+
if(mat_c != NULL)
|
752
|
+
delete[] mat_c;
|
753
|
+
if(mat_r != NULL)
|
754
|
+
delete[] mat_r;
|
755
|
+
if(mat_v != NULL)
|
756
|
+
delete[] mat_v;
|
757
|
+
if(lrhs != NULL)
|
758
|
+
delete[] lrhs;
|
759
|
+
if(obj != NULL)
|
760
|
+
delete[] obj;
|
761
|
+
if(urhs != NULL)
|
762
|
+
delete[] urhs;
|
763
|
+
if(sense != NULL)
|
764
|
+
delete[] sense;
|
765
|
+
if(ub != NULL)
|
766
|
+
delete[] ub;
|
767
|
+
if(lb != NULL)
|
768
|
+
delete[] lb;
|
769
|
+
if(type != NULL)
|
770
|
+
delete[] type;
|
771
|
+
if(x != 0)
|
772
|
+
delete[] x;
|
773
|
+
if(dual != NULL)
|
774
|
+
delete[] dual;
|
775
|
+
if(rcost != NULL)
|
776
|
+
delete[] rcost;
|
777
|
+
if(slack != NULL)
|
778
|
+
delete[] slack;
|
779
|
+
if(cname != NULL)
|
780
|
+
{
|
781
|
+
for(long i = 0; i < onc; i++)
|
782
|
+
delete[] cname[i];
|
783
|
+
delete[] cname;
|
784
|
+
}
|
785
|
+
if(rname != NULL)
|
786
|
+
{
|
787
|
+
for(long i = 0; i < onr; i++)
|
788
|
+
delete[] rname[i];
|
789
|
+
delete[] rname;
|
790
|
+
}
|
791
|
+
Reset();
|
792
|
+
|
793
|
+
return 0;
|
794
|
+
}
|
795
|
+
|
796
|
+
long CplexData::Delete()
|
797
|
+
{
|
798
|
+
if(lp != NULL)
|
799
|
+
{
|
800
|
+
CPXfreeprob(env, &lp);
|
801
|
+
}
|
802
|
+
if(env != NULL)
|
803
|
+
{
|
804
|
+
CPXcloseCPLEX(&env);
|
805
|
+
}
|
806
|
+
if(cpxfileptr != NULL)
|
807
|
+
{
|
808
|
+
CPXfclose(cpxfileptr);
|
809
|
+
}
|
810
|
+
|
811
|
+
ClearStructure();
|
812
|
+
|
813
|
+
return 0;
|
814
|
+
}
|