Skip to content

Commit

Permalink
vint() method
Browse files Browse the repository at this point in the history
  • Loading branch information
Brian Doolittle committed May 27, 2020
1 parent 1ea64e4 commit 6f72487
Show file tree
Hide file tree
Showing 6 changed files with 127 additions and 11 deletions.
1 change: 1 addition & 0 deletions docs/src/exports.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,4 +28,5 @@ traf
portsort
posie
fctp
vint
```
5 changes: 3 additions & 2 deletions src/XPORTA.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ historical names from the PORTA software.
- [`fctp`](@ref) - Given inequalities and a `POI`, determines which inequalities
tightly bound the `POI` and which inequalities exclude elements of the `POI`.
In each case, the satisfying/violating elements are returned in a `POI`.
- [`vint`](@ref) - Enumerates the integral points which satisfy the linear system specified by an `IEQ`.
The compiled PORTA binaries are accessed through [PORTA_jll.jl](https://github.com/JuliaBinaryWrappers/PORTA_jll.jl)
Expand All @@ -39,8 +40,8 @@ using PORTA_jll
using Suppressor

export POI, IEQ # types
export traf, portsort # xporta methods
export fctp, posie # valid methods
export traf, portsort # xporta methods
export fctp, posie, vint # valid methods

# including local files
include("./types.jl")
Expand Down
4 changes: 2 additions & 2 deletions src/types.jl
Original file line number Diff line number Diff line change
Expand Up @@ -114,8 +114,8 @@ both have the following form.
`IEQ` Fields:
* `inequalities`: each matrix row is a linear inequality, the first M elements indexed `1:(end-1)` are α and the last element indexed `end` is β.
* `equalities`: each matrix row is linear equality, the first M elements indexed `1:(end-1)` are α and the last element indexed `end` is β.
* `lower_bounds`: each matrix row is a lower bound for enumerating integral points with `vint`.
* `upper_bounds`: each matrix row is an upper bound for enumerating integral points with `vint`.
* `lower_bounds`: a row vector which specifies the lower bound on each individual parameter. Used for enumerating integral points with `vint`.
* `upper_bounds`: a row vector which specifies the upper bound on each individual parameter. Used for enumerating integral points with `vint`.
* `valid`: a feasible point for the linear system.
* `dim`: the dimension of in/equalities, upper/lower bounds, etc. This field is auto-populated on construction.
Expand Down
59 changes: 53 additions & 6 deletions src/valid_subroutines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,7 @@ of the `IEQ`. A `POI` containing the valid points and rays is returned.
`kwargs` is shorthand for the following keyword arguments:
* `dir :: String = "./"` - The directory to which files are written.
* `filename :: String = "traf_tmp"`- The name of produced files.
* `filename :: String = "posie_tmp"`- The name of produced files.
* `cleanup :: Bool = true` - If `true`, created files are removed after computation.
* `verbose :: Bool = false`- If `true`, PORTA will print progress to `STDOUT`.
Expand All @@ -62,7 +62,7 @@ function posie(ieq::IEQ, poi::POI;

valid_poi = isfile(ieq_filepath * ".poi") ? read_poi(ieq_filepath * ".poi") : POI(vertices = Array{Rational{Int}}(undef,0,0))

if (cleanup)
if cleanup
rm_porta_tmp(dir)
end

Expand Down Expand Up @@ -100,7 +100,7 @@ and `"invalid"` dictionaries may include zero or more elements.
`kwargs` is shorthand for the following keyword arguments:
* `dir::String = "./"` - The directory to which files are written.
* `filename::String = "traf_tmp"`- The name of produced files.
* `filename::String = "fctp_tmp"`- The name of produced files.
* `cleanup::Bool = true` - If `true`, created files are removed after computation.
* `verbose::Bool = false`- If `true`, PORTA will print progress to `STDOUT`.
Expand Down Expand Up @@ -157,7 +157,7 @@ function fctp( inequalities::PortaMatrix, poi::POI;
end
end

if (cleanup)
if cleanup
rm_porta_tmp(dir)
end

Expand Down Expand Up @@ -191,7 +191,7 @@ is returned.
`kwargs` is shorthand for the following keyword arguments:
* `dir::String = "./"` - The directory to which files are written.
* `filename::String = "traf_tmp"`- The name of produced files.
* `filename::String = "iespo_tmp"`- The name of produced files.
* `strong_validity::Bool = false` - Prints the strong validity table to the output `IEQ`, (requires manual parsing).
* `cleanup::Bool = true` - If `true`, created files are removed after computation.
* `verbose::Bool = false`- If `true`, PORTA will print progress to `STDOUT`.
Expand Down Expand Up @@ -221,9 +221,56 @@ function iespo(ieq::IEQ, poi::POI;

valid_ieq = read_ieq(poi_filepath * ".ieq")

if (cleanup)
if cleanup
rm_porta_tmp(dir)
end

return valid_ieq
end

"""
vint( ieq::IEQ; kwargs... ) :: POI{Rational{Int}}
Enumerates all integral (integer) points which satisfy the linear system specified by the `IEQ`
and bounds specified by `upper_bounds` and `lower_bounds` fields of the `IEQ`.
These points may lie on the facets, vertices, or interior of the polytope specified by
`IEQ`. If no equalities or inequalities are specified, all integral points within
the bounds will be enumerated.
`kwargs` specifes the keyword args:
* `dir::String = "./"` - The directory to which files are written.
* `filename::String = "vint_tmp"`- The name of produced files.
* `cleanup::Bool = true` - If `true`, created files are removed after computation.
* `verbose::Bool = false`- If `true`, PORTA will print progress to `STDOUT`.
A `DomainError` is thrown if the `IEQ` does not contain upper/lower bounds or
if upper/lower bounds contain more than one row.
For more details regarding `vint()` please refer to the [PORTA vint documentation](https://github.com/bdoolittle/julia-porta#vint).
"""
function vint(ieq::IEQ;
dir::String="./",
filename::String="vint_tmp",
cleanup::Bool=true,
verbose::Bool=false
) :: POI{Rational{Int}}

workdir = cleanup ? make_porta_tmp(dir) : dir

if (length(ieq.upper_bounds) != ieq.dim) || (length(ieq.lower_bounds) != ieq.dim)
throw(DomainError((ieq.upper_bounds, ieq.lower_bounds), "upper/lower bounds are required for vint and there should one row for each."))
end

ieq_filepath = write_ieq(filename, ieq, dir=workdir)

run_valid("-V", [ieq_filepath])

# replace .ieq file extension with .poi extension
poi = read_poi(replace(ieq_filepath, r"\.ieq$"=>".poi"))

if cleanup
rm_porta_tmp(dir)
end

return poi
end
2 changes: 1 addition & 1 deletion src/xporta_subroutines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -154,7 +154,7 @@ Sorting is performed in the following hierarchy:
`kwargs` is shorthand for the keyword arguments:
* `dir::String = "./"` - The directory in which to write files.
* `filename::String = "traf_tmp"`- The name of produced files.
* `filename::String = "portsort_tmp"`- The name of produced files.
* `cleanup::Bool = true` - If `true`, created files are removed after computation.
* `verbose::Bool = false`- If `true`, PORTA will print progress to `STDOUT`.
Expand Down
67 changes: 67 additions & 0 deletions test/integration/valid_subroutines.jl
Original file line number Diff line number Diff line change
Expand Up @@ -231,4 +231,71 @@ end
end
end

@testset "vint()" begin
@testset "invalid upper/lower bounds" begin
@test_throws DomainError vint(IEQ(inequalities=[-1 0 0 0;0 -1 0 0;0 0 -1 0], upper_bounds = [1 1 1;2 2 2], lower_bounds = [0 0 0]), dir=dir)
@test_throws DomainError vint(IEQ(inequalities=[-1 0 0 0;0 -1 0 0;0 0 -1 0], upper_bounds = [1 1 1], lower_bounds = [0 0 0;-1 -1 -1]), dir=dir)
@test_throws DomainError vint(IEQ(inequalities=[-1 0 0 0;0 -1 0 0;0 0 -1 0], upper_bounds = [1 1 1]), dir=dir)
@test_throws DomainError vint(IEQ(inequalities=[-1 0 0 0;0 -1 0 0;0 0 -1 0], lower_bounds = [0 0 0]), dir=dir)
end

@testset "finds vertices of simple polyhedra given complete H-representation" begin
@testset "unit cube with corner at origin has vertices as integer points" begin
int_cube_ieq = IEQ(inequalities=[0 0 1 1;0 1 0 1;1 0 0 1;-1 0 0 0;0 -1 0 0;0 0 -1 0], upper_bounds=[1 1 1], lower_bounds=[0 0 0])
int_cube_poi = vint(int_cube_ieq, dir=dir)

@test int_cube_poi.conv_section == [
0 0 0;0 0 1;0 1 0;0 1 1;
1 0 0;1 0 1;1 1 0;1 1 1;
]
@test length(int_cube_poi.cone_section) == 0
end

@testset "vint example from http://co-at-work.zib.de/berlin2009/downloads/2009-09-22/2009-09-22-0900-CR-AW-Introduction-Porta-Polymake.pdf" begin
example_ieq = IEQ(inequalities=[
-1 0 0 0 0;0 -1 0 0 0;0 0 -1 0 0;0 0 0 -1 0;1 1 0 0 1;0 1 1 0 1;0 0 1 1 1;1 0 0 1 1;0 1 0 1 1
], upper_bounds=[1 1 1 1], lower_bounds=[0 0 0 0])

example_poi = vint(example_ieq, dir=dir)
@test example_poi.conv_section == [0 0 0 0;0 0 0 1;0 0 1 0;0 1 0 0;1 0 0 0;1 0 1 0]
end

@testset "unit cube centered at origin only has the origin as an integral point" begin
cube_ieq = IEQ(inequalities=[
0 0 2 1;0 2 0 1;2 0 0 1;-2 0 0 1;0 -2 0 1;0 0 -2 1
], upper_bounds=[1 1 1], lower_bounds=[-1 -1 -1])

cube_int_poi = vint(cube_ieq, dir=dir)

@test cube_int_poi.conv_section == [0 0 0]
end

@testset "simplex with integral vertices" begin
simplex_ieq = IEQ(
inequalities=[-1 0 0 0;0 -1 0 0;0 0 -1 0], equalities=[1 1 1 1],
upper_bounds=[1 1 1], lower_bounds=[0 0 0]
)
simplex_poi = vint(simplex_ieq, dir=dir)

@test simplex_poi.conv_section == [0 0 1;0 1 0;1 0 0]
end
end


@testset "open linear system" begin
@testset "positive octant in 3-space" begin
# bounds completely specify a valid range w/o inequalities
ieq = IEQ(
upper_bounds=[1 1 1],
lower_bounds=[0 0 0]
)
poi = vint(ieq, dir=dir)
@test poi.conv_section == [
0 0 0;0 0 1;0 1 0;0 1 1;
1 0 0;1 0 1;1 1 0;1 1 1;
]
end
end
end

end

0 comments on commit 6f72487

Please sign in to comment.