loco
loco copied to clipboard
Wrong result when using :minimize on product of negative vars
I'm trying to use Loco to minimize the sum of squared errors in a constraint problem, however it seems that the solver is giving the wrong result when the variable ranges go into the negative numbers:
(solutions
[($in :e -5 5)]
:minimize ($* :e :e))
;; => ({:e 5})
Oddly enough, creating a temporary variable solves the issue in this case, but not in a larger model involving multiple squared vars.
(solutions
[($in :e -5 5)
($in :sse -1000 1000 :bounded)
($= :sse ($* :e :e))]
:minimize :sse)
;; => ({:e 0, :sse 0})
Am I doing something wrong here? The docstring for $*
says
One of the arguments can be a number greater than or equal to -1.
which is confusing as to whether it handles both arguments being negative.
You're right, something seems off here. As an experiment I changed the boundaries of your :sse
variable to [-25,25], to mimic what Loco is doing behind the scenes in your first example, and was able to reproduce the bizarre result:
user> (solutions
[($in :e -5 5)
($in :sse -25 25)
($= :sse ($* :e :e))]
:minimize :sse)
({:e -5, :sse -25})
It's possible there's a bug in Choco, but it would need more investigation and might not even get fixed upstream since I'm not depending on the latest major version of Choco. If I'm ever able to dust off and improve this project, my first TODO item is to update that dependency, which would give us more reliability in the underlying engine.
Just wanted to say that I've been trying out various constraint solvers and Loco had far by the most elegant and functional API for declaring constraint problems, I'm just slightly wary of the correctness of its solutions after encountering the above bug.
Is there anything I could help with upgrading to the latest upstream Choco version?
Can confirm that this was due to a bug in the Choco library, and not in the loco source. I'm working on a fork together with @aengelberg in https://github.com/mortenschioler/loco. The upstream dependency to Choco is updated in [io.github.mortenschioler/loco "0.3.2"]
, which I confirmed fixed the issue.
;; with `[org.choco-solver/choco-solver "0.3.0"], as in `[loco/loco "0.3.1"]:
(solutions
[($in :e -5 5)]
:minimize ($* :e :e))
=> ({:e 5})
;; with `[org.choco-solver/choco-solver "0.3.3"], as in `[io.github.mortenschioler/loco "0.3.2"]:
(solutions
[($in :e -5 5)]
:minimize ($* :e :e))
=> ({:e 0})