1 #include "soplex.h"
2 #include "soplex_interface.h"
3 #include <iostream>
4
5 using namespace soplex;
6
7 /** creates new SoPlex struct **/
8 void* SoPlex_create()
9 {
10 SoPlex* so = new SoPlex();
11 return so;
12 }
13
14 /** frees SoPlex struct **/
15 void SoPlex_free(void* soplex)
16 {
17 SoPlex* so = (SoPlex*)(soplex);
18 delete so;
19 }
20
21 /** clears the (floating point) LP **/
22 void SoPlex_clearLPReal(void* soplex)
23 {
24 SoPlex* so = (SoPlex*)(soplex);
25 so->clearLPReal();
26 }
27
28 /** returns number of rows **/
29 int SoPlex_numRows(void* soplex)
30 {
31 SoPlex* so = (SoPlex*)(soplex);
32 return so->numRows();
33 }
34
35 /** returns number of columns **/
36 int SoPlex_numCols(void* soplex)
37 {
38 SoPlex* so = (SoPlex*)(soplex);
39 return so->numCols();
40 }
41
42 /** enables rational solving mode **/
43 void SoPlex_setRational(void* soplex)
44 {
45 #ifndef SOPLEX_WITH_BOOST
46 throw SPxException("Rational functions cannot be used when built without Boost.");
47 #endif
48 /* coverity[unreachable] */
49 SoPlex* so = (SoPlex*)(soplex);
50 so->setIntParam(SoPlex::READMODE, SoPlex::READMODE_RATIONAL);
51 so->setIntParam(SoPlex::SOLVEMODE, SoPlex::SOLVEMODE_RATIONAL);
52 so->setIntParam(SoPlex::CHECKMODE, SoPlex::CHECKMODE_RATIONAL);
53 so->setIntParam(SoPlex::SYNCMODE, SoPlex::SYNCMODE_AUTO);
54 so->setRealParam(SoPlex::FEASTOL, 0.0);
55 so->setRealParam(SoPlex::OPTTOL, 0.0);
56 }
57
58 /** sets integer parameter value **/
59 void SoPlex_setIntParam(void* soplex, int paramcode, int paramvalue)
60 {
61 SoPlex* so = (SoPlex*)(soplex);
62 so->setIntParam((SoPlex::IntParam)paramcode, paramvalue);
63 }
64
65 /** returns value of integer parameter **/
66 int SoPlex_getIntParam(void* soplex, int paramcode)
67 {
68 SoPlex* so = (SoPlex*)(soplex);
69 return so->intParam((SoPlex::IntParam)paramcode);
70 }
71
72 /** adds a single (floating point) column **/
73 void SoPlex_addColReal(
74 void* soplex,
75 double* colentries,
76 int colsize,
77 int nnonzeros,
78 double objval,
79 double lb,
80 double ub
81 )
82 {
83 SoPlex* so = (SoPlex*)(soplex);
84 DSVector col(nnonzeros);
85
86 /* add nonzero entries to column vector */
87 for(int i = 0; i < colsize; ++i)
88 {
89 if(colentries[i] != 0.0)
90 col.add(i, colentries[i]);
91 }
92
93 so->addColReal(LPCol(objval, col, ub, lb));
94 }
95
96 /** adds a single rational column **/
97 void SoPlex_addColRational(
98 void* soplex,
99 long* colnums,
100 long* coldenoms,
101 int colsize,
102 int nnonzeros,
103 long objvalnum,
104 long objvaldenom,
105 long lbnum,
106 long lbdenom,
107 long ubnum,
108 long ubdenom
109 )
110 {
111 #ifndef SOPLEX_WITH_BOOST
112 throw SPxException("Rational functions cannot be used when built without Boost.");
113 #endif
114 /* coverity[unreachable] */
115 SoPlex* so = (SoPlex*)(soplex);
116 DSVectorRational col(nnonzeros);
117
118 /* get rational lower bound */
119 Rational lower(lbnum, lbdenom);
120
121 /* get rational upper bound */
122 Rational upper(ubnum, ubdenom);
123
124 /* get rational objective value */
125 Rational objval(objvalnum, objvaldenom);
126
127 /* add nonzero entries to column vector */
128 for(int i = 0; i < colsize; ++i)
129 {
130 if(colnums[i] != 0)
131 {
132 /* get rational nonzero entry */
133 Rational colentry(colnums[i], coldenoms[i]);
134 col.add(i, colentry);
135 }
136 }
137
138 so->addColRational(LPColRational(objval, col, upper, lower));
139 }
140
141 /** adds a single (floating point) row **/
142 void SoPlex_addRowReal(
143 void* soplex,
144 double* rowentries,
145 int rowsize,
146 int nnonzeros,
147 double lb,
148 double ub
149 )
150 {
151 SoPlex* so = (SoPlex*)(soplex);
152 DSVector row(nnonzeros);
153
154 /* add nonzero entries to row vector */
155 for(int i = 0; i < rowsize; ++i)
156 {
157 if(rowentries[i] != 0.0)
158 row.add(i, rowentries[i]);
159 }
160
161 so->addRowReal(LPRow(lb, row, ub));
162 }
163
164 /** adds a single rational row **/
165 void SoPlex_addRowRational(
166 void* soplex,
167 long* rownums,
168 long* rowdenoms,
169 int rowsize,
170 int nnonzeros,
171 long lbnum,
172 long lbdenom,
173 long ubnum,
174 long ubdenom
175 )
176 {
177 #ifndef SOPLEX_WITH_BOOST
178 throw SPxException("Rational functions cannot be used when built without Boost.");
179 #endif
180 /* coverity[unreachable] */
181 SoPlex* so = (SoPlex*)(soplex);
182 DSVectorRational row(nnonzeros);
183
184 /* get rational lower bound */
185 Rational lower(lbnum, lbdenom);
186
187 /* get rational upper bound */
188 Rational upper(ubnum, ubdenom);
189
190 /* add nonzero entries to row vector */
191 for(int i = 0; i < rowsize; ++i)
192 {
193 if(rownums[i] != 0)
194 {
195 /* get rational nonzero entry */
196 Rational rowentry(rownums[i], rowdenoms[i]);
197 row.add(i, rowentry);
198 }
199 }
200
201 so->addRowRational(LPRowRational(lower, row, upper));
202 }
203
204 /** gets primal solution **/
205 void SoPlex_getPrimalReal(void* soplex, double* primal, int dim)
206 {
207 SoPlex* so = (SoPlex*)(soplex);
208 so->getPrimalReal(primal, dim);
209 }
210
211 /** Returns rational primal solution in a char pointer.
212 * The caller needs to ensure the char array is freed.
213 **/
214 char* SoPlex_getPrimalRationalString(void* soplex, int dim)
215 {
216 #ifndef SOPLEX_WITH_BOOST
217 throw SPxException("Rational functions cannot be used when built without Boost.");
218 #endif
219 /* coverity[unreachable] */
220 SoPlex* so = (SoPlex*)(soplex);
221 VectorRational primal(dim);
222 std::string primalstring;
223 char* rawstring;
224 long unsigned int stringlength;
225
226 so->getPrimalRational(primal);
227
228 for(int i = 0; i < dim; ++i)
229 {
230 primalstring.append(primal[i].str());
231 primalstring.append(" ");
232 }
233
234 stringlength = strlen(primalstring.c_str()) + 1;
235 rawstring = new char[stringlength];
236 strncpy(rawstring, primalstring.c_str(), stringlength);
237 return rawstring;
238 }
239
240 /** gets dual solution **/
241 void SoPlex_getDualReal(void* soplex, double* dual, int dim)
242 {
243 SoPlex* so = (SoPlex*)(soplex);
244 so->getDualReal(dual, dim);
245 }
246
247 /** optimizes the given LP **/
248 int SoPlex_optimize(void* soplex)
249 {
250 SoPlex* so = (SoPlex*)(soplex);
251 return so->optimize();
252 }
253
254 /** changes objective function vector to obj **/
255 void SoPlex_changeObjReal(void* soplex, double* obj, int dim)
256 {
257 SoPlex* so = (SoPlex*)(soplex);
258 Vector objective(dim, obj);
259 return so->changeObjReal(objective);
260 }
261
262 /** changes rational objective function vector to obj **/
263 void SoPlex_changeObjRational(void* soplex, long* objnums, long* objdenoms, int dim)
264 {
265 #ifndef SOPLEX_WITH_BOOST
266 throw SPxException("Rational functions cannot be used when built without Boost.");
267 #endif
268 /* coverity[unreachable] */
269 SoPlex* so = (SoPlex*)(soplex);
270 Rational* objrational = new Rational [dim];
271
272 /* create rational objective vector */
273 for(int i = 0; i < dim; ++i)
274 {
275 Rational objentry(objnums[i], objdenoms[i]);
276 objrational[i] = objentry;
277 }
278
279 VectorRational objective(dim, objrational);
280 return so->changeObjRational(objective);
281 }
282
283 /** changes left-hand side vector for constraints to lhs **/
284 void SoPlex_changeLhsReal(void* soplex, double* lhs, int dim)
285 {
286 SoPlex* so = (SoPlex*)(soplex);
287 Vector lhsvec(dim, lhs);
288 return so->changeLhsReal(lhsvec);
289 }
290
291 /** changes rational left-hand side vector for constraints to lhs **/
292 void SoPlex_changeLhsRational(void* soplex, long* lhsnums, long* lhsdenoms, int dim)
293 {
294 #ifndef SOPLEX_WITH_BOOST
295 throw SPxException("Rational functions cannot be used when built without Boost.");
296 #endif
297 /* coverity[unreachable] */
298 SoPlex* so = (SoPlex*)(soplex);
299 Rational* lhsrational = new Rational [dim];
300
301 /* create rational lhs vector */
302 for(int i = 0; i < dim; ++i)
303 {
304 Rational lhsentry(lhsnums[i], lhsdenoms[i]);
305 lhsrational[i] = lhsentry;
306 }
307
308 VectorRational lhs(dim, lhsrational);
309 return so->changeLhsRational(lhs);
310 }
311
312 /** changes right-hand side vector for constraints to rhs **/
313 void SoPlex_changeRhsReal(void* soplex, double* rhs, int dim)
314 {
315 SoPlex* so = (SoPlex*)(soplex);
316 Vector rhsvec(dim, rhs);
317 return so->changeRhsReal(rhsvec);
318 }
319
320 /** changes rational right-hand side vector for constraints to rhs **/
321 void SoPlex_changeRhsRational(void* soplex, long* rhsnums, long* rhsdenoms, int dim)
322 {
323 #ifndef SOPLEX_WITH_BOOST
324 throw SPxException("Rational functions cannot be used when built without Boost.");
325 #endif
326 /* coverity[unreachable] */
327 SoPlex* so = (SoPlex*)(soplex);
328 Rational* rhsrational = new Rational [dim];
329
330 /* create rational rhs vector */
331 for(int i = 0; i < dim; ++i)
332 {
333 Rational rhsentry(rhsnums[i], rhsdenoms[i]);
334 rhsrational[i] = rhsentry;
335 }
336
337 VectorRational rhs(dim, rhsrational);
338 return so->changeRhsRational(rhs);
339 }
340
341 /** write LP to file **/
342 void SoPlex_writeFileReal(void* soplex, char* filename)
343 {
344 SoPlex* so = (SoPlex*)(soplex);
345 so->writeFile(filename);
346 }
347
348 /** returns the objective value if a primal solution is available **/
349 double SoPlex_objValueReal(void* soplex)
350 {
351 SoPlex* so = (SoPlex*)(soplex);
352 return so->objValueReal();
353 }
354
355 /** Returns the rational objective value (as a string) if a primal solution is available.
356 * The caller needs to ensure the char array is freed.
357 **/
358 char* SoPlex_objValueRationalString(void* soplex)
359 {
360 #ifndef SOPLEX_WITH_BOOST
361 throw SPxException("Rational functions cannot be used when built without Boost.");
362 #endif
363 /* coverity[unreachable] */
364 long unsigned int stringlength;
365 char* value;
366 std::string objstring;
367 SoPlex* so = (SoPlex*)(soplex);
368
369 stringlength = strlen(objstring.c_str()) + 1;
370 objstring = so->objValueRational().str();
371 value = new char[stringlength];
372 strncpy(value, objstring.c_str(), stringlength);
373 return value;
374 }
375
376 /** changes vectors of column bounds to lb and ub **/
377 void SoPlex_changeBoundsReal(void* soplex, double* lb, double* ub, int dim)
378 {
379 SoPlex* so = (SoPlex*)(soplex);
380 Vector lbvec(dim, lb);
381 Vector ubvec(dim, ub);
382 return so->changeBoundsReal(lbvec, ubvec);
383 }
384
385 /** changes bounds of a column to lb and ub **/
386 void SoPlex_changeVarBoundsReal(void* soplex, int colidx, double lb, double ub)
387 {
388 SoPlex* so = (SoPlex*)(soplex);
389 return so->changeBoundsReal(colidx, lb, ub);
390 }
391
392 /** changes rational bounds of a column to lbnum/lbdenom and ubnum/ubdenom **/
393 void SoPlex_changeVarBoundsRational(
394 void* soplex,
395 int colidx,
396 long lbnum,
397 long lbdenom,
398 long ubnum,
399 long ubdenom
400 )
401 {
402 #ifndef SOPLEX_WITH_BOOST
403 throw SPxException("Rational functions cannot be used when built without Boost.");
404 #endif
405 /* coverity[unreachable] */
406 SoPlex* so = (SoPlex*)(soplex);
407
408 /* get rational lower bound */
409 Rational lower(lbnum, lbdenom);
410
411 /* get rational upper bound */
412 Rational upper(ubnum, ubdenom);
413
414 return so->changeBoundsRational(colidx, lower, upper);
415 }
416
417 /** changes upper bound of column to ub **/
418 void SoPlex_changeVarUpperReal(void* soplex, int colidx, double ub)
419 {
420 SoPlex* so = (SoPlex*)(soplex);
421 return so->changeLowerReal(colidx, ub);
422 }
423
424 /** changes upper bound vector of columns to ub **/
425 void SoPlex_getUpperReal(void* soplex, double* ub, int dim)
426 {
427 SoPlex* so = (SoPlex*)(soplex);
428 Vector ubvec(dim, ub);
429
430 so->getLowerReal(ubvec);
431
432 for(int i = 0; i < dim; ++i)
433 ub[i] = ubvec[i];
434 }
435
436 /** returns status of row
437 * 0 -> row is set to its upper bound
438 * 1 -> row is set to its lower bound
439 * 2 -> row is fixed to its identical bounds
440 * 4 -> row is basic
441 * 5 -> nothing known about basis status
442 **/
443 int SoPlex_basisRowStatus(void* soplex, int rowidx)
444 {
445 SoPlex* so = (SoPlex*)(soplex);
446
447 return so->basisRowStatus(rowidx);
448 }
449
450 /** returns status of column
451 * 0 -> column is set to its upper bound
452 * 1 -> column is set to its lower bound
453 * 2 -> column is fixed to its identical bounds
454 * 3 -> column is free and fixed to zero
455 * 4 -> column is basic
456 * 5 -> nothing known about basis status
457 **/
458 int SoPlex_basisColStatus(void* soplex, int colidx)
459 {
460 SoPlex* so = (SoPlex*)(soplex);
461
462 return so->basisColStatus(colidx);
463 }
464
465 /** get non-zero entries and indices of row i **/
466 void SoPlex_getRowVectorReal(
467 void* soplex,
468 int i,
469 int* nnonzeros,
470 long* indices,
471 double* coefs
472 )
473 {
474 SoPlex* so = (SoPlex*)(soplex);
475 DSVector row;
476
477 so->getRowVectorReal(i, row);
478
479 *nnonzeros = row.size();
480
481 for(int j = 0; j < *nnonzeros; ++j)
482 {
483 coefs[j] = row.value(j);
484 indices[j] = row.index(j);
485 }
486 }
487
488 /** get non-zero entries and indices of rational row i **/
489 void SoPlex_getRowVectorRational(
490 void* soplex,
491 int i,
492 int* nnonzeros,
493 long* indices,
494 long* coefsnum,
495 long* coefsdenom
496 )
497 {
498 #ifndef SOPLEX_WITH_BOOST
499 throw SPxException("Rational functions cannot be used when built without Boost.");
500 #endif
501 SoPlex* so = (SoPlex*)(soplex);
502 LPRowRational lprow;
503 SVectorRational row;
504
505 so->getRowRational(i, lprow);
506 row = lprow.rowVector();
507
508 *nnonzeros = row.size();
509
510 for(int j = 0; j < *nnonzeros; ++j)
511 {
512 coefsnum[j] = (long int) numerator(row.value(j));
513 coefsdenom[j] = (long int) denominator(row.value(j));
514 indices[j] = row.index(j);
515 }
516 }
517
518 /** get lower and upper bounds of row i **/
519 void SoPlex_getRowBoundsReal(
520 void* soplex,
521 int i,
522 double* lb,
523 double* ub
524 )
525 {
526 SoPlex* so = (SoPlex*)(soplex);
527
528 *lb = so->lhsReal(i);
529 *ub = so->rhsReal(i);
530 }
531
532 /** get rational lower and upper bounds of row i **/
533 void SoPlex_getRowBoundsRational(
534 void* soplex,
535 int i,
536 long* lbnum,
537 long* lbdenom,
538 long* ubnum,
539 long* ubdenom
540 )
541 {
542 #ifndef SOPLEX_WITH_BOOST
543 throw SPxException("Rational functions cannot be used when built without Boost.");
544 #endif
545 SoPlex* so = (SoPlex*)(soplex);
546
547 *lbnum = (long int) numerator(so->lhsRational(i));
548 *lbdenom = (long int) denominator(so->lhsRational(i));
549 *ubnum = (long int) numerator(so->rhsRational(i));
550 *ubdenom = (long int) denominator(so->rhsRational(i));
551 }
552