Open schillic opened 4 years ago
IIUC, you suggest adding a keyword argument solver = default_solver(p)
and pass the solver to detectvlinearity!
in line 76 and 77, is that correct ?
That or always use solver = default_solver(p)
(but maybe there is a reason for not doing that).
Which solver is used in your example? It seems to be GLPK, isn't it the default solver?
Then I don't get your comment:
The function
removevredundancy!
does not use the solver associated withP
(as can be seen in the stack trace) and then crashes.
In the stacktrace, we see that it uses GLPK which is the solver associated with P
.
It goes to line 72 which is the solver === nothing
branch.
The error message say that presolve
was not activated but I think the solver I passed had it activated. I am not 100% sure but I guess in the function in line 72 it uses a different solver.
It is using default_solver
too
https://github.com/JuliaPolyhedra/Polyhedra.jl/blob/485f7dfb2abb93b9032d711bc017c355796ad02e/src/linearity.jl#L35
But that one does not have presolve
activated.
Then that means that p.solver
does not have presolve. There is no default solver in Polyhedra if p.solver
is nothing so if a solver is used, the only possibility is that you set it to the library.
~I tried to reproduce what I did but the behavior is not the same as in the OP. I guess I did not pass the solver to the correct polyhedron :sweat_smile:~ Now I could reproduce.
julia> using Polyhedra, JuMP, GLPK
julia> v1 = [[1.0, 1.0], [-1.0, 1.0], [1.0, -1.0], [-1.0, -1.0]];
julia> v2 = [[3.0, 3.0], [1.0, 3.0], [1.0, 1.0], [3.0, 1.0]];
julia> solver = Polyhedra.DefaultLibrary{Float64}(
JuMP.optimizer_with_attributes(GLPK.Optimizer, "presolve" => GLPK.ON));
julia> p1 = polyhedron(Polyhedra.vrep(v1), solver);
julia> p2 = polyhedron(Polyhedra.vrep(v2), solver);
julia> p = Polyhedra.intersect(p1, p2);
julia> Polyhedra.default_solver(p1)
MathOptInterface.OptimizerWithAttributes(GLPK.Optimizer,
Pair{MathOptInterface.AbstractOptimizerAttribute,Any}[MathOptInterface.RawParameter("presolve") => 1])
julia> Polyhedra.default_solver(p2)
MathOptInterface.OptimizerWithAttributes(GLPK.Optimizer,
Pair{MathOptInterface.AbstractOptimizerAttribute,Any}[MathOptInterface.RawParameter("presolve") => 1])
julia> Polyhedra.default_solver(p)
MathOptInterface.OptimizerWithAttributes(GLPK.Optimizer,
Pair{MathOptInterface.AbstractOptimizerAttribute,Any}[MathOptInterface.RawParameter("presolve") => 1])
julia> removevredundancy!(p);
*crash from OP*
Maybe the solver encounters numerical errors even if the presolve is on ? The warning is just a hint that might be useful, it does not mean that the presolve is off.
Maybe the solver encounters numerical errors even if the presolve is on ? The warning is just a hint that might be useful, it does not mean that the presolve is off.
Indeed, you are right, so the original discussion is wrong. Still, this example should somehow work as it is not particularly difficult. Geometrically it is the intersection of two squares in a single vertex - clearly a corner case but doable.
After replacing line 59 in
by solver = default_solver(p)
, it does not crash anymore. That is why I thought that passing the solver would be the solution. But this is not really the solution as it just skips the call to detecthlinearity!(p)
, which is the real source.
The delicate aspect here is that I can call detecthlinearity!(p)
and detectvlinearity!(p)
individually without a problem. But after calling detecthlinearity!(p)
once, the second time it crashes. If I do not call detectvlinearity!(p)
first, then that call will also crash (which is what happens in the OP; if it had been called first, I guess the second call ignores the H-representation and works on the V-representation).
My understanding is that detecthlinearity!(p)
can make a stable representation unstable. Not sure if we can do anything about that.
julia> using Polyhedra, JuMP, GLPK
julia> v1 = [[1.0, 1.0], [-1.0, 1.0], [1.0, -1.0], [-1.0, -1.0]];
julia> v2 = [[3.0, 3.0], [1.0, 3.0], [1.0, 1.0], [3.0, 1.0]];
julia> solver = Polyhedra.DefaultLibrary{Float64}(
JuMP.optimizer_with_attributes(GLPK.Optimizer, "presolve" => GLPK.ON));
julia> p1 = polyhedron(Polyhedra.vrep(v1), solver);
julia> p2 = polyhedron(Polyhedra.vrep(v2), solver);
julia> p = Polyhedra.intersect(p1, p2)
Polyhedron DefaultPolyhedron{Float64,Polyhedra.Intersection{Float64,Array{Float64,1},Int64},Polyhedra.Hull{Float64,Array{Float64,1},Int64}}:
8-element iterator of HalfSpace{Float64,Array{Float64,1}}:
HalfSpace([-0.0, 0.3333333333333333], 0.3333333333333333)
HalfSpace([0.18181818181818182, -0.0], 0.18181818181818182)
HalfSpace([-0.0, -0.15], 0.15)
HalfSpace([-0.13953488372093026, -0.0], 0.13953488372093026)
HalfSpace([1.460819769243627e-17, 0.13157894736842105], 0.39473684210526316)
HalfSpace([-0.14251425142514254, 3.560008573561765e-17], -0.1425142514251425)
HalfSpace([0.07809788267962511, -0.0], 0.23429364803887537)
HalfSpace([-1.0367150553151396e-17, -0.0818244458905945], -0.08182444589059451)
julia> detectvlinearity!(p) # works fine
V-representation Polyhedra.Hull{Float64,Array{Float64,1},Int64}:
1-element iterator of Array{Float64,1}:
[1.0, 1.0]
julia> detecthlinearity!(p) # works fine but changes the constraints
H-representation Polyhedra.Intersection{Float64,Array{Float64,1},Int64}:
2-element iterator of HyperPlane{Float64,Array{Float64,1}}:
HyperPlane([-0.0, 0.3333333333333333], 0.3333333333333333)
HyperPlane([0.18181818181818182, -0.0], 0.18181818181818182),
4-element iterator of HalfSpace{Float64,Array{Float64,1}}:
HalfSpace([-0.0, -0.15], 0.15)
HalfSpace([-0.13953488372093026, -0.0], 0.13953488372093026)
HalfSpace([1.460819769243627e-17, 0.13157894736842105], 0.39473684210526316)
HalfSpace([0.07809788267962511, -0.0], 0.23429364803887537)
julia> detecthlinearity!(p) # second call crashes
I have a simple polyhedron
P
(below). The functionremovevredundancy!
does not use the solver associated withP
(as can be seen in the stack trace) and then crashes. The reason is thatsolver
is initialized tonothing
and the linesolver = default_solver(p)
is only executed under some conditions. There is no other way to pass the solver to this function.https://github.com/JuliaPolyhedra/Polyhedra.jl/blob/485f7dfb2abb93b9032d711bc017c355796ad02e/src/redundancy.jl#L58-L79