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

Support of JuMP anonymous constraints/variables #553

Closed
etiennedeg opened this issue Jul 7, 2021 · 7 comments · Fixed by #565
Closed

Support of JuMP anonymous constraints/variables #553

etiennedeg opened this issue Jul 7, 2021 · 7 comments · Fixed by #565
Assignees
Labels
bug Something isn't working discussion Further information is requested needs investigation The issue needs investigation because we don't know if it's a bug and if it comes from Coluna.

Comments

@etiennedeg
Copy link

Hi, I have some troubles with Coluna. Here is a MWE of my problem. I create two sub-problems S1 containing x[1] and S2 containing x[2], with the master x[1] + x[2] <= 1. (the sub-problems are not constrained, I put a more complex example in commented lines). The optimal solution returned is 2, whereas 1 is expected.
What am I doing wrong ?

using JuMP
using BlockDecomposition
using Coluna
using Gurobi

coluna = optimizer_with_attributes(
    Coluna.Optimizer,
    "params" => Coluna.Params(
        solver = Coluna.Algorithm.TreeSearchAlgorithm()
    ),
    "default_optimizer" => Gurobi.Optimizer
)

model = BlockModel(coluna)

@axis(S, 1:2)

@variable(model, x[i in S], Bin)
# @variable(model, y[i in S], Bin)
@constraint(model, sum(x[i] for i in S) <= 1)
# @constraint(model, [i in S], y[i] <= x[i])
@objective(model, Max, sum(x))
# @objective(model, Max, sum(y))

@dantzig_wolfe_decomposition(model, decomposition, S)

optimize!(model)
@guimarqu guimarqu added the bug Something isn't working label Jul 7, 2021
@guimarqu guimarqu self-assigned this Jul 7, 2021
@guimarqu
Copy link
Contributor

guimarqu commented Jul 7, 2021

Hi, the model looks ok, so Coluna may have a bug. I'll check as soon as possible.

@guimarqu
Copy link
Contributor

guimarqu commented Jul 9, 2021

Thanks for the report.

When a constraint is unamed, BlockDecomposition does not send the annotation of the constraint to Coluna. As a result, Coluna does not know to which subproblem the constraint belongs and ignore it.

A fix would be to assign to the master constraints or variables that are unamed. However, It seems possible to create anonymous constraints and variables that use an axis e.g. :

c = @constraint(model, [Axis], ....)

(you do that in your comment).
In this case, we'll have to forbid the use of anonymous constraints at the moment because I don't know how we can fix that.

If you name your constraint :

@constraint(model, name, sum(x[i] for i in S) <= 1)

it works.

@guimarqu guimarqu changed the title Coluna gives wrong result on a simple model Support of JuMP anonymous constraints/variables Jul 9, 2021
@guimarqu guimarqu added needs investigation The issue needs investigation because we don't know if it's a bug and if it comes from Coluna. discussion Further information is requested labels Jul 9, 2021
@guimarqu guimarqu added this to the v0.4 milestone Jul 9, 2021
@etiennedeg
Copy link
Author

Thanks, this seems to work with named constraints

@etiennedeg
Copy link
Author

It would be cool to support anonymous objects, especially for constraints, where names are not very useful. Naming constraints is easy when the constraints can be written in vectorized style, but it is harder when it gets more complicated.

I'm not fluent in JuMP, MOI or Coluna internals, but I took a look at the source code, and the pitfall seems to be in this file: the objects are gathered via model.obj_dict (object_dictionary(model) would be a safer option). This object is only used to link names with their associated objects, and was never supposed to reference the anonymous constraints.
I think we can gather everything without going down to MOI with something along these lines:

vars = all_variables(model)
for con_type in list_of_constraint_types(model)
   cons = all_constraints(model, con_type...)
end

Maybe filtering some constraint types...
I can take a look at it if you want but I am quite busy this week, and then I'm going on vacation, so this can take a bit of time.

@etiennedeg
Copy link
Author

Ah, it's harder than I thought, all_variables does not gives the containers, so we can't get the axes. I'm not sure where the containers are stored (I'm not even sure if these are stored)

@guimarqu
Copy link
Contributor

Yes you found the pitfall.

I didn't find any access to JuMP objects that contain anonymous variables or constraints from the JuMP model. I didn't try to go down to MOI because I think we loose the indices provided by the user (they are necessary to annotate & then perform the decomposition).

I think you can access these JuMP objects only from the Julia variable you declare in the scope where you define the model. If this assumption is true, we must forbid anonymous vars & constrs.

@guimarqu
Copy link
Contributor

Ah, it's harder than I thought, all_variables does not gives the containers, so we can't get the axes. I'm not sure where the containers are stored (I'm not even sure if these are stored)

I didn't know these methods.

Yes, we need JuMP containers (I called them JuMP objects in my previous message).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bug Something isn't working discussion Further information is requested needs investigation The issue needs investigation because we don't know if it's a bug and if it comes from Coluna.
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants