Open glebbelov opened 2 years ago
Running the following:
from amplpy import AMPL
ampl = AMPL()
ampl.option['solver'] = 'x-gurobi'
ampl.read('x-multmip3.mod')
ampl.read_data('multmip3.dat')
ampl.solve()
print(ampl.get_value('Total_Cost'))
produces the following output:
x-Gurobi 9.5.0: optimal solution; objective 231650
306 simplex iterations
31 branching nodes
Total_Cost = 233150
This is matching the AMPL session:
ampl: model x-multmip3.mod;
ampl: data multmip3.dat;
ampl: option solver x-gurobi;
ampl: solve;
x-Gurobi 9.5.0: optimal solution; objective 231650
306 simplex iterations
31 branching nodes
ampl: display Total_Cost;
Total_Cost = 233150
Does this AMPL session produce a different output on your machine?
You might need the current x-gurobi 20220303, but I did not manage to get it updated in the portal (messaged @mapgccv). But 20220217 might show similar behavior, although it reports a wrong solution.
Your Python code works well, identical to AMPL session. To "confuse" it, I added the following statement, similar to this line in AMPLRunner.py: ampl.setOption("solver_msg", 0)
. Then calling solve()
several times, each other time gives wrong result:
>>> print(ampl.get_value('Total_Cost'))
235625.0
>>> print(ampl.getCurrentObjective().value())
235625.0
>>> ampl.setOption("solver_msg", 0)
>>> ampl.solve()
x-Gurobi 9.5.1: Set parameter Username
Academic license - for non-commercial use only - expires 2022-05-06
>>> print(ampl.getCurrentObjective().value())
232424.9979338393
>>> print(ampl.getCurrentObjective().value())
232424.9979338393
>>> ampl.solve()
x-Gurobi 9.5.1: Set parameter Username
Academic license - for non-commercial use only - expires 2022-05-06
>>> print(ampl.getCurrentObjective().value())
235625.0
>>> ampl.solve()
x-Gurobi 9.5.1: Set parameter Username
Academic license - for non-commercial use only - expires 2022-05-06
>>> print(ampl.getCurrentObjective().value())
232424.9979338393
>>> ampl.solve()
x-Gurobi 9.5.1: Set parameter Username
Academic license - for non-commercial use only - expires 2022-05-06
>>> print(ampl.getCurrentObjective().value())
235625.0
>>> ampl.solve()
x-Gurobi 9.5.1: Set parameter Username
Academic license - for non-commercial use only - expires 2022-05-06
>>> print(ampl.getCurrentObjective().value())
232424.9979338393
Not sure this is it. This might be related to the bug mentioned in line 177: without calling terminateAMPL()
after every instance, when running the 102 fast tests, 1 test fails due to a wrong objective.
This might be related to warm start: every other iteration, Gurobi accepts it but then tries to improve it and says the solution violates tolerances. This does not happen when using big-M redefinitions (acc::or=1, acc:and=1, acc:ind_le=1).
Don't know if this is the issue. Running the tests with these options still gives different objectives.
Yep this seems to be the issue. Running with just "acc:and=1", only 1 of 2 examples differs. But only in the test script...
I am not being able to reproduce that with the previous version and the the latest version is not building on macOS:
/Users/fdabrandao/github/solvers-private/mp/include/mp/flat/constraint_base.h:144:3: error: constexpr function never produces a constant expression [-Winvalid-constexpr]
GetAprioriBounds() { return {-INFINITY, INFINITY}; }
^
/Users/fdabrandao/github/solvers-private/mp/include/mp/flat/constraint_base.h:144:31: note: non-constexpr constructor 'pair<float, float, false>' cannot be used in a constant expression
GetAprioriBounds() { return {-INFINITY, INFINITY}; }
^
/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX12.0.sdk/usr/include/c++/v1/utility:444:5: note: declared here
pair(_U1&& __u1, _U2&& __u2)
Regarding the difference between the AMPL session and amplpy, it should not happen. For every API interaction there is a corresponding AMPL session that can be recorded with ampl._start_recording('session.run')
.
I removed constexpr
from static constexpr std::pair<double, double>
in order to build the latest version on macOS and I was able to reproduce the issue with it.
The script:
from amplpy import AMPL
ampl = AMPL()
ampl._start_recording('session.run')
ampl.option['solver'] = 'x-gurobi'
ampl.option['solver_msg'] = 0
ampl.read('x-multmip3.mod')
ampl.read_data('multmip3.dat')
ampl.solve()
print(ampl.get_value('Total_Cost'))
ampl.solve()
print(ampl.get_value('Total_Cost'))
ampl.solve()
print(ampl.get_value('Total_Cost'))
ampl.solve()
print(ampl.get_value('Total_Cost'))
produces the output:
235624.99999999997
232424.9979338393
235624.99999999997
232424.9979338393
The corresponding AMPL session is:
option 'solver' 'x-gurobi';
option 'solver_msg' '0';
include 'x-multmip3.mod';
data 'multmip3.dat';
solve;
_display Total_Cost;
solve;
_display Total_Cost;
solve;
_display Total_Cost;
solve;
_display Total_Cost;
and it produces the same output:
_display 0 1 1:
Total_Cost
235624.99999999997
_display 0 1 1:
Total_Cost
232424.9979338393
_display 0 1 1:
Total_Cost
235624.99999999997
_display 0 1 1:
Total_Cost
232424.9979338393
When running x-multmip3.mod + multmip3.dat, see test/end2end/cases/fast/cp_global_constraints, AMPLPY reports a different objective value than the solver. This does not happen when solving in AMPL session.