Skip to content

Commit 3bb7577

Browse files
authored
Add test (#5)
* Add test * Add MOI wrapper * Fix * Add ci * Add test/Project.toml
1 parent 88fa391 commit 3bb7577

11 files changed

Lines changed: 211 additions & 11 deletions

File tree

.github/workflows/CompatHelper.yml

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
name: CompatHelper
2+
on:
3+
schedule:
4+
- cron: '00 00 * * *'
5+
jobs:
6+
CompatHelper:
7+
runs-on: ubuntu-latest
8+
steps:
9+
- uses: julia-actions/setup-julia@latest
10+
with:
11+
version: 1.6
12+
- name: Pkg.add("CompatHelper")
13+
run: julia -e 'using Pkg; Pkg.add("CompatHelper")'
14+
- name: CompatHelper.main()
15+
env:
16+
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
17+
run: julia -e 'using CompatHelper; CompatHelper.main()'

.github/workflows/TagBot.yml

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
name: TagBot
2+
on:
3+
issue_comment:
4+
types:
5+
- created
6+
workflow_dispatch:
7+
jobs:
8+
TagBot:
9+
if: github.event_name == 'workflow_dispatch' || github.actor == 'JuliaTagBot'
10+
runs-on: ubuntu-latest
11+
steps:
12+
- uses: JuliaRegistries/TagBot@v1
13+
with:
14+
token: ${{ secrets.GITHUB_TOKEN }}
15+
ssh: ${{ secrets.DOCUMENTER_KEY }}

.github/workflows/ci.yml

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
name: CI
2+
on:
3+
push:
4+
branches: [main]
5+
pull_request:
6+
types: [opened, synchronize, reopened]
7+
jobs:
8+
test:
9+
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
10+
runs-on: ${{ matrix.os }}
11+
strategy:
12+
fail-fast: false
13+
matrix:
14+
include:
15+
- version: '1.10'
16+
os: ubuntu-latest
17+
arch: x64
18+
- version: '1'
19+
os: ubuntu-latest
20+
arch: x64
21+
steps:
22+
- uses: actions/checkout@v4
23+
- uses: julia-actions/setup-julia@v2
24+
with:
25+
version: ${{ matrix.version }}
26+
arch: ${{ matrix.arch }}
27+
- uses: julia-actions/cache@v1
28+
- uses: julia-actions/julia-buildpkg@v1
29+
- uses: julia-actions/julia-runtest@v1
30+
with:
31+
depwarn: error
32+
- uses: julia-actions/julia-processcoverage@v1
33+
- uses: codecov/codecov-action@v4
34+
with:
35+
file: lcov.info
36+
token: ${{ secrets.CODECOV_TOKEN }}

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Manifest.toml

src/ComplementOpt.jl

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,6 @@ const MOIU = MOI.Utilities
55

66
include("vertical.jl")
77
include("nonlinear.jl")
8+
include("MOI_wrapper.jl")
89

910
end # module ComplementOpt

src/MOI_wrapper.jl

Lines changed: 65 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,65 @@
1+
struct Reformulation <: MOI.AbstractOptimizerAttribute end
2+
3+
struct Optimizer{O<:MOI.ModelLike} <: MOI.AbstractOptimizer
4+
optimizer::O
5+
reformulation
6+
function Optimizer(optimizer::MOI.ModelLike)
7+
return new{typeof(optimizer)}(
8+
optimizer,
9+
NonlinearReformulation(),
10+
)
11+
end
12+
end
13+
14+
MOI.is_empty(model::Optimizer) = MOI.is_empty(model.optimizer)
15+
MOI.empty!(model::Optimizer) = MOI.empty!(model.optimizer)
16+
17+
function MOI.supports(
18+
model::Optimizer,
19+
attr::Union{
20+
MOI.AbstractModelAttribute,
21+
MOI.AbstractOptimizerAttribute,
22+
},
23+
)
24+
return MOI.supports(model.optimizer, attr)
25+
end
26+
27+
function MOI.get(
28+
model::Optimizer,
29+
attr::Union{
30+
MOI.AbstractModelAttribute,
31+
MOI.AbstractOptimizerAttribute,
32+
},
33+
)
34+
return MOI.get(model.optimizer, attr)
35+
end
36+
37+
function MOI.set(
38+
model::Optimizer,
39+
attr::Union{
40+
MOI.AbstractModelAttribute,
41+
MOI.AbstractOptimizerAttribute,
42+
},
43+
value,
44+
)
45+
return MOI.set(model.optimizer, attr, value)
46+
end
47+
48+
function MOI.supports_constraint(
49+
model::Optimizer,
50+
::Type{F},
51+
::Type{S},
52+
) where {F<:MOI.AbstractFunction,S<:MOI.AbstractSet}
53+
return MOI.supports_constraint(model.optimizer, F, S)
54+
end
55+
56+
function MOI.copy_to(dest::Optimizer, src::MOI.ModelLike)
57+
tmp = MOI.Utilities.UniversalFallback(
58+
MOI.Utilities.Model{Float64}()
59+
)
60+
tmp_index_map = MOI.copy_to(tmp, src)
61+
reformulate_to_vertical!(tmp)
62+
reformulate_as_nonlinear_program!(tmp)
63+
# TODO combine with `tmp_index_map`
64+
return MOI.copy_to(dest.optimizer, tmp)
65+
end

src/nonlinear.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
struct NonlinearReformulation end
12

23
"""
34
reformulate_as_nonlinear_program!(model::MOI.ModelLike; relaxation=0.0)
@@ -94,4 +95,3 @@ function reformulate_as_nonlinear_program!(model::MOI.ModelLike; relaxation=0.0)
9495
MOI.delete(model, cc_cons)
9596
return ind_cc
9697
end
97-

src/vertical.jl

Lines changed: 18 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,9 @@ const VF = Union{
55
}
66

77
function has_complementarity(model::MOI.ModelLike)
8-
CC = MOI.Complements
9-
cc_vov = MOI.get(model, MOI.ListOfConstraintIndices{MOI.VectorOfVariables, CC}())
10-
cc_vf = MOI.get(model, MOI.ListOfConstraintIndices{VF, CC}())
11-
return length(cc_vov) >= 1 || length(cc_vf) >= 1
8+
return any(MOI.get(model, MOI.ListOfConstraintTypesPresent())) do (F, S)
9+
S == MOI.Complements
10+
end
1211
end
1312

1413
#=
@@ -151,8 +150,19 @@ function reformulate_to_vertical!(model::MOI.ModelLike)
151150
end
152151

153152
function is_vertical(model::MOI.ModelLike)
154-
CC = MOI.Complements
155-
cc_vov = MOI.get(model, MOI.ListOfConstraintIndices{MOI.VectorOfVariables, CC}())
156-
cc_vf = MOI.get(model, MOI.ListOfConstraintIndices{VF, CC}())
157-
return length(cc_vov) == 1 && length(cc_vf) == 0
153+
one_vov = false
154+
for (F, S) in MOI.get(model, MOI.ListOfConstraintTypesPresent())
155+
if S == MOI.Complements
156+
if F == MOI.VectorOfVariables
157+
if MOI.get(model, MOI.NumberOfConstraints{F,S}()) == 1
158+
one_vov = true
159+
else
160+
return false
161+
end
162+
else
163+
return false
164+
end
165+
end
166+
end
167+
return one_vov
158168
end

test/Project.toml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
[deps]
2+
JuMP = "4076af6c-e467-56ae-b986-b466b2749572"
3+
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"

test/instances.jl

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,8 @@ using JuMP
66
function fletcher_leyffer_ex1_model()
77
model = Model()
88
@variable(model, z[1:2])
9+
set_lower_bound(z[2], 0)
910
@objective(model, Min, (z[1] - 1)^2 + z[2]^2)
10-
@constraint(model, z[2] >= 0)
1111
@constraint(model, z[2] - z[1] >= 0)
1212
@constraint(model, [z[2] - z[1], z[2]] MOI.Complements(2))
1313
return model
@@ -374,4 +374,3 @@ function water_net_model()
374374

375375
return model
376376
end
377-

0 commit comments

Comments
 (0)