Skip to content

Add tree-decomposition-based partitioning.#149

Open
samuelsonric wants to merge 1 commit intoplasmo-dev:mainfrom
samuelsonric:main
Open

Add tree-decomposition-based partitioning.#149
samuelsonric wants to merge 1 commit intoplasmo-dev:mainfrom
samuelsonric:main

Conversation

@samuelsonric
Copy link

@samuelsonric samuelsonric commented Mar 5, 2026

This PR adds adds a partitioning feature using CliqueTrees.jl. The fuction apply_clique_tree! transforms an opti-graph into a forest of disjoint subgraphs, which can be used by PlasmoBenders.jl.

Example

using Plasmo, PlasmoBenders, HiGHS, JuMP                                                                                                   

# Petersen graph
function build_graph()                      
      graph = OptiGraph()

      @optinode(graph, n[0:9])                                                                                                                                     
      @variable(n[0], 0 <= cap <= 10, Int)
      @variable(n[0], 0 <= x)       
      @constraint(n[0], x <= 5cap)  
      @objective(n[0], Min, 30cap + 2x)         
     
      for i in 1:9        
          @variable(n[i], 0 <= x)                     
          @variable(n[i], 0 <= slack)        
          @constraint(n[i], x + slack >= 5 + i)                    
          @objective(n[i], Min, 3x + 100slack) 
      end      
    
      for (i, j) in [(0,1), (1,2), (2,3), (3,4), (4,0)]       
          @linkconstraint(graph, n[i][:x] + n[j][:x] >= 8)                         
      end           
     
      for (i, j) in [(5,7), (7,9), (9,6), (6,8), (8,5)]                
          @linkconstraint(graph, n[i][:x] + n[j][:x] >= 7)
      end  

      for (i, j) in [(0,5), (1,6), (2,7), (3,8), (4,9)]                 
          @linkconstraint(graph, n[i][:x] + n[j][:x] >= 6)     
      end 
       
      set_to_node_objectives(graph)   
      return graph
end

function solve_base(solver, graph)
    set_optimizer(graph, solver)
    optimize!(graph)
    return objective_value(graph)
end

function solve_benders(solver, graph; kw...)
    root = apply_clique_tree!(graph; kw...)

    for subgraph in local_subgraphs(graph)              
      set_optimizer(subgraph, solver)
    end

    benders = BendersAlgorithm(graph, root; max_iters=50, solver=solver)                                                                 
    run_algorithm!(benders)
    return benders.best_upper_bound
end
            
solver = optimizer_with_attributes(HiGHS.Optimizer, "output_flag" => false)

We can solve this naively...

julia> solve_base(solver, build_graph())
275.999999

... or using nested Benders.

julia> solve_benders(solver, build_graph())
Initializing BendersAlgorithm...
BendersAlgorithm Initialized!
################################################
Running BendersAlgorithm
################################################

Number of Variables: 72
Number of Subproblems: 5

Iter |      Gap | LowerBound | UpperBound | Time (s)
   1 |    70.7 % | 8.100e+01 | 2.760e+02 | 1.099e-02
   2 |      37 % | 1.740e+02 | 2.760e+02 | 9.408e-03
   3 |       0 % | 2.760e+02 | 2.760e+02 | 9.465e-03
Optimal Solution Found!
275.999999

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant