# HG changeset patch
# User Alpar Juttner <alpar@cs.elte.hu>
# Date 1611155841 -3600
# Wed Jan 20 16:17:21 2021 +0100
# Node ID 57abff252556e0ffd928de63314904bd531974c1
# Parent 8c567e298d7f3fad82cc66754f2fb6c4a420366b
Bugfixes in CplexBase and ClpLp (#639)
diff --git a/cmake/FindILOG.cmake b/cmake/FindILOG.cmake
a
|
b
|
|
96 | 96 | SET(ILOG_LIBRARIES ${ILOG_CPLEX_LIBRARY} ${ILOG_CONCERT_LIBRARY}) |
97 | 97 | IF(CMAKE_SYSTEM_NAME STREQUAL "Linux") |
98 | 98 | # SET(CPLEX_LIBRARIES "${CPLEX_LIBRARIES};m;pthread") |
99 | | SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread") |
| 99 | SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread" "dl") |
100 | 100 | ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux") |
101 | 101 | ENDIF(ILOG_FOUND) |
102 | 102 | |
diff --git a/lemon/clp.cc b/lemon/clp.cc
a
|
b
|
|
227 | 227 | } |
228 | 228 | |
229 | 229 | ClpLp::Value ClpLp::_getCoeff(int ix, int jx) const { |
230 | | CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix]; |
231 | | CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix]; |
| 230 | CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[jx]; |
| 231 | CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[jx]; |
232 | 232 | |
233 | 233 | const int* indices = _prob->clpMatrix()->getIndices(); |
234 | 234 | const double* elements = _prob->clpMatrix()->getElements(); |
235 | 235 | |
236 | | const int* it = std::lower_bound(indices + begin, indices + end, jx); |
237 | | if (it != indices + end && *it == jx) { |
| 236 | const int* it = std::lower_bound(indices + begin, indices + end, ix); |
| 237 | if (it != indices + end && *it == ix) { |
238 | 238 | return elements[it - indices]; |
239 | 239 | } else { |
240 | 240 | return 0.0; |
diff --git a/lemon/cplex.cc b/lemon/cplex.cc
a
|
b
|
|
158 | 158 | } else { |
159 | 159 | const char s = 'R'; |
160 | 160 | double len = ub - lb; |
161 | | CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &ub, &s, |
| 161 | CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &lb, &s, |
162 | 162 | &rmatbeg, &indices.front(), &values.front(), 0, 0); |
163 | 163 | CPXchgrngval(cplexEnv(), _prob, 1, &i, &len); |
164 | 164 | } |
diff --git a/test/lp_test.cc b/test/lp_test.cc
a
|
b
|
|
339 | 339 | check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!"); |
340 | 340 | check(lp.sense() == lp.MAX,"This is a maximization!"); |
341 | 341 | check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!"); |
| 342 | check(lp.coeff(upright,x2)==2,"The coefficient in question is 1!"); |
342 | 343 | check(lp.colLowerBound(x1)==0, |
343 | 344 | "The lower bound for variable x1 should be 0."); |
344 | 345 | check(lp.colUpperBound(x1)==LpSolver::INF, |
… |
… |
|
424 | 425 | delete lpclone; |
425 | 426 | } |
426 | 427 | |
| 428 | template<class LP> |
| 429 | void rangeConstraintTest() |
| 430 | { |
| 431 | LP lp; |
| 432 | // Add two columns (variables) to the problem |
| 433 | typename LP::Col x1 = lp.addCol(); |
| 434 | typename LP::Col x2 = lp.addCol(); |
| 435 | // Add rows (constraints) to the problem |
| 436 | lp.addRow(x1 - 5 <= x2); |
| 437 | lp.addRow(0 <= 2 * x1 + x2 <= 25); |
| 438 | |
| 439 | // Set lower and upper bounds for the columns (variables) |
| 440 | lp.colLowerBound(x1, 0); |
| 441 | lp.colUpperBound(x2, 10); |
| 442 | |
| 443 | // Specify the objective function |
| 444 | lp.max(); |
| 445 | lp.obj(5 * x1 + 3 * x2); |
| 446 | |
| 447 | // Solve the problem using the underlying LP solver |
| 448 | lp.solve(); |
| 449 | // Print the results |
| 450 | check(lp.primalType() == LP::OPTIMAL, "Optimal solution is not found"); |
| 451 | check(lp.primal() <= 67.501 && lp.primal() >= 67.499, "Wrong objective value"); |
| 452 | check(lp.primal(x1) <= 7.501 && lp.primal(x1) >= 7.499, "Wrong value for x1"); |
| 453 | check(lp.primal(x2) <= 10.001 && lp.primal(x2) >= 9.999, "Wrong value for x2"); |
| 454 | } |
| 455 | |
427 | 456 | int main() |
428 | 457 | { |
429 | 458 | LpSkeleton lp_skel; |
… |
… |
|
444 | 473 | lpTest(lp_glpk1); |
445 | 474 | aTest(lp_glpk2); |
446 | 475 | cloneTest<GlpkLp>(); |
| 476 | rangeConstraintTest<GlpkLp>(); |
447 | 477 | } |
448 | 478 | #endif |
449 | 479 | |
… |
… |
|
453 | 483 | lpTest(lp_cplex1); |
454 | 484 | aTest(lp_cplex2); |
455 | 485 | cloneTest<CplexLp>(); |
| 486 | rangeConstraintTest<CplexLp>(); |
456 | 487 | } catch (CplexEnv::LicenseError& error) { |
457 | 488 | check(false, error.what()); |
458 | 489 | } |
… |
… |
|
464 | 495 | lpTest(lp_soplex1); |
465 | 496 | aTest(lp_soplex2); |
466 | 497 | cloneTest<SoplexLp>(); |
| 498 | rangeConstraintTest<Soplex>(); |
467 | 499 | } |
468 | 500 | #endif |
469 | 501 | |
… |
… |
|
473 | 505 | lpTest(lp_clp1); |
474 | 506 | aTest(lp_clp2); |
475 | 507 | cloneTest<ClpLp>(); |
| 508 | rangeConstraintTest<ClpLp>(); |
476 | 509 | } |
477 | 510 | #endif |
478 | 511 | |
diff --git a/test/mip_test.cc b/test/mip_test.cc
a
|
b
|
|
61 | 61 | } |
62 | 62 | } |
63 | 63 | |
64 | | void aTest(MipSolver& mip) |
| 64 | void aTest(MipSolver& mip, bool solve_empty=true) |
65 | 65 | { |
66 | 66 | //The following example is very simple |
67 | 67 | |
… |
… |
|
80 | 80 | mip.max(); |
81 | 81 | |
82 | 82 | //Unconstrained optimization |
83 | | mip.solve(); |
| 83 | if(solve_empty) |
| 84 | mip.solve(); |
84 | 85 | //Check it out! |
85 | 86 | |
86 | 87 | //Constraints |
… |
… |
|
135 | 136 | #ifdef LEMON_HAVE_MIP |
136 | 137 | { |
137 | 138 | Mip mip1; |
| 139 | #if LEMON_DEFAULT_MIP==LEMON_CBC_ |
| 140 | aTest(mip1, false); |
| 141 | #else |
138 | 142 | aTest(mip1); |
| 143 | #endif |
139 | 144 | cloneTest<Mip>(); |
140 | 145 | } |
141 | 146 | #endif |
… |
… |
|
161 | 166 | #ifdef LEMON_HAVE_CBC |
162 | 167 | { |
163 | 168 | CbcMip mip1; |
164 | | aTest(mip1); |
| 169 | aTest(mip1, false); |
165 | 170 | cloneTest<CbcMip>(); |
166 | 171 | } |
167 | 172 | #endif |