From 0b5dbe859cc31ee885e04cda2fd985c6efafb0ce Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 24 Jan 2025 17:05:20 +0100 Subject: [PATCH 1/6] Implement Polyhedra.isredundant --- .github/workflows/ci.yml | 3 +++ Project.toml | 4 ++-- src/lp.jl | 3 +-- src/matrix.jl | 15 ++++++++++++++- src/nash.jl | 4 ++-- src/redund.jl | 20 ++++++++++++++++---- 6 files changed, 38 insertions(+), 11 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index d3819a7..02f4074 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -12,6 +12,9 @@ jobs: fail-fast: false matrix: include: + - version: '1.10' + os: ubuntu-latest + arch: x64 - version: '1' os: ubuntu-latest arch: x64 diff --git a/Project.toml b/Project.toml index 2eae82a..f75e420 100644 --- a/Project.toml +++ b/Project.toml @@ -1,7 +1,7 @@ name = "LRSLib" uuid = "262c1cb6-76e2-5873-868b-19ece3183cc5" repo = "https://github.com/JuliaPolyhedra/LRSLib.jl.git" -version = "0.8.2" +version = "0.9.0" [deps] LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e" @@ -11,7 +11,7 @@ lrslib_jll = "3873f7d0-7b7c-52c3-bdf4-8ab39b8f337a" [compat] Polyhedra = "0.7, 0.8" -julia = "1.6" +julia = "1.10" lrslib_jll = "= 0.3.3" [extras] diff --git a/src/lp.jl b/src/lp.jl index a820f07..f87b198 100644 --- a/src/lp.jl +++ b/src/lp.jl @@ -172,8 +172,7 @@ function print_lpoutput(m::HMatrix, print_solution::Bool=false) for i in 0:P.d-1 C_i = unsafe_load(P.C, i+1) Col_i = unsafe_load(P.Col, i+1) - idx = _unsafe_load_inequality(m, C_i) - print(" y_$(idx)=") + print(" y_$(_unsafe_load_inequality(m, C_i).value)=") temp1 = extractbigint(unsafe_load(Q.Lcm, Col_i+1)) * (-1) temp1 *= extractbigint(unsafe_load(unsafe_load(P.A, 1), Col_i+1)) temp2 = extractbigint(unsafe_load(Q.Gcd, Col_i+1)) diff --git a/src/matrix.jl b/src/matrix.jl index ab75559..4d3341f 100644 --- a/src/matrix.jl +++ b/src/matrix.jl @@ -177,7 +177,20 @@ Base.get(rep::RepMatrix, idx::Polyhedra.Index{Rational{BigInt}}) = Polyhedra.val function _unsafe_load_inequality(m::RepMatrix, idx) Q = unsafe_load(m.Q) - return unsafe_load(Q.inequality, idx - Q.lastdv + 1) + _to_index(m, unsafe_load(Q.inequality, idx - Q.lastdv + 1)) +end + +# For H-rep, LRS internal index `0` corresponds to objective and `1` correspond to the first halfspace/hyperplane +# so it's the same 1-based indexing than `Polyhedra.HIndex` +_to_index(::HMatrix{T}, i) = Polyhedra.HIndex{T,HalfSpace{T,Vector{T}}}(i) + +# For V-rep, LRS internal index `0` first halfspace/hyperplane +# so it's the 0-based indexing instead of `Polyhedra.HIndex` so we need to do `+1` +_to_index(::VMatrix{T}, i) = Polyhedra.VIndex{T,Vector{T}}(i + 1) + +function _unsafe_load_inequality(m::VMatrix, Polyhedra.VIndex) + Q = unsafe_load(m.Q) + return unsafe_load(Q.inequality, idx - Q.lastdv) end # H-representation diff --git a/src/nash.jl b/src/nash.jl index 1f182ed..b6a30e8 100644 --- a/src/nash.jl +++ b/src/nash.jl @@ -125,8 +125,8 @@ function nash2_main(hr1::HMatrix, hr2::HMatrix, linindex::Vector{Clong}) unsafe_load(unsafe_load(P1).B, i+1), ) if ((unsafe_load(Q1).nlinearity == 0) || - (j < unsafe_load(unsafe_load(Q1).linearity, 1))) - unsafe_store!(linearity, j, nlinearity+1) + (j.value < unsafe_load(unsafe_load(Q1).linearity, 1))) + unsafe_store!(linearity, j.value, nlinearity+1) nlinearity += 1 end end diff --git a/src/redund.jl b/src/redund.jl index 362322e..5e5dec1 100644 --- a/src/redund.jl +++ b/src/redund.jl @@ -1,3 +1,15 @@ +function _inequality_indices(m::HMatrix) + # FIXME Not sure what `lastdv` is doing, isn't it just always zero ? + lastdv = unsafe_load(m.Q).lastdv + return (lastdv + 1):(m_A + d) +end + +function _inequality_indices(m::VMatrix) + # FIXME Not sure what `lastdv` is doing, isn't it just always zero ? + lastdv = unsafe_load(m.Q).lastdv + return (lastdv + 2):(m_A + d + 1) +end + function redund(m::RepMatrix) # if non-negative flag is set, non-negative constraints are not input # explicitly, and are not checked for redundancy @@ -25,19 +37,19 @@ function redund(m::RepMatrix) # rows 0..lastdv are cost, decision variables, or linearities # other rows need to be tested - redset = BitSet() + redset = [] # FIXME concrete type for index in (lastdv + 1):(m_A + d) - ineq = _unsafe_load_inequality(m, index) # the input inequality number corr. to this index status = checkindex(m, index) if :redundant == checkindex(m, index) - push!(redset, ineq) + # the input inequality number corr. to this index + push!(redset, _unsafe_load_inequality(m, index)) end end redset end -function redundi(m::RepMatrix, ineq::Int) +function Polyhedra.isredundant(m::RepMatrix, ineq::Polyhedra.Index) if m.status == :AtNoBasis getfirstbasis(m) end From bcf367ba553cde937e64f8d9e1a2f763d3d4ad74 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Fri, 24 Jan 2025 17:31:23 +0100 Subject: [PATCH 2/6] Fixes --- src/matrix.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/matrix.jl b/src/matrix.jl index 4d3341f..228d42a 100644 --- a/src/matrix.jl +++ b/src/matrix.jl @@ -182,11 +182,11 @@ end # For H-rep, LRS internal index `0` corresponds to objective and `1` correspond to the first halfspace/hyperplane # so it's the same 1-based indexing than `Polyhedra.HIndex` -_to_index(::HMatrix{T}, i) = Polyhedra.HIndex{T,HalfSpace{T,Vector{T}}}(i) +_to_index(::HMatrix{T}, i) where {T} = Polyhedra.HIndex{T,HalfSpace{T,Vector{T}}}(i) # For V-rep, LRS internal index `0` first halfspace/hyperplane # so it's the 0-based indexing instead of `Polyhedra.HIndex` so we need to do `+1` -_to_index(::VMatrix{T}, i) = Polyhedra.VIndex{T,Vector{T}}(i + 1) +_to_index(::VMatrix{T}, i) where {T} = Polyhedra.VIndex{T,Vector{T}}(i + 1) function _unsafe_load_inequality(m::VMatrix, Polyhedra.VIndex) Q = unsafe_load(m.Q) From b7c204febc3db8cffff9b60f74a576b5a9a439e5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sat, 25 Jan 2025 18:20:17 +0100 Subject: [PATCH 3/6] Fixes --- src/matrix.jl | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/matrix.jl b/src/matrix.jl index 228d42a..c3d8dc0 100644 --- a/src/matrix.jl +++ b/src/matrix.jl @@ -182,15 +182,16 @@ end # For H-rep, LRS internal index `0` corresponds to objective and `1` correspond to the first halfspace/hyperplane # so it's the same 1-based indexing than `Polyhedra.HIndex` -_to_index(::HMatrix{T}, i) where {T} = Polyhedra.HIndex{T,HalfSpace{T,Vector{T}}}(i) +function _to_index(::HMatrix, i) + T = Rational{BigInt} + return Polyhedra.HIndex{T,HalfSpace{T,Vector{T}}}(i) +end # For V-rep, LRS internal index `0` first halfspace/hyperplane # so it's the 0-based indexing instead of `Polyhedra.HIndex` so we need to do `+1` -_to_index(::VMatrix{T}, i) where {T} = Polyhedra.VIndex{T,Vector{T}}(i + 1) - -function _unsafe_load_inequality(m::VMatrix, Polyhedra.VIndex) - Q = unsafe_load(m.Q) - return unsafe_load(Q.inequality, idx - Q.lastdv) +function _to_index(::VMatrix, i) + T = Rational{BigInt} + return Polyhedra.VIndex{T,Vector{T}}(i + 1) end # H-representation From 64cc5de86b647dacbca12bb2af49d9589a86ce08 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Sun, 26 Jan 2025 10:23:39 +0100 Subject: [PATCH 4/6] Fixes --- src/matrix.jl | 4 ++-- src/polyhedron.jl | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/matrix.jl b/src/matrix.jl index c3d8dc0..a460822 100644 --- a/src/matrix.jl +++ b/src/matrix.jl @@ -184,14 +184,14 @@ end # so it's the same 1-based indexing than `Polyhedra.HIndex` function _to_index(::HMatrix, i) T = Rational{BigInt} - return Polyhedra.HIndex{T,HalfSpace{T,Vector{T}}}(i) + return Polyhedra.Index{T,HalfSpace{T,Vector{T}}}(i) end # For V-rep, LRS internal index `0` first halfspace/hyperplane # so it's the 0-based indexing instead of `Polyhedra.HIndex` so we need to do `+1` function _to_index(::VMatrix, i) T = Rational{BigInt} - return Polyhedra.VIndex{T,Vector{T}}(i + 1) + return Polyhedra.Index{T,Vector{T}}(i + 1) end # H-representation diff --git a/src/polyhedron.jl b/src/polyhedron.jl index 9cc56ae..61b88bd 100644 --- a/src/polyhedron.jl +++ b/src/polyhedron.jl @@ -199,7 +199,7 @@ _getrepfor(p::Polyhedron, ::Polyhedra.HIndex, status::Symbol) = getinem(p, statu _getrepfor(p::Polyhedron, ::Polyhedra.VIndex, status::Symbol) = getextm(p, status) function Polyhedra.isredundant(p::Polyhedron, idx::Polyhedra.Index; strongly=false, cert=false, solver=nothing) @assert !strongly && !cert - redundi(_getrepfor(p, idx, :AlmostFresh), idx.value) # FIXME does it need to be fresh ? + Polyhedra.isredundant(_getrepfor(p, idx, :AlmostFresh), idx) # FIXME does it need to be fresh ? end # Optional interface function Polyhedra.loadpolyhedron!(p::Polyhedron, filename::AbstractString, ::Type{Val{:ext}}) From 69d6951e60d785d272a0c223986a0f49c2b40871 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Mon, 27 Jan 2025 09:59:04 +0100 Subject: [PATCH 5/6] Fix --- src/polyhedron.jl | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/polyhedron.jl b/src/polyhedron.jl index 61b88bd..7690c7d 100644 --- a/src/polyhedron.jl +++ b/src/polyhedron.jl @@ -169,7 +169,7 @@ function Polyhedra.removehredundancy!(p::Polyhedron) ine = getine(p) inem = getinem(p, :AlmostFresh) # FIXME does it need to be fresh ? linset = getinputlinsubset(inem) - redset = redund(inem) + redset = [idx.value for idx in redund(extm)] nonred = setdiff(BitSet(1:size(ine.A, 1)), redset) nonred = collect(setdiff(nonred, linset)) lin = collect(linset) @@ -183,7 +183,7 @@ function Polyhedra.removevredundancy!(p::Polyhedron) detectvlinearity!(p) ext = getext(p) extm = getextm(p, :AlmostFresh) # FIXME does it need to be fresh ? - redset = BitSet(redund(extm) .+ 1) + redset = [idx.value for idx in redund(extm)] nonred = setdiff(BitSet(1:size(ext.R, 1)), redset) nonred = collect(setdiff(nonred, ext.linset)) lin = collect(ext.linset) From 9257be82fedf76831a5ac96629cf49b992f3e412 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Beno=C3=AEt=20Legat?= Date: Tue, 28 Jan 2025 10:01:15 +0100 Subject: [PATCH 6/6] Fix --- src/polyhedron.jl | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/polyhedron.jl b/src/polyhedron.jl index 7690c7d..5cb5090 100644 --- a/src/polyhedron.jl +++ b/src/polyhedron.jl @@ -169,7 +169,7 @@ function Polyhedra.removehredundancy!(p::Polyhedron) ine = getine(p) inem = getinem(p, :AlmostFresh) # FIXME does it need to be fresh ? linset = getinputlinsubset(inem) - redset = [idx.value for idx in redund(extm)] + redset = [idx.value for idx in redund(inem)] nonred = setdiff(BitSet(1:size(ine.A, 1)), redset) nonred = collect(setdiff(nonred, linset)) lin = collect(linset)