packages feed

algraph-0.7.0.0: src/Data/Graph/AdjacencyList/Network.hs

{-|
Module      : Data.Graph.AdjacencyList.Network
Description : Flow network data type for max-flow problems
Copyright   : Thodoris Papakonstantinou, 2017-2026
License     : LGPL-3
Maintainer  : dev@tpapak.com
Stability   : experimental
Portability : POSIX

Defines the 'Network' type used as input to the Tide max-flow algorithm.

A 'Network' consists of:

* A directed 'Graph'
* A distinguished 'source' and 'sink' vertex
* Edge 'Capacities' (mapping each edge to a non-negative 'Rational')
* Edge flows (initially zero, filled in by the solver)

Capacities use 'Rational' for exact arithmetic — the Tide algorithm
terminates correctly for arbitrary rational capacities.  For integer-only
workloads, see the Rust implementation @tide-maxflow@ which uses @i64@.
 -}

module Data.Graph.AdjacencyList.Network
  ( -- * Network type
    Network (..)
    -- * Type aliases
  , Capacity
  , Capacities
  , Flow
    -- * Utilities
  , uniformCapacities
  ) where

import Data.List
import Data.Maybe
import qualified Data.Map.Lazy as M
import qualified Data.IntSet as Set

import Data.Graph.AdjacencyList

-- | Edge capacity.  Uses 'Rational' for exact arithmetic, ensuring the
-- Tide algorithm terminates correctly for arbitrary capacity values.
type Capacity = Rational 

-- | Map from edges to their capacities.
type Capacities = M.Map Edge Capacity 

-- | Edge flow.  Same type as 'Capacity' since flow values are rational.
type Flow = Capacity

showCapacities :: Capacities -> String
showCapacities cps =
  show $ fmap (\c -> fromRational c :: Double) cps

-- | A flow network: a directed graph with a source, sink, edge capacities,
-- and edge flows.
--
-- Construct a 'Network' with zero initial flows and pass it to
-- 'Data.Graph.AdjacencyList.PushRelabel.Pure.pushRelabel' to compute the
-- maximum flow.
data Network = Network { graph :: !Graph
                         -- ^ The underlying directed graph.
                       , source :: Vertex
                         -- ^ Source vertex (flow originates here).
                       , sink :: Vertex
                         -- ^ Sink vertex (flow terminates here).
                       , capacities :: Capacities
                         -- ^ Edge capacities.  Every edge in 'graph' must
                         -- have a corresponding entry.
                       , flow :: Capacities
                         -- ^ Edge flows.  Set to zero initially; filled in
                         -- by the solver.
                       }
                       deriving (Eq)

instance Show Network where
  show net =
    "Network" <> show (graph net) <> "\n"
    <> " source: " <> show (source net) <> "\n"
    <> " sink  : " <> show (sink net) <> "\n"
    <> " capacities: " <> showCapacities (capacities net) <> "\n"
    <> " flows: " <> showCapacities (flow net) <> "\n"

-- | Set all edge capacities to 1 (unit capacity network).
uniformCapacities :: Graph -> Capacities
uniformCapacities g =
  M.fromList $ map (\e -> (e,1)) $ edges g