Skip to content

Commit

Permalink
Merge pull request #23 from jalving/fix_termination_status
Browse files Browse the repository at this point in the history
Store reference to aggregate optinode
  • Loading branch information
jalving authored Oct 5, 2020
2 parents 729081e + 14db730 commit b34964b
Show file tree
Hide file tree
Showing 4 changed files with 30 additions and 109 deletions.
2 changes: 1 addition & 1 deletion Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ name = "Plasmo"
uuid = "d3f7391f-f14a-50cc-bbe4-76a32d1bad3c"
repo = "https://github.com/zavalab/Plasmo.jl.git"
authors = ["Jordan Jalving <jhjalving@gmail.com>"]
version = "0.3.1"
version = "0.3.2"

[deps]
ColorTypes = "3da002f7-5984-5a60-b8a6-cbb66c0b333f"
Expand Down
4 changes: 2 additions & 2 deletions examples/simple_optigraph1.jl
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,8 @@ graph = OptiGraph()
optimizer = Ipopt.Optimizer

#Add nodes to a ModelGraph
n1 = @node(graph)
n2 = @node(graph)
n1 = @optinode(graph)
n2 = @optinode(graph)

#Node 1 Model
@variable(n1,0 <= x <= 2)
Expand Down
96 changes: 3 additions & 93 deletions src/optinode.jl
Original file line number Diff line number Diff line change
Expand Up @@ -204,7 +204,9 @@ function JuMP.set_objective(optinode::OptiNode, sense::MOI.OptimizationSense, fu
end

JuMP.termination_status(node::OptiNode) = JuMP.termination_status(getmodel(node))

JuMP.raw_status(node::OptiNode) = JuMP.raw_status(getmodel(node))
JuMP.primal_status(node::OptiNode) = JuMP.primal_status(getmodel(node))
JuMP.dual_status(node::OptiNode) = JuMP.dual_status(getmodel(node))

##############################################
# Get OptiNode
Expand Down Expand Up @@ -240,95 +242,3 @@ function string(node::OptiNode)
end
print(io::IO,node::OptiNode) = print(io, string(node))
show(io::IO,node::OptiNode) = print(io,node)





# TODO
# RECREATE LINK CONSTRAINTS IF POSSIBLE
# THROW WARNING IF THEY NEED TO BE DELETED
# Check for the same variable containers to attach link constraints to
# If it already had a model, delete all the link constraints corresponding to that model
# if hasmodel(node)
# for (graph,constraints) in getlinkconstraints(node)
# local_link_cons = constraints
# graph_links = getlinkconstraints(graph)
# filter!(c -> !(c in local_link_cons), graph_links) #filter out local link constraints
# node.link_data = NodeLinkData() #reset the local node or edge link data
# end
# end

#TODO
#set a model with the same variable names and dimensions as the old model on the node.
#This will not break link constraints by default but will make sure they match the old model
#switch out variables in any connected linkconstraints
#throw warnings if link constraints break
# function reset_model(node::ModelNode,m::JuMP.AbstractModel)
# #reassign the model
# node.model = m
# end

######################################################
# Node Constraints
######################################################
# const NodeAffExpr = Union{NodeVariableRef,JuMP.GenericAffExpr{Float64,NodeVariableRef}}
#
# struct ScalarNodeConstraint{F <: NodeAffExpr,S <: MOI.AbstractScalarSet} <: AbstractConstraint
# func::F
# set::S
# function ScalarNodeConstraint(F::NodeAffExpr,S::MOI.AbstractScalarSet)
# con = new{typeof(F),typeof(S)}(F,S)
# end
# end
#
# function JuMP.build_constraint(_error::Function,func::NodeAffExpr,set::MOI.AbstractScalarSet)
# constraint = ScalarNodeConstraint(func, set)
# return constraint
# end
#
# function JuMP.ScalarConstraint(con::ScalarNodeConstraint)
# terms = con.func.terms
# new_terms = OrderedDict([(linkvar_ref.vref,coeff) for (linkvar_ref,coeff) in terms])
# new_func = JuMP.GenericAffExpr{Float64,JuMP.VariableRef}()
# new_func.terms = new_terms
# new_func.constant = con.func.constant
# return JuMP.ScalarConstraint(new_func,con.set)
# end
#
# #Add a Node Constraint
# function JuMP.add_constraint(node::ModelNode, con::ScalarNodeConstraint, name::String="")
# scalar_con = JuMP.ScalarConstraint(con)
# cref = JuMP.add_constraint(getmodel(node),scalar_con,name) #also add to master model
# return cref
# end
#
# # Model Extras
# JuMP.show_constraints_summary(::IOContext,node::ModelNode) = ""
# JuMP.show_backend_summary(::IOContext,m::ModelNode) = ""
# Base.broadcastable(v::NodeVariableRef) = Ref(v)
# Base.copy(v::NodeVariableRef) = v
# Base.:(==)(v::NodeVariableRef, w::NodeVariableRef) = v.vref.model === w.vref.model && v.vref.index == w.vref.index
# JuMP.owner_model(v::NodeVariableRef) = v.node.model
# JuMP.isequal_canonical(v::NodeVariableRef, w::NodeVariableRef) = v.vref == w.vref
# JuMP.variable_type(::ModelNode) = NodeVariableRef
#
# JuMP.set_name(v::NodeVariableRef, s::String) = JuMP.set_name(v.vref,s)
# JuMP.name(v::NodeVariableRef) = JuMP.name(v.vref)
#
#
# #Delete a node variable
# function MOI.delete!(node::ModelNode, vref::NodeVariableRef)
# delete!(node.nodevariables, vref.idx)
# delete!(node.nodevarnames, vref.idx)
# end
# MOI.is_valid(node::ModelNode, vref::NodeVariableRef) = vref.idx in keys(node.nodevariables)

#getnode(var::NodeVariableRef) = var.node

#A node variable is a simple wrapper around a JuMP Variable Reference
# struct NodeVariableRef <: AbstractNodeVariableRef
# vref::JuMP.VariableRef
# node::ModelNode
# idx::Int64
# end
37 changes: 24 additions & 13 deletions src/solve.jl
Original file line number Diff line number Diff line change
@@ -1,38 +1,35 @@
#Convert optigraph into JuMP Model
JuMP.Model(optigraph::OptiGraph;add_node_objectives = !(has_objective(model_graph))) = getmodel(aggregate(optigraph,add_node_objectives = add_node_objectives))

function JuMP.optimize!(graph::OptiGraph,optimizer;kwargs...)
println("Converting OptiGraph to OptiNode...")
optinode,reference_map = combine(graph)
optinode,reference_map = aggregate(graph)

println("Optimizing OptiNode")
JuMP.set_optimizer(optinode,optimizer)
status = JuMP.optimize!(optinode)#,optimizer;kwargs...)
#status = JuMP.termination_status(aggregate_model)

#Hold on to aggregated optinode and reference map to access solver attributes
graph.obj_dict[:current_optinode] = optinode
graph.obj_dict[:current_ref_map] = reference_map

if JuMP.has_values(getmodel(optinode)) # TODO Get all the correct status codes for copying a solution
_copysolution!(graph,reference_map) #Now get our solution data back into the original ModelGraph
_copysolution!(graph,reference_map) #Now get our solution data back into the original OptiGraph
println("Found Solution")
end

return status
return nothing
end

function JuMP.optimize!(node::OptiNode,optimizer;kwargs...)
JuMP.set_optimizer(node,optimizer)
status = JuMP.optimize!(getmodel(node);kwargs...)
return status
JuMP.optimize!(getmodel(node);kwargs...)
return nothing
end

#TODO: Update node_variables
JuMP.optimize!(node::OptiNode;kwargs...) = JuMP.optimize!(getmodel(node);kwargs...)

# function JuMP.optimize!(graph::ModelGraph,optimizer::AbstractModelGraphOptimizer,kwargs...)
# optimizer_model = initialize_model(optimizer,graph)
# status = optimize!(optimizer_model)
# _copysolution!(optimizer_model,graph)
# return status
# end

function _copysolution!(optigraph::OptiGraph,ref_map::CombinedMap)

#Node solutions
Expand Down Expand Up @@ -68,5 +65,19 @@ function _copysolution!(optigraph::OptiGraph,ref_map::CombinedMap)
# end
# end
# end
end

has_aggregate(graph::OptiGraph) = haskey(graph.obj_dict,:current_optinode)

function getmodel(graph::OptiGraph)
if has_aggregate(graph)
return graph.obj_dict[:current_optinode]
else
error("OptiGraph has no current aggregate model")
end
end

JuMP.termination_status(graph::OptiGraph) = JuMP.termination_status(getmodel(graph))
JuMP.raw_status(graph::OptiGraph) = JuMP.raw_status(getmodel(graph))
JuMP.primal_status(graph::OptiGraph) = JuMP.primal_status(getmodel(graph))
JuMP.dual_status(graph::OptiGraph) = JuMP.dual_status(getmodel(graph))

0 comments on commit b34964b

Please sign in to comment.