While using soplex as an exact LP solver, I encountered an issue trying to solve a problem like the one shown below.
Based on my superficial analysis, it seems it has something to do with the routine _transformUnbounded, and in general the unboundness check, not playing along with _performOptIRStable's check.
Below I have provided an instance that on my machine exhibits the problematic behavior.
I tested it with
SoPlex version 9.0.0 [mode: debug] [precision: 8 byte] [rational: GMP 6.2.1] [PaPILO n/a] [GitHash: 37f6c488-dirty]
The interesting part is that, feeding back to soplex the output of soplex.writeFileRational and then using the file as an input with
soplex file.mps --loadset=settings/exact.set
produces the correct output, provided the solver is in mode: optimized. So I wonder whether the assertion is wrong and the underlying logic is sound.
// Example
#include <iostream>
#include "soplex.h"
using namespace soplex;
void test_rational() {
SoPlex mysoplex;
/* set parameters for exact solving */
mysoplex.setIntParam(SoPlex::OBJSENSE, SoPlex::OBJSENSE_MINIMIZE);
// Same result with both SIMPLIFIER_OFF and SIMPLIFIER_AUTO
mysoplex.setIntParam(SoPlex::SIMPLIFIER, SoPlex::SIMPLIFIER_AUTO);
// Same result with both ALGORITHM_PRIMAL and ALGORITHM_DUAL
mysoplex.setIntParam(SoPlex::ALGORITHM, SoPlex::ALGORITHM_PRIMAL);
mysoplex.setIntParam(SoPlex::READMODE, SoPlex::READMODE_RATIONAL);
mysoplex.setIntParam(SoPlex::SYNCMODE, SoPlex::SYNCMODE_AUTO);
// Using SOLVEMODE_REAL and CHECKMODE_REAL,
// along with a non-zero FEASTOL and OPTTOL, does not manifest the issue
mysoplex.setIntParam(SoPlex::SOLVEMODE, SoPlex::SOLVEMODE_RATIONAL);
mysoplex.setIntParam(SoPlex::CHECKMODE, SoPlex::CHECKMODE_RATIONAL);
mysoplex.setRealParam(SoPlex::FEASTOL, 0.0);
mysoplex.setRealParam(SoPlex::OPTTOL, 0.0);
/*
* We first build the problem using sets of rows and cols
* The goal is to define the problem.
*
* Minimize
* obj: -1 x0
* Subject To
* C0 : 1 x1 - 1 x2 >= -1
* C1 : -1 x0 + 1 x1 - 1 x2 <= 1
* C2_1 : 1 x3 - 1 x4 >= -1
* C2_2 : 1 x3 - 1 x4 <= 1
* C3 : 1 x0 + 1 x5 >= 1
* Bounds
* 0 <= x0
* x1 = 1
* x2 = 1
* x3 = 1
* x4 = 1
* 1 <= x5 <= 121
* End
*
* When run externally, via
*
* soplex problem.lp --loadset=settings/exact.set
*
* SoPlex seems to produce the correct output, i.e., UNBOUNDED.
*/
LPColSetRational cols(6);
LPRowSetRational rows(4);
cols.add({-1.0, DSVectorRational(), infinity, 0});
cols.add({0.0, DSVectorRational(), 1, 1});
cols.add({0.0, DSVectorRational(), 1, 1});
cols.add({0.0, DSVectorRational(), 1, 1});
cols.add({0.0, DSVectorRational(), 1, 1});
cols.add({0.0, DSVectorRational(), 121, 1});
{
DSVectorRational vec(2);
vec.add(1, 1);
vec.add(2, -1);
rows.add(-1, vec, infinity);
}
{
DSVectorRational vec(3);
vec.add(0, -1);
vec.add(1, 1);
vec.add(2, -1);
rows.add(-infinity, vec, 1);
}
{
DSVectorRational vec(2);
vec.add(3, 1);
vec.add(4, -1);
rows.add(-1, vec, 1);
}
{
DSVectorRational vec(2);
vec.add(0, 1);
vec.add(5, 1);
rows.add(1, vec, infinity);
}
mysoplex.addColsRational(cols);
mysoplex.addRowsRational(rows);
// The optimiation fais on the assertion
//
// assert((lhsRational(r) == rhsRational(r)) == (_rowTypes[r] == RANGETYPE_FIXED));
//
// in src/soplex/solverational.hpp:2351
auto res = mysoplex.optimize();
std::cout << "Optimization result: " << res << std::endl;
}
int main() {
test_rational();
return 0;
}
While using soplex as an exact LP solver, I encountered an issue trying to solve a problem like the one shown below.
Based on my superficial analysis, it seems it has something to do with the routine
_transformUnbounded, and in general the unboundness check, not playing along with_performOptIRStable's check.Below I have provided an instance that on my machine exhibits the problematic behavior.
I tested it with
The interesting part is that, feeding back to soplex the output of
soplex.writeFileRationaland then using the file as an input withproduces the correct output, provided the solver is in
mode: optimized. So I wonder whether the assertion is wrong and the underlying logic is sound.