Skip to content

Commit 8228ae5

Browse files
authored
Enabled Using Repartitioned Graphs, Added Display (#29)
* Fixed minor bug, added display ability * updated readme
1 parent 9836d58 commit 8228ae5

File tree

4 files changed

+44
-12
lines changed

4 files changed

+44
-12
lines changed

lib/PlasmoBenders/Project.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
name = "PlasmoBenders"
22
uuid = "491f1417-53b2-48aa-b9da-44cdd6c031b7"
33
authors = ["David Cole"]
4-
version = "0.1.3"
4+
version = "0.1.4"
55

66
[deps]
77
Plasmo = "d3f7391f-f14a-50cc-bbe4-76a32d1bad3c"

lib/PlasmoBenders/README.md

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,12 +18,12 @@ Pkg.add("PlasmoBenders")
1818

1919
[Benders decomposition](https://en.wikipedia.org/wiki/Benders_decomposition) (BD) is a decomposition approach that breaks problems into a master problem and a subproblem(s) and is typically applied to linear and mixed integer linear programs. BD is an iterative algorithm that can be useful for problems where there are a set of complicating variables (in the master problem) that, once fixed, make the subproblem easier to solve. An iteration of BD generally includes 1) solving the master problem, 2) passing the solution of the master problem to the subproblem, 3) solving the subproblem with the master problem solution, and 4) passing primal and dual information from the subproblem to the master problem and forming cutting planes on the master problem. PlasmoBenders applies this approach to graph-based problems where each subgraph of an OptiGraph is the master problem or a subproblem. PD is applied to the graph based on the user-defined subproblems.
2020

21-
Nested Benders Decomposition (NBD; also called [dual dynamic programming](https://www-sciencedirect-com.ezproxy.library.wisc.edu/science/article/pii/S0098135421000430)) uses similar ideas to BD but can have a sequence of subproblems (i.e., not all subproblems are connected to the original master problem, forming a nested structure). NBD can be applied to graphs with a tree structure, and NBD is likewise implemented in PlasmoBenders.
21+
Nested Benders Decomposition (NBD; also called [dual dynamic programming](https://doi.org/10.1016/j.compchemeng.2021.107265)) uses similar ideas to BD but can have a sequence of subproblems (i.e., not all subproblems are connected to the original master problem, forming a nested structure). NBD can be applied to graphs with a tree structure, and NBD is likewise implemented in PlasmoBenders.
2222

2323
> [!NOTE]
2424
> PlasmoBenders requires Plasmo v0.6.2 or later
2525
26-
PlasmoBenders is built on a `BendersOptimizer` object which requires a user-defined graph and a subgraph of that graph as the root (master problem) graph. After the information is past, the `BendersOptimizer` constructor updates the graph to apply BD or NBD. `JuMP.optimize!` is extended so that the iterative BD/NBD algorithm is applied to find a solution.
26+
PlasmoBenders is built on a `BendersAlgorithm` object which requires a user-defined graph and a subgraph of that graph as the root (master problem) graph. After the information is passed, the `BendersAlgorithm` object is instantiated and can be solved with the `run_algorithm!` function.
2727

2828

2929
### Simple Exmaple
@@ -63,16 +63,16 @@ set_to_node_objectives(g22)
6363

6464
solver = optimizer_with_attributes(HiGHS.Optimizer, "output_flag" => false)
6565

66-
BendersOpt = BendersOptimizer(g0, g1; solver = solver)
66+
BendersAlg = BendersAlgorithm(g0, g1; solver = solver)
6767

68-
optimize!(BendersOpt)
68+
run_algorithm!(BendersAlg)
6969
```
7070

71-
The `BendersOptimizer` constructor takes the overall graph, `g0` as the first object and then the root/master subgraph `g1` as the second argument.
71+
The `BendersAlgorithm` constructor takes the overall graph, `g0` as the first object and then the root/master subgraph `g1` as the second argument.
7272

7373
### Additional Functionality
7474

75-
PlasmoBenders includes additional functionality. The following keyword arguments can be passed to the `BendersOptimizer` constructor. These include the following key word arguments:
75+
PlasmoBenders includes additional functionality. The following keyword arguments can be passed to the `BendersAlgorithm` constructor. These include the following key word arguments:
7676

7777
* `max_iters` - maximum number of iterations to use
7878
* `tol` - termination tolerance between upper and lower bounds

lib/PlasmoBenders/src/initialize.jl

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -140,8 +140,12 @@ function _add_complicating_variables!(
140140
con_obj = constraint_object(link)
141141
vars = con_obj.func.terms.keys
142142

143-
next_object_link_vars = [var for var in vars if source_graph(JuMP.owner_model(var)) == next_object]
144-
last_object_link_vars = [var for var in vars if source_graph(JuMP.owner_model(var)) == last_object]
143+
# Get the variables from the constraint in the next_object
144+
next_object_nodes = all_nodes(next_object)
145+
last_object_nodes = all_nodes(last_object)
146+
147+
next_object_link_vars = [var for var in vars if JuMP.owner_model(var) in next_object_nodes]
148+
last_object_link_vars = [var for var in vars if JuMP.owner_model(var) in last_object_nodes]
145149

146150
# Get the optinodes containing the next set of variables
147151
#next_optinode = optinode(next_object_vars[1]) #NEXT: Fix this!
@@ -239,8 +243,11 @@ function _add_complicating_variables!(
239243
vars = con_obj.func.terms.keys
240244

241245
# Get the variables from the constraint in the next_object
242-
next_object_link_vars = [var for var in vars if source_graph(JuMP.owner_model(var)) == next_object]
243-
last_object_link_vars = [var for var in vars if source_graph(JuMP.owner_model(var)) == last_object]
246+
next_object_nodes = all_nodes(next_object)
247+
last_object_nodes = all_nodes(last_object)
248+
249+
next_object_link_vars = [var for var in vars if JuMP.owner_model(var) in next_object_nodes]
250+
last_object_link_vars = [var for var in vars if JuMP.owner_model(var) in last_object_nodes]
244251
next_object_copy_vars = [var_copy_map[var] for var in last_object_link_vars]
245252

246253
# Get the set of nodes in the next_object that are included in the constraint

lib/PlasmoBenders/src/utils.jl

Lines changed: 26 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,28 @@
1+
# Enable printing the optimizer
2+
function Base.string(optimizer::BendersAlgorithm)
3+
return return @sprintf(
4+
"""
5+
A BendersAlgorithm
6+
-------------------------------------------
7+
%32s %9s
8+
%32s %9s
9+
%32s %9s
10+
%32s %9s
11+
""",
12+
"Num subproblem subgraphs:",
13+
length(optimizer.solve_order),
14+
"MIP subproblems (nonroot):",
15+
optimizer.is_MIP,
16+
"Absolute Tolerance:",
17+
optimizer.tol,
18+
"Maximum Iterations:",
19+
optimizer.max_iters,
20+
)
21+
end
22+
23+
Base.print(io::IO, optimizer::BendersAlgorithm) = Base.print(io, Base.string(optimizer))
24+
Base.show(io::IO, optimizer::BendersAlgorithm) = Base.print(io, optimizer)
25+
126
function _get_hyper_projection(optimizer::BendersAlgorithm, graph::Plasmo.OptiGraph)
227
if haskey(optimizer.ext, "_projection")
328
return optimizer.ext["_projection"]
@@ -413,7 +438,7 @@ function get_upper_bounds(optimizer::BendersAlgorithm; monotonic = true)
413438
if optimizer.current_iter == 0
414439
return ubs
415440
else
416-
return [minimum(ubs[1:i] for i in 1:length(ubs))]
441+
return [minimum(ubs[1:i]) for i in 1:length(ubs)]
417442
end
418443
else
419444
return ubs

0 commit comments

Comments
 (0)