Skip to content

Commit

Permalink
Fix breaking changes in CBLS, JuMP and MOI
Browse files Browse the repository at this point in the history
  • Loading branch information
Azzaare committed Jul 22, 2024
1 parent f1a9e8f commit 321c4b4
Show file tree
Hide file tree
Showing 8 changed files with 62 additions and 152 deletions.
4 changes: 2 additions & 2 deletions src/ConstraintModels.jl
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@ export qap
export magic_square
export mincut
export n_queens
export scheduling
# export scheduling
export sudoku

include("assignment.jl")
Expand All @@ -25,7 +25,7 @@ include("cut.jl")
include("golomb.jl")
include("magic_square.jl")
include("n_queens.jl")
include("scheduling.jl")
# include("scheduling.jl")
include("sudoku.jl")

end
12 changes: 4 additions & 8 deletions src/cut.jl
Original file line number Diff line number Diff line change
Expand Up @@ -10,16 +10,12 @@ function mincut(graph, source, sink, interdiction, ::Val{:raw})
foreach(_ -> variable!(m, d), 0:n)

# Extract error function from usual_constraint
e1 = (x; param=nothing, dom_size=n + 1) -> error_f(
usual_constraints[:ordered])(x; param, dom_size
)
e2 = (x; param=nothing, dom_size=n + 1) -> error_f(
usual_constraints[:all_different])(x; param, dom_size
)
e1 = (x; kargs...) -> error_f(USUAL_CONSTRAINTS[:ordered])(x; kargs...)
e2 = (x; kargs...) -> error_f(USUAL_CONSTRAINTS[:all_different])(x; kargs...)

# Add constraint
constraint!(m, e1, [source, separator, sink])
constraint!(m, e2, 1:(n + 1))
constraint!(m, e2, 1:(n+1))

# Add objective
objective!(m, (x...) -> o_mincut(graph, x...; interdiction))
Expand Down Expand Up @@ -56,6 +52,6 @@ Compute the minimum cut of a graph.
- `interdiction`: indicates the number of forbidden links
- `modeler`: Default to `:JuMP`.
"""
function mincut(graph; source, sink, interdiction =0, modeler = :JuMP)
function mincut(graph; source, sink, interdiction=0, modeler=:JuMP)
return mincut(graph, source, sink, interdiction, Val(modeler))
end
20 changes: 7 additions & 13 deletions src/golomb.jl
Original file line number Diff line number Diff line change
Expand Up @@ -6,20 +6,14 @@ function golomb(n, L, ::Val{:raw})
foreach(_ -> variable!(m, d), 1:n)

# Extract error function from usual_constraint
e1 = (x; param=nothing, dom_size=n) -> error_f(
usual_constraints[:all_different])(x; param, dom_size
)
e2 = (x; param=nothing, dom_size=n) -> error_f(
usual_constraints[:all_equal_param])(x; param, dom_size
)
e3 = (x; param=nothing, dom_size=n) -> error_f(
usual_constraints[:dist_different])(x; param, dom_size
)
e1 = (x; kargs...) -> error_f(USUAL_CONSTRAINTS[:all_different])(x; kargs...)
e2 = (x; kargs...) -> error_f(USUAL_CONSTRAINTS[:all_equal])(x; kargs...)
e3 = (x; kargs...) -> error_f(USUAL_CONSTRAINTS[:dist_different])(x; kargs...)

# # Add constraints
constraint!(m, e1, 1:n)
constraint!(m, x -> e2(x; param=0), 1:1)
for i in 1:(n - 1), j in (i + 1):n, k in i:(n - 1), l in (k + 1):n
constraint!(m, e2, 1:1)
for i in 1:(n-1), j in (i+1):n, k in i:(n-1), l in (k+1):n
(i, j) < (k, l) || continue
constraint!(m, e3, [i, j, k, l])
end
Expand All @@ -39,7 +33,7 @@ function golomb(n, L, ::Val{:JuMP})
@constraint(m, X in Ordered()) # for output convenience, keep them ordered

# No two pairs have the same length
for i in 1:(n - 1), j in (i + 1):n, k in i:(n - 1), l in (k + 1):n
for i in 1:(n-1), j in (i+1):n, k in i:(n-1), l in (k+1):n
(i, j) < (k, l) || continue
@constraint(m, [X[i], X[j], X[k], X[l]] in DistDifferent())
end
Expand All @@ -55,4 +49,4 @@ end
Model the Golomb problem of `n` marks on the ruler `0:L`. The `modeler` argument accepts :raw, and :JuMP (default), which refer respectively to the solver internal model, the MathOptInterface model, and the JuMP model.
"""
golomb(n, L=n^2; modeler = :JuMP) = golomb(n, L, Val(modeler))
golomb(n, L=n^2; modeler=:JuMP) = golomb(n, L, Val(modeler))
18 changes: 5 additions & 13 deletions src/magic_square.jl
Original file line number Diff line number Diff line change
Expand Up @@ -7,11 +7,11 @@ function magic_square(n, ::Val{:JuMP})
@constraint(model, vec(X) in AllDifferent())

for i in 1:n
@constraint(model, X[i,:] in SumEqualParam(magic_constant))
@constraint(model, X[:,i] in SumEqualParam(magic_constant))
@constraint(model, X[i, :] in AllEqual(; val=magic_constant))
@constraint(model, X[:, i] in AllEqual(; val=magic_constant))
end
@constraint(model, [X[i,i] for i in 1:n] in SumEqualParam(magic_constant))
@constraint(model, [X[i,n + 1 - i] for i in 1:n] in SumEqualParam(magic_constant))
@constraint(model, [X[i, i] for i in 1:n] in AllEqual(; val=magic_constant))
@constraint(model, [X[i, n+1-i] for i in 1:n] in AllEqual(; val=magic_constant))

return model, X
end
Expand All @@ -21,12 +21,4 @@ end
Create a model for the magic square problem of order `n`. The `modeler` argument accepts :JuMP (default), which refer to the solver the JuMP model.
"""
magic_square(n; modeler = :JuMP) = magic_square(n, Val(modeler))








magic_square(n; modeler=:JuMP) = magic_square(n, Val(modeler))
2 changes: 1 addition & 1 deletion src/scheduling.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
function scheduling(processing_times, due_dates, ::Val{:raw})
m = model(; kind = :scheduling)
m = model(; kind=:scheduling)
n = length(processing_times) # number of jobs
max_time = sum(processing_times)

Expand Down
52 changes: 25 additions & 27 deletions src/sudoku.jl
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ function sudoku(n, start, ::Val{:raw})
N = n^2
d = domain(1:N)

m = model(;kind=:sudoku)
m = model(; kind=:sudoku)

# Add variables
if isnothing(start)
Expand All @@ -12,19 +12,17 @@ function sudoku(n, start, ::Val{:raw})
end


e = (x; param=nothing, dom_size=N) -> error_f(
usual_constraints[:all_different])(x; param=param, dom_size=dom_size
)
e = (x; kargs...) -> error_f(USUAL_CONSTRAINTS[:all_different])(x; kargs...)

# Add constraints: line, columns; blocks
foreach(i -> constraint!(m, e, (i * N + 1):((i + 1) * N)), 0:(N - 1))
foreach(i -> constraint!(m, e, [j * N + i for j in 0:(N - 1)]), 1:N)
foreach(i -> constraint!(m, e, (i*N+1):((i+1)*N)), 0:(N-1))
foreach(i -> constraint!(m, e, [j * N + i for j in 0:(N-1)]), 1:N)

for i in 0:(n - 1)
for j in 0:(n - 1)
for i in 0:(n-1)
for j in 0:(n-1)
vars = Vector{Int}()
for k in 1:n
for l in 0:(n - 1)
for l in 0:(n-1)
push!(vars, (j * n + l) * N + i * n + k)
end
end
Expand All @@ -45,16 +43,16 @@ function sudoku(n, start, ::Val{:MOI})
foreach(i -> MOI.add_constraint(m, VI(i), DiscreteSet(1:N)), 1:N^2)

# Add constraints: line, columns; blocks
foreach(i -> MOI.add_constraint(m, VOV(map(VI, (i * N + 1):((i + 1) * N))),
MOIAllDifferent(N)), 0:(N - 1))
foreach(i -> MOI.add_constraint(m, VOV(map(VI, [j * N + i for j in 0:(N - 1)])),
foreach(i -> MOI.add_constraint(m, VOV(map(VI, (i*N+1):((i+1)*N))),
MOIAllDifferent(N)), 0:(N-1))
foreach(i -> MOI.add_constraint(m, VOV(map(VI, [j * N + i for j in 0:(N-1)])),
MOIAllDifferent(N)), 1:N)

for i in 0:(n - 1)
for j in 0:(n - 1)
for i in 0:(n-1)
for j in 0:(n-1)
vars = Vector{Int}()
for k in 1:n
for l in 0:(n - 1)
for l in 0:(n-1)
push!(vars, (j * n + l) * N + i * n + k)
end
end
Expand All @@ -72,16 +70,16 @@ function sudoku(n, start, ::Val{:JuMP})
@variable(m, 1 X[1:N, 1:N] N, Int)
if !isnothing(start)
for i in 1:N, j in 1:N
v_ij = start[i,j]
v_ij = start[i, j]
if 1 v_ij N
@constraint(m, X[i,j] == v_ij)
@constraint(m, X[i, j] == v_ij)
end
end
end

for i in 1:N
@constraint(m, X[i,:] in AllDifferent()) # rows
@constraint(m, X[:,i] in AllDifferent()) # columns
@constraint(m, X[i, :] in AllDifferent()) # rows
@constraint(m, X[:, i] in AllDifferent()) # columns
end
for i in 0:(n-1), j in 0:(n-1)
@constraint(m, vec(X[(i*n+1):(n*(i+1)), (j*n+1):(n*(j+1))]) in AllDifferent()) # blocks
Expand Down Expand Up @@ -119,7 +117,7 @@ solution = value.(grid)
display(solution, Val(:sudoku))
```
"""
sudoku(n; start=nothing, modeler = :JuMP) = sudoku(n, start, Val(modeler))
sudoku(n; start=nothing, modeler=:JuMP) = sudoku(n, start, Val(modeler))

@doc raw"""
```julia
Expand All @@ -138,10 +136,10 @@ SudokuInstance(P::Pair{Tuple{Int, Int}, T}...) # again, default to 9×9 sudoku,
```
Constructor functions for the `SudokuInstance` `struct`.
"""
mutable struct SudokuInstance{T <: Integer} <: AbstractMatrix{T}
A::AbstractMatrix{T} where {T <: Integer}
mutable struct SudokuInstance{T<:Integer} <: AbstractMatrix{T}
A::AbstractMatrix{T} where {T<:Integer}

function SudokuInstance(A::AbstractMatrix{T}) where {T <: Integer}
function SudokuInstance(A::AbstractMatrix{T}) where {T<:Integer}
size(A, 1) == size(A, 2) || throw(error("Sodokus must be square; received matrix of size $(size(A, 1))×$(size(A, 2))."))
isequal(sqrt(size(A, 1)), isqrt(size(A, 1))) || throw(error("SudokuInstances must be able to split into equal boxes (e.g., a 9×9 SudokuInstance has three 3×3 squares). Size given is $(size(A, 1))×$(size(A, 2))."))
new{T}(A)
Expand Down Expand Up @@ -172,8 +170,8 @@ Construct a `SudokuInstance` with the values `X` of a solver as input.
function SudokuInstance(X::Dictionary)
n = isqrt(length(X))
A = zeros(Int, n, n)
for (k,v) in enumerate(Base.Iterators.partition(X, n))
A[k,:] = v
for (k, v) in enumerate(Base.Iterators.partition(X, n))
A[k, :] = v
end
return SudokuInstance(A)
end
Expand Down Expand Up @@ -238,7 +236,7 @@ function _format_line_segment(r, col_pos, M)
line = string()
for k in axes(r, 1)
n_spaces = 1
Δ = maximum((ndigits(i) for i in M[:, (col_pos * sep_length) + k])) - ndigits(r[k])
Δ = maximum((ndigits(i) for i in M[:, (col_pos*sep_length)+k])) - ndigits(r[k])
if Δ 0
n_spaces = Δ + 1
end
Expand All @@ -259,7 +257,7 @@ function _format_line(r, M)
line = _rules[:column]
for i in 1:sep_length
abs_sep_pos = sep_length * i
line *= _format_line_segment(r[(abs_sep_pos - sep_length + 1):abs_sep_pos], i - 1, M)
line *= _format_line_segment(r[(abs_sep_pos-sep_length+1):abs_sep_pos], i - 1, M)
end

return line
Expand Down
35 changes: 16 additions & 19 deletions test/JuMP.jl
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@

@constraint(m, X in AllDifferent())
@constraint(m, X in AllEqual())
@constraint(m, X in AllEqualParam(2))
@constraint(m, X in AlwaysTrue())
@constraint(m, X[1:4] in DistDifferent())
@constraint(m, X[1:2] in Eq())
@constraint(m, X in Ordered())
end

Expand Down Expand Up @@ -64,15 +61,15 @@ end
@variable(model, x in DiscreteSet(0:20))
@variable(model, y in DiscreteSet(0:20))

@constraint(model, [x,y] in Predicate(v -> 6v[1] + 8v[2] >= 100 ))
@constraint(model, [x,y] in Predicate(v -> 7v[1] + 12v[2] >= 120 ))
@constraint(model, [x, y] in Predicate(v -> 6v[1] + 8v[2] >= 100))
@constraint(model, [x, y] in Predicate(v -> 7v[1] + 12v[2] >= 120))

objFunc = v -> 12v[1] + 20v[2]
@objective(model, Min, ScalarFunction(objFunc))

optimize!(model)
@info solution_summary(model)
@info "JuMP: basic opt" value(x) value(y) (12*value(x)+20*value(y))
@info "JuMP: basic opt" value(x) value(y) (12 * value(x) + 20 * value(y))
end

@testset "JuMP: Chemical equilibrium" begin
Expand All @@ -84,22 +81,22 @@ end
@info "JuMP: $compounds_names$mixture_name" value.(X)
end

@testset "JuMP: Scheduling" begin
model, completion_times, start_times = scheduling(processing_times, due_times)
optimize!(model)
@info solution_summary(model)
@info "JuMP: scheduling" value.(start_times) value.(completion_times) processing_times due_times
@info (value.(start_times)+processing_times == value.(completion_times))
end
# @testset "JuMP: Scheduling" begin
# model, completion_times, start_times = scheduling(processing_times, due_times)
# optimize!(model)
# @info solution_summary(model)
# @info "JuMP: scheduling" value.(start_times) value.(completion_times) processing_times due_times
# @info (value.(start_times)+processing_times == value.(completion_times))
# end

@testset "JuMP: Minimum Cut" begin
graph = zeros(5, 5)
graph[1,2] = 1.0
graph[1,3] = 2.0
graph[1,4] = 3.0
graph[2,5] = 1.0
graph[3,5] = 2.0
graph[4,5] = 3.0
graph[1, 2] = 1.0
graph[1, 3] = 2.0
graph[1, 4] = 3.0
graph[2, 5] = 1.0
graph[3, 5] = 2.0
graph[4, 5] = 3.0

model, links = mincut(graph; source=1, sink=5, interdiction=1)
optimize!(model)
Expand Down
Loading

0 comments on commit 321c4b4

Please sign in to comment.