Skip to content

Commit e5cc1cd

Browse files
authored
Update MOI interface (#27)
1 parent a6fd3e7 commit e5cc1cd

5 files changed

Lines changed: 69 additions & 18 deletions

File tree

.github/workflows/Test.yml

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,12 +13,23 @@ permissions:
1313

1414
jobs:
1515
test:
16+
name: Julia ${{ matrix.version }} - ${{ matrix.suite_name }}
1617
runs-on: ubuntu-latest
1718
strategy:
1819
matrix:
1920
version:
2021
- 'lts'
2122
- '1'
23+
moi_suite:
24+
- '0'
25+
- '1'
26+
include:
27+
- moi_suite: '0'
28+
suite_name: 'unit'
29+
- moi_suite: '1'
30+
suite_name: 'MOI'
31+
env:
32+
COOLPDLP_TEST_MOISUITE: ${{ matrix.moi_suite }}
2233
steps:
2334
- uses: actions/checkout@v6
2435
- uses: julia-actions/setup-julia@v2

README.md

Lines changed: 13 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,19 @@ pkg> add https://github.com/JuliaDecisionFocusedLearning/CoolPDLP.jl
2525
```
2626

2727
There are two ways to call the solver: either directly or via its [`JuMP.jl`](https://github.com/jump-dev/JuMP.jl) interface.
28-
See the tutorial for details.
28+
29+
## Use with JuMP
30+
31+
To use `CoolPDLP` with JuMP, select `CoolPDLP.Optimizer` and customize the options:
32+
33+
```julia
34+
using CoolPDLP, JuMP
35+
36+
model = Model(CoolPDLP.Optimizer)
37+
# Set `matrix_type` and `backend` to use GPU:
38+
set_attribute(model, "matrix_type", CUSPARSE.CuSparseMatrixCSR)
39+
set_attribute(model, "backend", CUDABackend())
40+
```
2941

3042
## Why a new package?
3143

src/CoolPDLP.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ include("public.jl")
4848
include("algorithms/pdlp.jl")
4949
end
5050

51-
include("moi.jl")
51+
include("MOI_wrapper.jl")
5252

5353
export GPUSparseMatrixCOO, GPUSparseMatrixCSR, GPUSparseMatrixELL
5454

src/moi.jl renamed to src/MOI_wrapper.jl

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -165,10 +165,33 @@ const OptimizerCache{T} = MOI.Utilities.GenericModel{
165165
},
166166
}
167167

168+
MOI.default_cache(::Optimizer{T}, ::Type{T}) where {T} = MOI.Utilities.UniversalFallback(OptimizerCache{T}())
169+
168170
function MOI.optimize!(dest::Optimizer{T}, src::MOI.ModelLike) where {T}
169-
MOI.empty!(dest)
170-
cache = OptimizerCache{T}()
171+
cache = MOI.default_cache(dest, T)
171172
index_map = MOI.copy_to(cache, src)
173+
MOI.optimize!(dest, cache)
174+
return index_map, false
175+
end
176+
177+
function _pass_attributes(dest::Optimizer{T}, cache::MOI.Utilities.UniversalFallback{OptimizerCache{T}}, index_map) where {T}
178+
MOI.Utilities.pass_attributes(dest, cache, index_map, MOI.get(cache, MOI.ListOfVariableIndices()))
179+
180+
attrs = MOI.Utilities.ModelFilter(a -> !(a isa MOI.ObjectiveSense || a isa MOI.ObjectiveFunction), cache)
181+
MOI.Utilities.pass_attributes(dest, attrs, index_map)
182+
183+
for (F, S) in MOI.get(cache, MOI.ListOfConstraintTypesPresent())
184+
idxs = MOI.get(cache, MOI.ListOfConstraintIndices{F, S}())
185+
MOI.Utilities.pass_attributes(dest, cache, index_map, idxs)
186+
end
187+
188+
return cache.model
189+
end
190+
191+
function MOI.optimize!(dest::Optimizer{T}, fcache::MOI.Utilities.UniversalFallback{OptimizerCache{T}}) where {T}
192+
MOI.empty!(dest)
193+
index_map = MOI.Utilities.identity_index_map(fcache)
194+
cache = _pass_attributes(dest, fcache, index_map)
172195

173196
n = cache.constraints.coefficients.n
174197
max_sense = cache.objective.sense == MOI.MAX_SENSE

test/runtests.jl

Lines changed: 19 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,28 @@
11
using Test
22

33
@testset verbose = true "CoolPDLP" begin
4-
@testset "Formalities" begin
5-
include("formalities.jl")
6-
end
7-
@testset "Tutorial" begin
8-
include("tutorial.jl")
9-
end
10-
for folder in readdir(@__DIR__)
11-
isdir(joinpath(@__DIR__, folder)) || continue
12-
@testset verbose = true "$folder" begin
13-
for file in readdir(joinpath(@__DIR__, folder))
14-
@testset "$file" begin
15-
include(joinpath(@__DIR__, folder, file))
4+
moisuite = get(ENV, "COOLPDLP_TEST_MOISUITE", nothing)
5+
if moisuite != "1"
6+
@testset "Formalities" begin
7+
include("formalities.jl")
8+
end
9+
@testset "Tutorial" begin
10+
include("tutorial.jl")
11+
end
12+
for folder in readdir(@__DIR__)
13+
isdir(joinpath(@__DIR__, folder)) || continue
14+
@testset verbose = true "$folder" begin
15+
for file in readdir(joinpath(@__DIR__, folder))
16+
@testset "$file" begin
17+
include(joinpath(@__DIR__, folder, file))
18+
end
1619
end
1720
end
1821
end
1922
end
20-
@testset "MOI Wrapper" begin
21-
include("moi.jl")
23+
if moisuite != "0"
24+
@testset "MOI Wrapper" begin
25+
include("moi.jl")
26+
end
2227
end
2328
end

0 commit comments

Comments
 (0)