1.1 --- a/cmake/FindILOG.cmake Thu Jan 21 08:36:53 2021 +0100
1.2 +++ b/cmake/FindILOG.cmake Thu Jan 21 18:58:37 2021 +0100
1.3 @@ -96,7 +96,7 @@
1.4 SET(ILOG_LIBRARIES ${ILOG_CPLEX_LIBRARY} ${ILOG_CONCERT_LIBRARY})
1.5 IF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
1.6 # SET(CPLEX_LIBRARIES "${CPLEX_LIBRARIES};m;pthread")
1.7 - SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread")
1.8 + SET(ILOG_LIBRARIES ${ILOG_LIBRARIES} "m" "pthread" "dl")
1.9 ENDIF(CMAKE_SYSTEM_NAME STREQUAL "Linux")
1.10 ENDIF(ILOG_FOUND)
1.11
2.1 --- a/lemon/clp.cc Thu Jan 21 08:36:53 2021 +0100
2.2 +++ b/lemon/clp.cc Thu Jan 21 18:58:37 2021 +0100
2.3 @@ -227,14 +227,14 @@
2.4 }
2.5
2.6 ClpLp::Value ClpLp::_getCoeff(int ix, int jx) const {
2.7 - CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[ix];
2.8 - CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[ix];
2.9 + CoinBigIndex begin = _prob->clpMatrix()->getVectorStarts()[jx];
2.10 + CoinBigIndex end = begin + _prob->clpMatrix()->getVectorLengths()[jx];
2.11
2.12 const int* indices = _prob->clpMatrix()->getIndices();
2.13 const double* elements = _prob->clpMatrix()->getElements();
2.14
2.15 - const int* it = std::lower_bound(indices + begin, indices + end, jx);
2.16 - if (it != indices + end && *it == jx) {
2.17 + const int* it = std::lower_bound(indices + begin, indices + end, ix);
2.18 + if (it != indices + end && *it == ix) {
2.19 return elements[it - indices];
2.20 } else {
2.21 return 0.0;
2.22 @@ -461,4 +461,14 @@
2.23 }
2.24 }
2.25
2.26 + void ClpLp::_write(std::string file, std::string format) const
2.27 + {
2.28 + if(format == "LP")
2.29 + _prob->writeLp(file.c_str(), "", 1e-5, 10, 5,
2.30 + sense()==ClpLp::MIN?1:-1,
2.31 + true
2.32 + );
2.33 + else throw UnsupportedFormatError(format);
2.34 + }
2.35 +
2.36 } //END OF NAMESPACE LEMON
3.1 --- a/lemon/clp.h Thu Jan 21 08:36:53 2021 +0100
3.2 +++ b/lemon/clp.h Thu Jan 21 18:58:37 2021 +0100
3.3 @@ -139,6 +139,8 @@
3.4
3.5 virtual void _messageLevel(MessageLevel);
3.6
3.7 + void _write(std::string file, std::string format) const;
3.8 +
3.9 public:
3.10
3.11 ///Solves LP with primal simplex method.
4.1 --- a/lemon/cplex.cc Thu Jan 21 08:36:53 2021 +0100
4.2 +++ b/lemon/cplex.cc Thu Jan 21 18:58:37 2021 +0100
4.3 @@ -158,7 +158,7 @@
4.4 } else {
4.5 const char s = 'R';
4.6 double len = ub - lb;
4.7 - CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &ub, &s,
4.8 + CPXaddrows(cplexEnv(), _prob, 0, 1, values.size(), &lb, &s,
4.9 &rmatbeg, &indices.front(), &values.front(), 0, 0);
4.10 CPXchgrngval(cplexEnv(), _prob, 1, &i, &len);
4.11 }
5.1 --- a/test/lp_test.cc Thu Jan 21 08:36:53 2021 +0100
5.2 +++ b/test/lp_test.cc Thu Jan 21 18:58:37 2021 +0100
5.3 @@ -339,6 +339,7 @@
5.4 check(lp.objCoeff(x1)==1,"First term should be 1 in the obj function!");
5.5 check(lp.sense() == lp.MAX,"This is a maximization!");
5.6 check(lp.coeff(upright,x1)==1,"The coefficient in question is 1!");
5.7 + check(lp.coeff(upright,x2)==2,"The coefficient in question is 1!");
5.8 check(lp.colLowerBound(x1)==0,
5.9 "The lower bound for variable x1 should be 0.");
5.10 check(lp.colUpperBound(x1)==LpSolver::INF,
5.11 @@ -424,6 +425,34 @@
5.12 delete lpclone;
5.13 }
5.14
5.15 +template<class LP>
5.16 +void rangeConstraintTest()
5.17 +{
5.18 + LP lp;
5.19 + // Add two columns (variables) to the problem
5.20 + typename LP::Col x1 = lp.addCol();
5.21 + typename LP::Col x2 = lp.addCol();
5.22 + // Add rows (constraints) to the problem
5.23 + lp.addRow(x1 - 5 <= x2);
5.24 + lp.addRow(0 <= 2 * x1 + x2 <= 25);
5.25 +
5.26 + // Set lower and upper bounds for the columns (variables)
5.27 + lp.colLowerBound(x1, 0);
5.28 + lp.colUpperBound(x2, 10);
5.29 +
5.30 + // Specify the objective function
5.31 + lp.max();
5.32 + lp.obj(5 * x1 + 3 * x2);
5.33 +
5.34 + // Solve the problem using the underlying LP solver
5.35 + lp.solve();
5.36 + // Print the results
5.37 + check(lp.primalType() == LP::OPTIMAL, "Optimal solution is not found");
5.38 + check(lp.primal() <= 67.501 && lp.primal() >= 67.499, "Wrong objective value");
5.39 + check(lp.primal(x1) <= 7.501 && lp.primal(x1) >= 7.499, "Wrong value for x1");
5.40 + check(lp.primal(x2) <= 10.001 && lp.primal(x2) >= 9.999, "Wrong value for x2");
5.41 +}
5.42 +
5.43 int main()
5.44 {
5.45 LpSkeleton lp_skel;
5.46 @@ -444,6 +473,7 @@
5.47 lpTest(lp_glpk1);
5.48 aTest(lp_glpk2);
5.49 cloneTest<GlpkLp>();
5.50 + rangeConstraintTest<GlpkLp>();
5.51 }
5.52 #endif
5.53
5.54 @@ -453,6 +483,7 @@
5.55 lpTest(lp_cplex1);
5.56 aTest(lp_cplex2);
5.57 cloneTest<CplexLp>();
5.58 + rangeConstraintTest<CplexLp>();
5.59 } catch (CplexEnv::LicenseError& error) {
5.60 check(false, error.what());
5.61 }
5.62 @@ -464,6 +495,7 @@
5.63 lpTest(lp_soplex1);
5.64 aTest(lp_soplex2);
5.65 cloneTest<SoplexLp>();
5.66 + rangeConstraintTest<Soplex>();
5.67 }
5.68 #endif
5.69
5.70 @@ -473,6 +505,7 @@
5.71 lpTest(lp_clp1);
5.72 aTest(lp_clp2);
5.73 cloneTest<ClpLp>();
5.74 + rangeConstraintTest<ClpLp>();
5.75 }
5.76 #endif
5.77
6.1 --- a/test/mip_test.cc Thu Jan 21 08:36:53 2021 +0100
6.2 +++ b/test/mip_test.cc Thu Jan 21 18:58:37 2021 +0100
6.3 @@ -61,7 +61,7 @@
6.4 }
6.5 }
6.6
6.7 -void aTest(MipSolver& mip)
6.8 +void aTest(MipSolver& mip, bool solve_empty=true)
6.9 {
6.10 //The following example is very simple
6.11
6.12 @@ -80,7 +80,8 @@
6.13 mip.max();
6.14
6.15 //Unconstrained optimization
6.16 - mip.solve();
6.17 + if(solve_empty)
6.18 + mip.solve();
6.19 //Check it out!
6.20
6.21 //Constraints
6.22 @@ -135,7 +136,11 @@
6.23 #ifdef LEMON_HAVE_MIP
6.24 {
6.25 Mip mip1;
6.26 +#if LEMON_DEFAULT_MIP==LEMON_CBC_
6.27 + aTest(mip1, false);
6.28 +#else
6.29 aTest(mip1);
6.30 +#endif
6.31 cloneTest<Mip>();
6.32 }
6.33 #endif
6.34 @@ -161,7 +166,7 @@
6.35 #ifdef LEMON_HAVE_CBC
6.36 {
6.37 CbcMip mip1;
6.38 - aTest(mip1);
6.39 + aTest(mip1, false);
6.40 cloneTest<CbcMip>();
6.41 }
6.42 #endif