Aleph-w 3.0
A C++ Library for Data Structures and Algorithms
Loading...
Searching...
No Matches
Aleph::Network_Simplex< Net > Class Template Reference

Network Simplex algorithm for minimum cost flow. More...

#include <tpl_netcost.H>

Collaboration diagram for Aleph::Network_Simplex< Net >:
[legend]

Public Types

using Node = typename Net::Node
 
using Arc = typename Net::Arc
 
using Flow_Type = typename Net::Flow_Type
 
using Node_Info = Simplex_Node_Info< Flow_Type >
 
using Arc_Info = Simplex_Arc_Info< Flow_Type >
 

Public Member Functions

 Network_Simplex (Net &network)
 Construct Network Simplex solver.
 
void set_lower_bound (Arc *a, Flow_Type lower_bound)
 Set lower bound for an arc.
 
Flow_Type get_lower_bound (Arc *a) const
 Get lower bound for an arc.
 
bool is_at_lower_bound (Arc *a) const
 Check if arc flow is at lower bound.
 
bool is_at_upper_bound (Arc *a) const
 Check if arc flow is at upper bound (capacity).
 
Flow_Type residual_capacity (Arc *a) const
 Get residual capacity (room to increase flow).
 
Flow_Type residual_lower (Arc *a) const
 Get residual lower (room to decrease flow).
 
size_t run (Flow_Type unused=0)
 Execute Network Simplex algorithm.
 
size_t get_num_pivots () const
 Return number of pivots performed in last run.
 
const NetworkSimplexStats & get_stats () const noexcept
 Return execution statistics from last run.
 
void print_stats () const
 Print execution statistics to stdout.
 
size_t force_partial_arcs_into_tree ()
 Phase I: Force all partial-flow arcs into the spanning tree.
 
bool is_valid_basic_solution () const
 Check if current solution is a valid basic feasible solution.
 
size_t count_non_tree_partial_arcs () const
 Count arcs with partial flow not in tree.
 
bool verify_tree_reduced_costs () const
 Verify that tree arcs have zero reduced cost.
 
bool verify_tree_integrity () const
 Verify tree integrity - all parent_arcs should be Tree arcs.
 
void print_diagnostics () const
 Print diagnostic information about current state.
 

Private Member Functions

Node_Info & ninfo (Node *p)
 Get node info reference.
 
const Node_Info & ninfo (Node *p) const
 Get node info const reference.
 
Arc_Info & ainfo (Arc *a)
 Get arc info reference.
 
const Arc_Info & ainfo (Arc *a) const
 Get arc info const reference.
 
Node * parent (Node *p) const
 Get parent node.
 
Arc * parent_arc (Node *p) const
 Get parent arc.
 
long depth (Node *p) const
 Get depth.
 
Flow_Type potential (Node *p) const
 Get potential.
 
bool is_zero (Flow_Type x) const
 Check if value is effectively zero.
 
Flow_Type reduced_cost (Arc *a) const
 Compute reduced cost of an arc.
 
void init_structures ()
 Initialize data structures.
 
bool is_partial_flow (Arc *a) const
 Check if arc has partial flow (strictly between bounds).
 
void build_spanning_tree ()
 Build initial spanning tree from source.
 
Arc * find_entering_arc ()
 Find entering arc using most negative reduced cost.
 
Node * find_lca (Node *u, Node *v)
 Find the lowest common ancestor of two nodes.
 
bool augment_and_find_leaving (Arc *entering, Flow_Type &delta, Arc *&leaving, bool &leaving_goes_lower)
 Augment flow around the cycle and find leaving arc.
 
void pivot_tree (Arc *entering, Arc *leaving, bool leaving_goes_lower)
 Update tree structure after pivot.
 

Static Private Member Functions

static Flow_Type eps ()
 Epsilon for floating-point comparisons.
 

Private Attributes

Net & net
 
DynArray< Node_Info > node_info
 
DynArray< Arc_Info > arc_info
 
DynMapTree< Node *, size_t > node_to_idx
 
DynMapTree< Arc *, size_t > arc_to_idx
 
Node * root = nullptr
 
size_t num_pivots = 0
 
long lca_mark = 0
 
NetworkSimplexStats stats
 
bool support_lower_bounds = false
 

Static Private Attributes

static constexpr Flow_Type Inf = std::numeric_limits<Flow_Type>::max()
 

Detailed Description

template<FlowNetwork Net>
class Aleph::Network_Simplex< Net >

Network Simplex algorithm for minimum cost flow.

This class implements the Network Simplex algorithm, a specialized version of the Simplex method for minimum cost network flow problems. It maintains a spanning tree of basic arcs and iteratively improves the solution through pivoting operations.

Algorithm Overview

The algorithm uses a two-phase approach:

Phase I: Establish Basic Feasible Solution

After Ford-Fulkerson, some arcs may have partial flow (0 < flow < cap). For a valid basic solution, these arcs MUST be in the spanning tree (non-basic arcs must be at their bounds). Phase I forces all partial-flow arcs into the tree through pivots.

Phase II: Cost Optimization

Standard Network Simplex that iteratively:

  1. Finds an entering arc with negative reduced cost
  2. Identifies the cycle created by adding this arc
  3. Determines the leaving arc (blocking arc in the cycle)
  4. Performs the pivot: updates flows and tree structure

Implementation Notes

This implementation follows the presentation in Sedgewick's "Algorithms" with some adaptations for the Aleph-w graph representation and the addition of Phase I to handle the basic feasibility requirement.

The algorithm assumes the network already has a feasible flow (typically from a max-flow algorithm like Ford-Fulkerson). It then optimizes the cost while maintaining the same flow value.

Template Parameters
NetNetwork type (must be Net_Cost_Graph or compatible).
See also
max_flow_min_cost_by_network_simplex
max_flow_min_cost_by_cycle_canceling

Definition at line 1042 of file tpl_netcost.H.

Member Typedef Documentation

◆ Arc

template<FlowNetwork Net>
using Aleph::Network_Simplex< Net >::Arc = typename Net::Arc

Definition at line 1046 of file tpl_netcost.H.

◆ Arc_Info

Definition at line 1049 of file tpl_netcost.H.

◆ Flow_Type

Definition at line 1047 of file tpl_netcost.H.

◆ Node

template<FlowNetwork Net>
using Aleph::Network_Simplex< Net >::Node = typename Net::Node

Definition at line 1045 of file tpl_netcost.H.

◆ Node_Info

Definition at line 1048 of file tpl_netcost.H.

Constructor & Destructor Documentation

◆ Network_Simplex()

template<FlowNetwork Net>
Aleph::Network_Simplex< Net >::Network_Simplex ( Net &  network)
inlineexplicit

Construct Network Simplex solver.

Parameters
[in,out]networkThe network to optimize.

Definition at line 1767 of file tpl_netcost.H.

Member Function Documentation

◆ ainfo() [1/2]

◆ ainfo() [2/2]

template<FlowNetwork Net>
const Arc_Info & Aleph::Network_Simplex< Net >::ainfo ( Arc *  a) const
inlineprivate

◆ augment_and_find_leaving()

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::augment_and_find_leaving ( Arc *  entering,
Flow_Type &  delta,
Arc *&  leaving,
bool &  leaving_goes_lower 
)
inlineprivate

Augment flow around the cycle and find leaving arc.

When entering arc is added, it creates a cycle. This function:

  1. Finds the bottleneck (minimum slack) in the cycle
  2. Updates flows around the cycle
  3. Identifies the leaving arc

For a valid cycle that allows flow redistribution, we need arcs going in both directions (considering the entering arc). If all arcs in the cycle go in the same "global" direction (e.g., all from source towards sink), then we cannot redistribute flow without changing the total flow value.

Parameters
[in]enteringThe entering arc.
[out]deltaFlow change amount.
[out]leavingThe leaving arc (becomes non-basic).
[out]leaving_goes_lowerTrue if leaving arc goes to lower bound.
Returns
true if a valid augmentation was performed.

Definition at line 1396 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::and, Aleph::Simplex_Node_Info< Ftype >::arc_from_parent, Aleph::blossom_maximum_cardinality_matching(), Aleph::Network_Simplex< Net >::find_lca(), Aleph::Lower, Aleph::Network_Simplex< Net >::ninfo(), Aleph::Network_Simplex< Net >::parent(), Aleph::Network_Simplex< Net >::parent_arc(), and Aleph::Simplex_Arc_Info< Ftype >::state.

Referenced by Aleph::Network_Simplex< Net >::force_partial_arcs_into_tree(), and Aleph::Network_Simplex< Net >::run().

◆ build_spanning_tree()

◆ count_non_tree_partial_arcs()

template<FlowNetwork Net>
size_t Aleph::Network_Simplex< Net >::count_non_tree_partial_arcs ( ) const
inline

◆ depth()

template<FlowNetwork Net>
long Aleph::Network_Simplex< Net >::depth ( Node *  p) const
inlineprivate

◆ eps()

◆ find_entering_arc()

template<FlowNetwork Net>
Arc * Aleph::Network_Simplex< Net >::find_entering_arc ( )
inlineprivate

Find entering arc using most negative reduced cost.

Scans all non-tree arcs and selects the one with the largest violation of the optimality conditions:

  • Arc at Lower bound (flow=0): should have reduced_cost >= 0
  • Arc at Upper bound (flow=cap): should have reduced_cost <= 0

This implementation checks BOTH directions for each arc:

  • Forward direction: increase flow (requires flow < cap, benefits if rc < 0)
  • Backward direction: decrease flow (requires flow > 0, benefits if rc > 0)

This is essential for finding all negative cycles, including those that require reversing flow through arcs with flow > 0.

Returns
Entering arc, or nullptr if optimal.

Definition at line 1300 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::and, Aleph::blossom_maximum_cardinality_matching(), Aleph::Network_Simplex< Net >::eps(), Aleph::Lower, Aleph::Network_Simplex< Net >::net, Aleph::Network_Simplex< Net >::reduced_cost(), Aleph::Simplex_Arc_Info< Ftype >::state, Aleph::Tree, and Aleph::Upper.

Referenced by Aleph::Network_Simplex< Net >::run().

◆ find_lca()

template<FlowNetwork Net>
Node * Aleph::Network_Simplex< Net >::find_lca ( Node *  u,
Node *  v 
)
inlineprivate

Find the lowest common ancestor of two nodes.

Uses marking to efficiently find the LCA in O(d) where d is depth.

Parameters
[in]uFirst node.
[in]vSecond node.
Returns
LCA of u and v.

Definition at line 1357 of file tpl_netcost.H.

References Aleph::and, Aleph::Network_Simplex< Net >::lca_mark, Aleph::Simplex_Node_Info< Ftype >::mark, Aleph::Network_Simplex< Net >::ninfo(), and Aleph::Network_Simplex< Net >::parent().

Referenced by Aleph::Network_Simplex< Net >::augment_and_find_leaving().

◆ force_partial_arcs_into_tree()

template<FlowNetwork Net>
size_t Aleph::Network_Simplex< Net >::force_partial_arcs_into_tree ( )
inline

Phase I: Force all partial-flow arcs into the spanning tree.

For a valid basic feasible solution in Network Simplex, all arcs with flow strictly between bounds (0 < flow < cap) MUST be in the spanning tree. Non-basic arcs must be at their bounds.

This method identifies arcs with partial flow that are not in the tree and forces pivots to include them. Each pivot replaces one tree arc with the entering arc, maintaining exactly N-1 tree arcs.

Returns
Number of forced pivots performed.

Definition at line 1962 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::and, Aleph::Network_Simplex< Net >::augment_and_find_leaving(), Aleph::blossom_maximum_cardinality_matching(), Aleph::Network_Simplex< Net >::eps(), Aleph::Network_Simplex< Net >::is_partial_flow(), Aleph::Lower, Aleph::Network_Simplex< Net >::net, Aleph::Network_Simplex< Net >::pivot_tree(), Aleph::Simplex_Arc_Info< Ftype >::state, Aleph::Tree, and Aleph::Upper.

Referenced by Aleph::Network_Simplex< Net >::run().

◆ get_lower_bound()

template<FlowNetwork Net>
Flow_Type Aleph::Network_Simplex< Net >::get_lower_bound ( Arc *  a) const
inline

Get lower bound for an arc.

Parameters
[in]aArc to query.
Returns
Lower bound value (0 if not set).

Definition at line 1790 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), and Aleph::Simplex_Arc_Info< Ftype >::lower_bound.

◆ get_num_pivots()

template<FlowNetwork Net>
size_t Aleph::Network_Simplex< Net >::get_num_pivots ( ) const
inline

Return number of pivots performed in last run.

Definition at line 1928 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::num_pivots.

◆ get_stats()

template<FlowNetwork Net>
const NetworkSimplexStats & Aleph::Network_Simplex< Net >::get_stats ( ) const
inlinenoexcept

Return execution statistics from last run.

Definition at line 1931 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::stats.

◆ init_structures()

◆ is_at_lower_bound()

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::is_at_lower_bound ( Arc *  a) const
inline

Check if arc flow is at lower bound.

Parameters
[in]aArc to check.
Returns
true if flow equals lower bound.

Definition at line 1800 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::Network_Simplex< Net >::eps(), and Aleph::lower_bound().

◆ is_at_upper_bound()

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::is_at_upper_bound ( Arc *  a) const
inline

Check if arc flow is at upper bound (capacity).

Parameters
[in]aArc to check.
Returns
true if flow equals capacity.

Definition at line 1810 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::eps().

◆ is_partial_flow()

◆ is_valid_basic_solution()

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::is_valid_basic_solution ( ) const
inline

Check if current solution is a valid basic feasible solution.

A valid BFS requires:

  1. All tree arcs can have any flow
  2. All non-tree arcs must be at their bounds (flow=0 or flow=cap)
Returns
true if valid BFS, false otherwise.

Definition at line 2044 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::Network_Simplex< Net >::is_partial_flow(), Aleph::Network_Simplex< Net >::net, and Aleph::Tree.

◆ is_zero()

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::is_zero ( Flow_Type  x) const
inlineprivate

Check if value is effectively zero.

Definition at line 1099 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::eps().

◆ ninfo() [1/2]

◆ ninfo() [2/2]

template<FlowNetwork Net>
const Node_Info & Aleph::Network_Simplex< Net >::ninfo ( Node *  p) const
inlineprivate

◆ parent()

◆ parent_arc()

◆ pivot_tree()

template<FlowNetwork Net>
void Aleph::Network_Simplex< Net >::pivot_tree ( Arc *  entering,
Arc *  leaving,
bool  leaving_goes_lower 
)
inlineprivate

◆ potential()

template<FlowNetwork Net>
Flow_Type Aleph::Network_Simplex< Net >::potential ( Node *  p) const
inlineprivate

◆ print_diagnostics()

◆ print_stats()

◆ reduced_cost()

template<FlowNetwork Net>
Flow_Type Aleph::Network_Simplex< Net >::reduced_cost ( Arc *  a) const
inlineprivate

Compute reduced cost of an arc.

Reduced cost = c_ij - pi_i + pi_j For optimality: reduced cost >= 0 for arcs at lower bound (flow = 0) reduced cost <= 0 for arcs at upper bound (flow = cap)

Definition at line 1111 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ninfo(), and Aleph::Simplex_Node_Info< Ftype >::potential.

Referenced by Aleph::Network_Simplex< Net >::build_spanning_tree(), Aleph::Network_Simplex< Net >::find_entering_arc(), Aleph::Network_Simplex< Net >::print_diagnostics(), and Aleph::Network_Simplex< Net >::verify_tree_reduced_costs().

◆ residual_capacity()

template<FlowNetwork Net>
Flow_Type Aleph::Network_Simplex< Net >::residual_capacity ( Arc *  a) const
inline

Get residual capacity (room to increase flow).

Parameters
[in]aArc to query.
Returns
Available capacity above current flow.

Definition at line 1820 of file tpl_netcost.H.

◆ residual_lower()

template<FlowNetwork Net>
Flow_Type Aleph::Network_Simplex< Net >::residual_lower ( Arc *  a) const
inline

Get residual lower (room to decrease flow).

Parameters
[in]aArc to query.
Returns
Available decrease to lower bound.

Definition at line 1830 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), and Aleph::Simplex_Arc_Info< Ftype >::lower_bound.

◆ run()

template<FlowNetwork Net>
size_t Aleph::Network_Simplex< Net >::run ( Flow_Type  unused = 0)
inline

Execute Network Simplex algorithm.

Computes minimum cost flow. If the network already has a feasible flow (e.g., from Ford-Fulkerson), it optimizes starting from there.

Parameters
[in]unusedKept for API compatibility.
Returns
Number of pivots performed.

Definition at line 1845 of file tpl_netcost.H.

References ah_domain_error_if, Aleph::Network_Simplex< Net >::ainfo(), Aleph::and, Aleph::Network_Simplex< Net >::augment_and_find_leaving(), Aleph::blossom_maximum_cardinality_matching(), Aleph::Network_Simplex< Net >::build_spanning_tree(), Aleph::Network_Simplex< Net >::count_non_tree_partial_arcs(), Aleph::NetworkSimplexStats::degenerate_pivots, Aleph::Network_Simplex< Net >::eps(), GraphCommon< GT, Node, Arc >::esize(), Aleph::Network_Simplex< Net >::find_entering_arc(), Aleph::Network_Simplex< Net >::force_partial_arcs_into_tree(), Aleph::NetworkSimplexStats::forced_into_tree, Aleph::Network_Simplex< Net >::init_structures(), Aleph::NetworkSimplexStats::initial_partial_arcs, Aleph::Net_Graph< NodeT, ArcT >::is_single_sink(), Aleph::Net_Graph< NodeT, ArcT >::is_single_source(), Aleph::Network_Simplex< Net >::net, Aleph::Network_Simplex< Net >::num_pivots, Aleph::NetworkSimplexStats::phase1_pivots, Aleph::NetworkSimplexStats::phase1_time_ms, Aleph::NetworkSimplexStats::phase2_pivots, Aleph::NetworkSimplexStats::phase2_time_ms, Aleph::Network_Simplex< Net >::pivot_tree(), Aleph::NetworkSimplexStats::reset(), Aleph::Simplex_Arc_Info< Ftype >::skip, Aleph::Simplex_Arc_Info< Ftype >::state, Aleph::Network_Simplex< Net >::stats, Aleph::NetworkSimplexStats::total_pivots, Aleph::NetworkSimplexStats::total_time_ms, Aleph::Tree, Aleph::NetworkSimplexStats::tree_arcs, and GraphCommon< GT, Node, Arc >::vsize().

◆ set_lower_bound()

template<FlowNetwork Net>
void Aleph::Network_Simplex< Net >::set_lower_bound ( Arc *  a,
Flow_Type  lower_bound 
)
inline

Set lower bound for an arc.

Sets the minimum flow that must pass through an arc. Default lower bound is 0.

Parameters
[in]aArc to set lower bound for.
[in]lower_boundMinimum flow value.
Note
Must be called before run().

Definition at line 1779 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::lower_bound(), Aleph::Simplex_Arc_Info< Ftype >::lower_bound, and Aleph::Network_Simplex< Net >::support_lower_bounds.

◆ verify_tree_integrity()

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::verify_tree_integrity ( ) const
inline

Verify tree integrity - all parent_arcs should be Tree arcs.

Returns
true if tree structure is consistent.

Definition at line 2098 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::blossom_maximum_cardinality_matching(), Aleph::Network_Simplex< Net >::net, Aleph::Network_Simplex< Net >::parent_arc(), Aleph::Network_Simplex< Net >::root, and Aleph::Tree.

◆ verify_tree_reduced_costs()

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::verify_tree_reduced_costs ( ) const
inline

Verify that tree arcs have zero reduced cost.

In a valid basic solution, all tree arcs must have reduced cost = 0. This is a consistency check for the potential values.

Returns
true if all tree arcs have rc=0, false otherwise.

Definition at line 2079 of file tpl_netcost.H.

References Aleph::Network_Simplex< Net >::ainfo(), Aleph::blossom_maximum_cardinality_matching(), Aleph::Network_Simplex< Net >::eps(), Aleph::Network_Simplex< Net >::net, Aleph::Network_Simplex< Net >::reduced_cost(), and Aleph::Tree.

Referenced by Aleph::Network_Simplex< Net >::print_diagnostics().

Member Data Documentation

◆ arc_info

◆ arc_to_idx

◆ Inf

template<FlowNetwork Net>
constexpr Flow_Type Aleph::Network_Simplex< Net >::Inf = std::numeric_limits<Flow_Type>::max()
staticconstexprprivate

Definition at line 1063 of file tpl_netcost.H.

◆ lca_mark

template<FlowNetwork Net>
long Aleph::Network_Simplex< Net >::lca_mark = 0
private

Definition at line 1059 of file tpl_netcost.H.

Referenced by Aleph::Network_Simplex< Net >::find_lca().

◆ net

◆ node_info

◆ node_to_idx

template<FlowNetwork Net>
DynMapTree<Node *, size_t> Aleph::Network_Simplex< Net >::node_to_idx
private

◆ num_pivots

template<FlowNetwork Net>
size_t Aleph::Network_Simplex< Net >::num_pivots = 0
private

◆ root

template<FlowNetwork Net>
Node* Aleph::Network_Simplex< Net >::root = nullptr
private

◆ stats

◆ support_lower_bounds

template<FlowNetwork Net>
bool Aleph::Network_Simplex< Net >::support_lower_bounds = false
private

Definition at line 1061 of file tpl_netcost.H.

Referenced by Aleph::Network_Simplex< Net >::set_lower_bound().


The documentation for this class was generated from the following file: