Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

rm support of anonymous variables & constraints #565

Merged
merged 1 commit into from
Jul 21, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 44 additions & 1 deletion src/decomposition.jl
Original file line number Diff line number Diff line change
Expand Up @@ -492,18 +492,61 @@ function buildformulations!(
return
end

# Error messages for `check_annotations`.
_err_check_annotations(id::VarId) = error("""
A variable (id = $id) is not annotated.
Make sure you do not use anonymous variables (variable with no name declared in JuMP macro variable).
Otherwise, open an issue at https://github.com/atoptima/Coluna.jl/issues
""")

_err_check_annotations(id::ConstrId) = error("""
A constraint (id = $id) is not annotated.
Make sure you do not use anonymous constraints (constraint with no name declared in JuMP macro variable).
Otherwise, open an issue at https://github.com/atoptima/Coluna.jl/issues
""")

"""
Make sure that all variables and constraints of the original formulation are
annotated. Otherwise, it returns an error.
"""
function check_annotations(prob::Problem, annotations::Annotations)
origform = get_original_formulation(prob)

for (varid, _) in getvars(origform)
if !haskey(annotations.ann_per_var, varid)
return _err_check_annotations(varid)
end
end

for (constrid, _) in getconstrs(origform)
if !haskey(annotations.ann_per_constr, constrid)
return _err_check_annotations(constrid)
end
end
return true
end

"""
Reformulate the original formulation of prob according to the annotations.
The environment maintains formulation ids.
"""
function reformulate!(prob::Problem, annotations::Annotations, env::Env)
# Once the original formulation built, we close the "fill mode" of the
# coefficient matrix which is a super fast writing mode compared to the default
# writing mode of the dynamic sparse matrix.
if getcoefmatrix(prob.original_formulation).fillmode
closefillmode!(getcoefmatrix(prob.original_formulation))
end

decomposition_tree = annotations.tree
if decomposition_tree !== nothing
check_annotations(prob, annotations)
root = BD.getroot(decomposition_tree)
reform = Reformulation()
set_reformulation!(prob, reform)
buildformulations!(prob, reform, env, annotations, reform, root)
relax_integrality!(getmaster(reform))
else
else # No decomposition provided by BlockDecomposition
push_optimizer!(
prob.original_formulation,
prob.default_optimizer_builder
Expand Down
47 changes: 47 additions & 0 deletions test/issues_tests.jl
Original file line number Diff line number Diff line change
Expand Up @@ -306,6 +306,49 @@ function continuous_vars_in_sp()
return
end

# issue https://github.com/atoptima/Coluna.jl/issues/553
function unsupported_anonym_constrs_vars()
coluna = JuMP.optimizer_with_attributes(
Coluna.Optimizer,
"params" => CL.Params(solver=ClA.TreeSearchAlgorithm()),
"default_optimizer" => GLPK.Optimizer
)

function anonymous_var_model!(m)
y = @variable(m, binary = true)
@variable(m, 0 <= x[D] <= 1)
@constraint(m, sp[d in D], x[d] <= 0.85)
@objective(m, Min, sum(x) + y)
@dantzig_wolfe_decomposition(m, dec, D)
end

function anonymous_constr_model!(m)
@variable(m, 0 <= x[D] <= 1)
sp = @constraint(m, [d in D], x[d] <= 0.85)
@objective(m, Min, sum(x))
@dantzig_wolfe_decomposition(m, dec, D)
end

@axis(D, 1:5)
m = BlockModel(coluna, direct_model=true)
anonymous_var_model!(m)
@test_throws ErrorException optimize!(m)

m = BlockModel(coluna)
anonymous_var_model!(m)
# The variable is annotated in the master.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I didn't understand why this happens.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Neither do I

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Haha ok. I tried to find a reason but couldn't yet, I can keep searching if it's relevant.

# @test_throws ErrorException optimize!(m)

m = BlockModel(coluna, direct_model=true)
anonymous_constr_model!(m)
@test_throws ErrorException optimize!(m)

m = BlockModel(coluna)
anonymous_constr_model!(m)
@test_throws ErrorException optimize!(m)
return
end

function test_issues_fixed()
@testset "no_decomposition" begin
solve_with_no_decomposition()
Expand Down Expand Up @@ -338,6 +381,10 @@ function test_issues_fixed()
@testset "continuous_vars_in_sp" begin
continuous_vars_in_sp()
end

@testset "unsupported_anonym_constrs_vars" begin
unsupported_anonym_constrs_vars()
end
end

test_issues_fixed()