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

Quadratic objectives with variables on separate nodes is not supported #84

Closed
dlcole3 opened this issue Aug 7, 2023 · 3 comments
Closed
Labels

Comments

@dlcole3
Copy link
Collaborator

dlcole3 commented Aug 7, 2023

Plasmo seems to only support quadratic objectives when the two terms of the quadratic objectives are on the same node. If a quadratic term is added to the objective function which has variables on separate nodes, the line here returns an error. The example below returns the error:

using Plasmo, JuMP, Ipopt

graph = OptiGraph()
set_optimizer(graph, Ipopt.Optimizer)

@optinode(graph, nodes[1:4])
for (i, node) in enumerate(nodes)
    @variable(node, x >= i)
    @objective(node, Min, 2 * x^2)
end

optimize!(graph)

obj_func = objective_function(graph)

new_term = UnorderedPair(nodes[1][:x], nodes[2][:x])
obj_func.terms[new_term] = 3.0

optimize!(graph)

On the modeling side, this can be avoided by placing dummy variables on each node and then adding a linking constraint between the dummy variable and the variable it represents, but it could be nice to someday support quadratic objectives on different nodes.

@dlcole3
Copy link
Collaborator Author

dlcole3 commented Aug 7, 2023

I am not sure if this is sufficient (or robust), but I currently avoid this error by changing these lines into the following code:

for (i, terms) in enumerate(quad_terms(obj))
    term1 = terms[2]
    term2 = terms[3]
    node1 = optinode(term1)
    node2 = optinode(term2)
    #@assert optinode(term1) == optinode(term2)
    moi_term1 = index(term1)
    moi_term2 = index(term2)
    node_idx_map1 = backend(node1).optimizers[graph.id].node_to_optimizer_map
    node_idx_map2 = backend(node2).optimizers[graph.id].node_to_optimizer_map
    new_moi_idx_1 = node_idx_map1[moi_term1]
    new_moi_idx_2 = node_idx_map2[moi_term2]
    moi_obj = _swap_quad_term!(moi_obj, i, new_moi_idx_1, new_moi_idx_2)
end

When I make this change, I no longer get an error. I have quadratic terms with variables from separate nodes, and the OptiGraph solves without issue.

@jalving jalving added the bug label Oct 9, 2023
@jalving
Copy link
Member

jalving commented Sep 1, 2024

This should work now in v0.6. The following example demonstrates what you should be able to do:

using Plasmo, JuMP, Ipopt

graph = OptiGraph()
set_optimizer(graph, Ipopt.Optimizer)

@optinode(graph, nodes[1:4])
for (i, node) in enumerate(nodes)
    @variable(node, x >= i)
    @objective(node, Min, 2 * x^2)
end

node_objectives = sum([objective_function(node) for node in nodes])

# set quadratic over multiple nodes
@objective(graph, Min, node_objectives + nodes[1][:x]^2*nodes[2][:x]^2)

optimize!(graph)

@jalving
Copy link
Member

jalving commented Sep 1, 2024

@dlcole3 please reopen if this persists.

@jalving jalving closed this as completed Sep 1, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants