Skip to content

Commit cbe8289

Browse files
blegatAzzaare
andauthored
Update to MOI v1 (#2)
* Update to MOI v1 * Update JavaCall to 0.8. Doesn't fix the test errors * Bump * Fix * Fixes * set environment variables * Fix * Fix * Fix * Fix * Fix * Fix * Fix * Don't set copy_stack on windows --------- Co-authored-by: Azzaare <jf@baffier.fr>
1 parent 7954bcc commit cbe8289

File tree

8 files changed

+161
-66
lines changed

8 files changed

+161
-66
lines changed

.github/workflows/GitHubCI.yml

Lines changed: 4 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,9 @@ jobs:
1515
test:
1616
name: Julia ${{ matrix.version }} - ${{ matrix.os }} - ${{ matrix.arch }} - ${{ github.event_name }}
1717
runs-on: ${{ matrix.os }}
18+
env:
19+
JULIA_NUM_THREADS: '1'
20+
JULIA_COPY_STACKS: ${{ matrix.os == 'windows-latest' && '0' || '1' }}
1821
strategy:
1922
fail-fast: false
2023
matrix:
@@ -45,16 +48,7 @@ jobs:
4548
with:
4649
version: ${{ matrix.version }}
4750
arch: ${{ matrix.arch }}
48-
- uses: actions/cache@v4
49-
env:
50-
cache-name: cache-artifacts
51-
with:
52-
path: ~/.julia/artifacts
53-
key: ${{ runner.os }}-test-${{ env.cache-name }}-${{ hashFiles('**/Project.toml') }}
54-
restore-keys: |
55-
${{ runner.os }}-test-${{ env.cache-name }}-
56-
${{ runner.os }}-test-
57-
${{ runner.os }}-
51+
- uses: julia-actions/cache@v2
5852
- uses: julia-actions/julia-buildpkg@v1
5953
- uses: julia-actions/julia-runtest@v1
6054
- uses: julia-actions/julia-processcoverage@v1

Project.toml

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "JaCoP"
22
uuid = "02462d8f-a5b3-44fd-8fd4-3169fe7a24c5"
33
authors = ["Thibaut Cuvelier <cuvelier.thibaut@gmail.com>"]
4-
repo = "https://github.com/dourouc05/JaCoP.jl"
4+
repo = "https://github.com/JuliaConstraints/JaCoP.jl"
55
version = "0.1.0"
66

77
[deps]
@@ -12,7 +12,7 @@ Downloads = "f43a241f-c20a-4ad4-852c-f6b1247861c6"
1212
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
1313

1414
[compat]
15-
julia = "^1.6"
16-
MathOptInterface = "^0.10"
17-
ConstraintProgrammingExtensions = "^0.6.2, ^0.7"
18-
JavaCall = "^0.7.4"
15+
julia = "1.10"
16+
MathOptInterface = "1"
17+
ConstraintProgrammingExtensions = "0.8"
18+
JavaCall = "0.8"

src/MOI/parse.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@ function _parse_to_vars(
22
model::Optimizer,
33
f::MOI.VectorOfVariables,
44
)
5-
return [_info(model, v) for v in f.variables]
5+
return [_info(model, v).variable for v in f.variables]
66
end
77

88
function _parse_to_coeffs_vars(
@@ -19,6 +19,6 @@ function _parse_to_coeffs_vars(
1919
terms::Vector{MOI.ScalarAffineTerm{T}},
2020
) where {T <: Integer}
2121
coeffs = Int32[t.coefficient for t in terms]
22-
vars = Variable[_info(model, t.variable) for t in terms]
22+
vars = Variable[_info(model, t.variable).variable for t in terms]
2323
return coeffs, vars
2424
end

src/MOI/wrapper.jl

Lines changed: 58 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -36,15 +36,15 @@ end
3636
mutable struct ConstraintInfo
3737
# Only necessary information to access an existing constraint, delete it when needed.
3838
index::MOI.ConstraintIndex
39-
constraint::Union{Constraint, Nothing}
39+
constraint::Union{JavaObject, Nothing}
4040
f::Union{MOI.AbstractScalarFunction, MOI.AbstractVectorFunction}
4141
set::MOI.AbstractSet
4242
name::String
4343
end
4444

4545
function ConstraintInfo(
4646
index::MOI.ConstraintIndex,
47-
constraint::Union{Constraint, Nothing},
47+
constraint::Union{JavaObject, Nothing},
4848
f::Union{MOI.AbstractScalarFunction, MOI.AbstractVectorFunction},
4949
set::MOI.AbstractSet,
5050
)
@@ -73,8 +73,9 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
7373
# objective_function_cp::Union{Nothing, NumExpr}
7474
# objective_cp::Union{Nothing, IloObjective}
7575

76-
# # Cache parts of a solution.
77-
# cached_solution_state::Union{Nothing, Bool}
76+
# Cached solution state.
77+
termination_status::MOI.TerminationStatusCode
78+
primal_status::MOI.ResultStatusCode
7879

7980
# # Mappings from variable and constraint names to their indices. These are
8081
# # lazily built on-demand, so most of the time, they are `nothing`.
@@ -97,12 +98,14 @@ mutable struct Optimizer <: MOI.AbstractOptimizer
9798
CleverDicts.CleverDict{MOI.VariableIndex, VariableInfo}()
9899
model.constraint_info = Dict{MOI.ConstraintIndex, ConstraintInfo}()
99100

101+
model.termination_status = MOI.OPTIMIZE_NOT_CALLED
102+
model.primal_status = MOI.NO_SOLUTION
103+
100104
# model.objective_sense = MOI.FEASIBILITY_SENSE
101105
# model.objective_function = nothing
102106
# model.objective_function_cp = nothing
103107
# model.objective_cp = nothing
104108

105-
# model.cached_solution_state = nothing
106109
# model.callback_state = CB_NONE
107110

108111
MOI.empty!(model)
@@ -117,29 +120,16 @@ function MOI.empty!(model::Optimizer)
117120
model.name = ""
118121
empty!(model.variable_info)
119122
empty!(model.constraint_info)
120-
121-
# model.objective_sense = MOI.FEASIBILITY_SENSE
122-
# model.objective_function = nothing
123-
# model.objective_function_cp = nothing
124-
# model.objective_cp = nothing
125-
126-
# model.cached_solution_state = nothing
127-
# model.name_to_variable = nothing
128-
# model.name_to_constraint = nothing
123+
model.termination_status = MOI.OPTIMIZE_NOT_CALLED
124+
model.primal_status = MOI.NO_SOLUTION
129125
return
130126
end
131127

132128
function MOI.is_empty(model::Optimizer)
133129
!isempty(model.name) && return false
134130
!isempty(model.variable_info) && return false
135131
!isempty(model.constraint_info) && return false
136-
# model.objective_sense != MOI.FEASIBILITY_SENSE && return false
137-
# model.objective_function !== nothing && return false
138-
# model.objective_function_cp !== nothing && return false
139-
# model.objective_cp !== nothing && return false
140-
# model.name_to_variable !== nothing && return false
141-
# model.name_to_constraint !== nothing && return false
142-
# model.cached_solution_state !== nothing && return false
132+
model.termination_status != MOI.OPTIMIZE_NOT_CALLED && return false
143133
return true
144134
end
145135

@@ -226,3 +216,50 @@ end
226216
function MOI.get(::Optimizer, ::MOI.ListOfConstraintAttributesSet)
227217
return MOI.AbstractConstraintAttribute[MOI.ConstraintName()]
228218
end
219+
220+
function MOI.optimize!(model::Optimizer)
221+
int_vars = IntVar[
222+
info.variable for info in values(model.variable_info)
223+
if info.variable isa IntVar
224+
]
225+
if isempty(int_vars)
226+
model.termination_status = MOI.OPTIMAL
227+
model.primal_status = MOI.FEASIBLE_POINT
228+
return
229+
end
230+
search = DepthFirstSearch(())
231+
indomain = IndomainMin(())
232+
select = InputOrderSelect(
233+
(Store, Vector{Var}, Indomain),
234+
model.inner, int_vars, indomain,
235+
)
236+
result = jcall(
237+
search, "labeling", jboolean, (Store, SelectChoicePoint),
238+
model.inner, select,
239+
)
240+
if result != 0
241+
model.termination_status = MOI.OPTIMAL
242+
model.primal_status = MOI.FEASIBLE_POINT
243+
else
244+
model.termination_status = MOI.INFEASIBLE
245+
model.primal_status = MOI.NO_SOLUTION
246+
end
247+
return
248+
end
249+
250+
function MOI.get(model::Optimizer, ::MOI.TerminationStatus)
251+
return model.termination_status
252+
end
253+
254+
function MOI.get(model::Optimizer, ::MOI.PrimalStatus)
255+
return model.primal_status
256+
end
257+
258+
function MOI.get(model::Optimizer, ::MOI.ResultCount)
259+
return model.primal_status == MOI.FEASIBLE_POINT ? 1 : 0
260+
end
261+
262+
function MOI.get(model::Optimizer, ::MOI.VariablePrimal, vi::MOI.VariableIndex)
263+
v = _info(model, vi).variable
264+
return Int(jcall(v, "value", jint, ()))
265+
end

src/MOI/wrapper_constraints_cp.jl

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
11
# Good source of mappings from MiniZinc:
22
# https://github.com/radsz/jacop/blob/develop/src/main/java/org/jacop/fz/constraints/GlobalConstraints.java
33

4-
# CP.AllDifferent
4+
# MOI.AllDifferent
55
function MOI.supports_constraint(
66
::Optimizer,
77
::Type{F},
88
::Type{S},
99
) where {
1010
F <: MOI.VectorOfVariables,
11-
S <: CP.AllDifferent,
11+
S <: MOI.AllDifferent,
1212
}
1313
return true
1414
end
1515

1616
function _build_constraint(
1717
model::Optimizer,
1818
f::MOI.VectorOfVariables,
19-
::CP.AllDifferent,
19+
::MOI.AllDifferent,
2020
)
2121
# This could also be Alldiff or Alldistinct, with various algorithms
2222
# for filtering behind. TODO: add a parameter to choose?
2323
# http://jacopguide.osolpro.com/guideJaCoP.pdf#subsection.3.3.1
2424
# fzn-jacop uses Alldiff:
2525
# https://github.com/radsz/jacop/blob/develop/src/main/java/org/jacop/fz/constraints/GlobalConstraints.java#L279
26-
return Alldifferent(_parse_to_vars(model, f))
26+
return Alldifferent((Vector{IntVar},), _parse_to_vars(model, f))
2727
end
2828

2929
# CP.Domain

src/MOI/wrapper_constraints_mo.jl

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,10 @@ function _build_constraint(
66
s::MOI.GreaterThan{T},
77
) where {T <: Real}
88
coeffs, vars, constant = _parse_to_coeffs_vars(model, f)
9-
return LinearInt(model.inner, coeffs, vars, ">=", s.constant - constant)
9+
return LinearInt(
10+
(Store, Vector{jint}, Vector{IntVar}, JString, jint),
11+
model.inner, coeffs, vars, ">=", Int32(s.constant - constant),
12+
)
1013
end
1114

1215
function _build_constraint(
@@ -15,7 +18,10 @@ function _build_constraint(
1518
s::MOI.LessThan{T},
1619
) where {T <: Real}
1720
coeffs, vars, constant = _parse_to_coeffs_vars(model, f)
18-
return LinearInt(model.inner, coeffs, vars, "<=", s.constant - constant)
21+
return LinearInt(
22+
(Store, Vector{jint}, Vector{IntVar}, JString, jint),
23+
model.inner, coeffs, vars, "<=", Int32(s.constant - constant),
24+
)
1925
end
2026

2127
function _build_constraint(
@@ -24,7 +30,10 @@ function _build_constraint(
2430
s::MOI.EqualTo{T},
2531
) where {T <: Real}
2632
coeffs, vars, constant = _parse_to_coeffs_vars(model, f)
27-
return LinearInt(model.inner, coeffs, vars, "==", s.constant - constant)
33+
return LinearInt(
34+
(Store, Vector{jint}, Vector{IntVar}, JString, jint),
35+
model.inner, coeffs, vars, "==", Int32(s.constant - constant),
36+
)
2837
end
2938

3039
# No vector of constraints, there is no more efficient way to do it.

src/MOI/wrapper_constraints_singlevar.jl

Lines changed: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,13 +40,64 @@ function MOI.is_valid(
4040
_info(model, index).lb == _info(model, index).ub
4141
end
4242

43-
function _build_constraint(
43+
function MOI.add_constraint(
4444
model::Optimizer,
4545
f::MOI.VariableIndex,
4646
s::MOI.EqualTo{T},
4747
) where {T <: Integer}
4848
v = _info(model, f).variable
49-
return XeqC(v, s.value)
49+
constr = XeqC((IntVar, jint), v, Int32(s.value))
50+
jacop_add_constraint_to_store(model.inner, constr)
51+
_info(model, f).lb = s.value
52+
_info(model, f).ub = s.value
53+
index = MOI.ConstraintIndex{MOI.VariableIndex, MOI.EqualTo{T}}(f.value)
54+
model.constraint_info[index] = ConstraintInfo(index, constr, f, s)
55+
return index
56+
end
57+
58+
function MOI.add_constraint(
59+
model::Optimizer,
60+
f::MOI.VariableIndex,
61+
s::MOI.LessThan{T},
62+
) where {T <: Integer}
63+
v = _info(model, f).variable
64+
constr = XlteqC((IntVar, jint), v, Int32(s.upper))
65+
jacop_add_constraint_to_store(model.inner, constr)
66+
_info(model, f).ub = s.upper
67+
index = MOI.ConstraintIndex{MOI.VariableIndex, MOI.LessThan{T}}(f.value)
68+
model.constraint_info[index] = ConstraintInfo(index, constr, f, s)
69+
return index
70+
end
71+
72+
function MOI.add_constraint(
73+
model::Optimizer,
74+
f::MOI.VariableIndex,
75+
s::MOI.GreaterThan{T},
76+
) where {T <: Integer}
77+
v = _info(model, f).variable
78+
constr = XgteqC((IntVar, jint), v, Int32(s.lower))
79+
jacop_add_constraint_to_store(model.inner, constr)
80+
_info(model, f).lb = s.lower
81+
index = MOI.ConstraintIndex{MOI.VariableIndex, MOI.GreaterThan{T}}(f.value)
82+
model.constraint_info[index] = ConstraintInfo(index, constr, f, s)
83+
return index
84+
end
85+
86+
function MOI.add_constraint(
87+
model::Optimizer,
88+
f::MOI.VariableIndex,
89+
s::MOI.Interval{T},
90+
) where {T <: Integer}
91+
v = _info(model, f).variable
92+
lb_constr = XgteqC((IntVar, jint), v, Int32(s.lower))
93+
ub_constr = XlteqC((IntVar, jint), v, Int32(s.upper))
94+
jacop_add_constraint_to_store(model.inner, lb_constr)
95+
jacop_add_constraint_to_store(model.inner, ub_constr)
96+
_info(model, f).lb = s.lower
97+
_info(model, f).ub = s.upper
98+
index = MOI.ConstraintIndex{MOI.VariableIndex, MOI.Interval{T}}(f.value)
99+
model.constraint_info[index] = ConstraintInfo(index, nothing, f, s)
100+
return index
50101
end
51102

52103
function MOI.is_valid(

src/java_wrapper.jl

Lines changed: 23 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,33 +6,37 @@
66
# These correspond to Java types (which are directly returned by the functions
77
# in this binder). In particular, the inheritance defined in Java is not brought
88
# back to Julia.
9-
const Store = JavaObject{Symbol("org.jacop.core.Store")}
9+
const Store = @jimport org.jacop.core.Store
1010

11-
const BooleanVar = JavaObject{Symbol("org.jacop.core.BooleanVar")}
12-
const IntVar = JavaObject{Symbol("org.jacop.core.IntVar")}
13-
const SetVar = JavaObject{Symbol("org.jacop.set.core.SetVar")}
14-
const FloatVar = JavaObject{Symbol("org.jacop.floats.core.FloatVar")}
15-
const CircuitVar = JavaObject{Symbol("org.jacop.constraints.CircuitVar")}
11+
const Var = @jimport org.jacop.core.Var
12+
const BooleanVar = @jimport org.jacop.core.BooleanVar
13+
const IntVar = @jimport org.jacop.core.IntVar
14+
const SetVar = @jimport org.jacop.set.core.SetVar
15+
const FloatVar = @jimport org.jacop.floats.core.FloatVar
16+
const CircuitVar = @jimport org.jacop.constraints.CircuitVar
1617

17-
const Constraint = JavaObject{Symbol("org.jacop.constraints.Constraint")}
18-
const LinearInt = JavaObject{Symbol("org.jacop.constraints.LinearInt")}
19-
const Alldifferent = JavaObject{Symbol("org.jacop.constraints.Alldifferent")}
20-
const In = JavaObject{Symbol("org.jacop.constraints.In")}
21-
const XeqC = JavaObject{Symbol("org.jacop.constraints.XeqC")}
18+
const Constraint = @jimport org.jacop.constraints.Constraint
19+
const LinearInt = @jimport org.jacop.constraints.LinearInt
20+
const Alldifferent = @jimport org.jacop.constraints.Alldifferent
21+
const In = @jimport org.jacop.constraints.In
22+
const XeqC = @jimport org.jacop.constraints.XeqC
23+
const XlteqC = @jimport org.jacop.constraints.XlteqC
24+
const XgteqC = @jimport org.jacop.constraints.XgteqC
25+
26+
# Search types.
27+
const DepthFirstSearch = @jimport org.jacop.search.DepthFirstSearch
28+
const InputOrderSelect = @jimport org.jacop.search.InputOrderSelect
29+
const IndomainMin = @jimport org.jacop.search.IndomainMin
30+
const Indomain = @jimport org.jacop.search.Indomain
31+
const SelectChoicePoint = @jimport org.jacop.search.SelectChoicePoint
2232

2333
# Unions of types to model Java type hierarchy.
2434

25-
const Variable = Union{
26-
BooleanVar,
27-
IntVar,
28-
SetVar,
29-
FloatVar,
30-
CircuitVar,
31-
}
35+
const Variable = Union{BooleanVar, IntVar, SetVar, FloatVar, CircuitVar}
3236

3337
# Add a constraint to a store.
3438

35-
function jacop_add_constraint_to_store(store::Store, constraint::Constraint)
39+
function jacop_add_constraint_to_store(store::Store, constraint)
3640
jcall(store, "impose", Nothing, (Constraint,), constraint)
3741
return
3842
end

0 commit comments

Comments
 (0)