Class NetworkSimplex

java.lang.Object
org.graphstream.stream.SinkAdapter
org.graphstream.algorithm.networksimplex.NetworkSimplex
All Implemented Interfaces:
Algorithm, DynamicAlgorithm, org.graphstream.stream.AttributeSink, org.graphstream.stream.ElementSink, org.graphstream.stream.Sink
Direct Known Subclasses:
DynamicOneToAllShortestPath

public class NetworkSimplex
extends org.graphstream.stream.SinkAdapter
implements DynamicAlgorithm

Minimum cost flow problem

Network simplex method is an algorithm that solves the minimum cost flow (MCF) problem for an oriented graph.

The MCF problem can be stated as follows. Each node has associated number supply representing the available supply of or demand for flow at that node. If supply is positive, the node is a supply node, if supply is negative, the node is a demand node and if supply is zero, the node is a transshipment node. Each arc has associated capacity (possibly infinite) and cost per unit flow. The MCF problem is to send the required flows from supply nodes to demand nodes at minimum cost, respecting the capacities of the arcs. Note that if the sum of supply attributes of all nodes is nonzero, the problem is infeasible.

MCF framework can be used to model a broad variety of network problems, including matching, shortest path, transportation, etc. For example, if we want to find the shortest paths from a source to all other nodes in a graph with n nodes, we can set the supply to n-1 for the source and to -1 for all other nodes, set capacity to n-1 and cost to the weight for each arc. The solution of the MCF problem with these particular settings will be minimum cost unit flow from the source to all other nodes passing by the shortest paths.

Problem data

The user of this class must store the problem data as attributes of the nodes and the edges of the graph as described below. The names of these attributes are specified in the constructor NetworkSimplex(String, String, String). For efficiency reasons all the data are supposed to be integer. If some of the attributes are real, their fractional part is ignored. To avoid loss of precision, the user must scale her data properly if they are real.

An attribute called supplyName is used to store the supply (or demand if negative) of each node. If a node has not an attribute with this name or if the value of this attribute is not numeric, the node supply is considered as zero (transshipment node).

An attribute called capacityName is used to store the capacity of each edge. If an edge has not an attribute with this name, or if the value of this attribute is negative or not numeric, the edge capacity is considered as infinite.

An attribute called costName is used to store the cost per unit flow of each edge. If an edge has not an attribute with this name or if the value of this attribute is not numeric, the cost per unit flow of the edge is considered 1.

The flow on a directed edge is always from its source node to its target node. Each undirected edge is considered as a couple of directed edges with the same capacity and cost per unit flow. In other words, there are possibly two independent flows on each undirected edge.

Solutions

TODO

Visualization

TODO
Author:
Stefan Balev
  • Field Details

    • PREFIX

      public static final String PREFIX
      The algorithm maintains some internal data whose names start with this prefix. The graph must not have any edges whose IDs start with this prefix.
      See Also:
      Constant Field Values
  • Constructor Details

    • NetworkSimplex

      public NetworkSimplex​(String supplyName, String capaciyName, String costName)
      Creates a network simplex instance specifying attribute names to be used. Use init(Graph) to assign a graph to this instance.
      Parameters:
      supplyName - Name of the attribute used to store the supply of each node.
      capaciyName - Name of the attribute used to store the capacity of each edge.
      costName - Name of the attribute used to store the cost of each edge.
  • Method Details

    • getSupplyName

      public String getSupplyName()
      Returns the name of the attribute used to store the supply of each node. This name is given as constructor parameter and cannot be modified.
      Returns:
      The name of the supply attribute.
    • getCapacityName

      public String getCapacityName()
      Returns the name of the attribute used to store the capacity of each edge. This name is given as constructor parameter and cannot be modified.
      Returns:
      The name of the capacity attribute.
    • getCostName

      public String getCostName()
      Returns the name of the attribute used to store the cost per unit flow of each edge. This name is given as constructor parameter and cannot be modified.
      Returns:
      The name of the cost attribute.
    • getPricingStrategy

      public NetworkSimplex.PricingStrategy getPricingStrategy()
      Returns the currently used pricing strategy.
      Returns:
      The pricing strategy
    • setPricingStrategy

      public void setPricingStrategy​(NetworkSimplex.PricingStrategy pricingStrategy)
      Sets the pricing strategy
      Parameters:
      pricingStrategy - The new pricing strategy
    • setAnimationDelay

      public void setAnimationDelay​(long millis)
      When the animation delay is positive, the algorithm continuously updates "ui.class" and "label" attributes of the edges and the nodes of the graph and sleeps at the beginning of each simplex pivot. This feature can be useful for visualizing the algorithm execution. The user must provide a stylesheet defining the classes of the graph elements as described in setUIClasses(). This feature is disabled by default.
      Parameters:
      millis - The time in milliseconds to sleep between two simplex pivots.
      See Also:
      setUIClasses()
    • getGraph

      public org.graphstream.graph.Graph getGraph()
      Returns the graph on which the algorithm is applied. This is the graph passed in parameter in init(Graph).
      Returns:
      The graph on which the algorithm is applied.
    • setLogFrequency

      public void setLogFrequency​(int pivots)
      Sets the log frequency. If the parameter is positive, outputs information about the algorithm execution to the log stream.
      Parameters:
      pivots - The log frequency in number of pivots
      See Also:
      setLogStream(PrintStream)
    • setLogStream

      public void setLogStream​(PrintStream log)
      Sets the log stream. Note that the algorithm outputs information about its execution only if the log frequency is positive. By default the log stream is System.err.
      Parameters:
      log - The log stream
      See Also:
      setLogFrequency(int)
    • getNetworkBalance

      public int getNetworkBalance()
      Returns the sum of the supplies of all the nodes in the network. The MCF problem has solution only if the problem is balanced, i.e. if the total supply is equal to the total demand. This method returns the missing supply (if negative) or demand (if positive) in order to make the problem balanced. If the returned value is zero, the problem is balanced.
      Returns:
      The network balance
    • getSolutionStatus

      public NetworkSimplex.SolutionStatus getSolutionStatus()
      If the current solution is up to date, returns the status of the problem. Otherwise returns NetworkSimplex.SolutionStatus.UNDEFINED.
      Returns:
      The status of the current solution.
      See Also:
      NetworkSimplex.SolutionStatus
    • getSolutionCost

      public long getSolutionCost()
      Returns the total cost of the current network flow
      Returns:
      The cost of the flow defined by the current solution
    • getSolutionInfeasibility

      public long getSolutionInfeasibility()
      Returns the infeasibility of the current solution. This is the sum of the absolute values of the infeasibilities of all the nodes. If the returned value is zero, the current solution is feasible, i.e. it satisfies the supply constraints of all the nodes.
      Returns:
      The infeasibility of the current solution.
      See Also:
      getInfeasibility(Node)
    • getInfeasibility

      public int getInfeasibility​(org.graphstream.graph.Node node)
      Returns the infeasibility of a node. Returns the amount of missing outflow (if positive) or inflow (if negative) of a given node. If the value is zero, the current solution satisfies the node demand / supply.
      Parameters:
      node - A node
      Returns:
      The infeasibility of the node
    • getEdgeFromParent

      public org.graphstream.graph.Edge getEdgeFromParent​(org.graphstream.graph.Node node)
      Returns the edge to the parent of a node in the current BFS tree. If the parent of the node is the artificial root, this method returns null. When the returned edge is undirected, use getStatus(Edge, boolean) to know which of the both arcs is basic.
      Parameters:
      node - A node
      Returns:
      The edge to the parent of the node in the BFS tree
    • getParent

      public org.graphstream.graph.Node getParent​(org.graphstream.graph.Node node)
      Returns the parent of a node in the current BFS tree. If the parent of the node is the artificial root, returns null.
      Parameters:
      node - A node
      Returns:
      The parent of a node in the BFS tree
    • getFlow

      public int getFlow​(org.graphstream.graph.Edge edge, boolean sameDirection)
      Returns the flow on an edge. If sameDirection is true, returns the flow from the source to the target of the edge, otherwise returns the flow from the target to the source of the edge. Note that for directed edges the flow can only pass from the source node to the target node. For undirected edges there may be independent flows in both directions.
      Parameters:
      edge - An edge
      sameDirection - If true, returns the flow from the source to the target.
      Returns:
      The flow on the edge.
    • getFlow

      public int getFlow​(org.graphstream.graph.Edge edge)
      Returns the flow on an edge from its source node to its target node. The same as getFlow(Edge, true).
      Parameters:
      edge - An edge
      Returns:
      The flow on the edge
      See Also:
      getFlow(Edge, boolean)
    • getStatus

      public NetworkSimplex.ArcStatus getStatus​(org.graphstream.graph.Edge edge, boolean sameDirection)
      Returns the status of an edge in the current solution. An edge can be basic, non-basic at zero or non-basic at upper bound. Note that undirected edges are interpreted as two directed arcs. If sameDirection is true, the method returns the status of the arc from the source to the target of the edge, otherwise it returns the status of the arc from the target to the source. If the edge is directed and sameDirection is false, returns null.
      Parameters:
      edge - An edge
      sameDirection - If true, returns the status of the arc from the source to the target.
      Returns:
      The status of the edge
    • getStatus

      public NetworkSimplex.ArcStatus getStatus​(org.graphstream.graph.Edge edge)
      Returns the status of an edge in the current solution. The same as getStatus(edge, true).
      Parameters:
      edge - An edge
      Returns:
      The status of the edge
      See Also:
      getStatus(Edge, boolean)
    • setUIClasses

      public void setUIClasses()
      This method can be used to visualize the current solution.

      It sets the attributes "label" and "ui.class" of the nodes and the edges of the graph depending on the current solution. The labels of the nodes are set to their balance (see getInfeasibility(Node)). The labels of the edges are set to the flow passing through them. The "ui.class" attribute of the nodes is set to one of "supply_balanced", "supply_unbalanced", "demand_balanced", "demand_unbalanced", "trans_balanced" or "trans_unbalanced" depending on the node type and the node status. The "ui.class" attribute of the edges is set to one of "basic", "nonbasic_lower" or "nonbasic_upper" according to their status (see getStatus(Edge).

      The user must provide a stylesheet defining the visual appearance for each of these node and edge classes. Note that if the animation delay is positive (see setAnimationDelay(long)), there is no need to call this method, because in this case the labels and the UI classes of the graph elements are set and updated during the algorithm execution.

      Note that in the case of undirected edges the label and the UI class are set according to the status of one of the corresponding arcs (not specified which one).

    • init

      public void init​(org.graphstream.graph.Graph graph)
      Description copied from interface: Algorithm
      Initialization of the algorithm. This method has to be called before the Algorithm.compute() method to initialize or reset the algorithm according to the new given graph.
      Specified by:
      init in interface Algorithm
      Parameters:
      graph - The graph this algorithm is using.
    • compute

      public void compute()
      Description copied from interface: Algorithm
      Run the algorithm. The Algorithm.init(Graph) method has to be called before computing.
      Specified by:
      compute in interface Algorithm
      See Also:
      Algorithm.init(Graph)
    • terminate

      public void terminate()
      Description copied from interface: DynamicAlgorithm
      Terminate the dynamic algorithm.
      Specified by:
      terminate in interface DynamicAlgorithm
      See Also:
      Algorithm.init(org.graphstream.graph.Graph)
    • edgeAttributeAdded

      public void edgeAttributeAdded​(String sourceId, long timeId, String edgeId, String attribute, Object value)
      Specified by:
      edgeAttributeAdded in interface org.graphstream.stream.AttributeSink
      Overrides:
      edgeAttributeAdded in class org.graphstream.stream.SinkAdapter
    • edgeAttributeChanged

      public void edgeAttributeChanged​(String sourceId, long timeId, String edgeId, String attribute, Object oldValue, Object newValue)
      Specified by:
      edgeAttributeChanged in interface org.graphstream.stream.AttributeSink
      Overrides:
      edgeAttributeChanged in class org.graphstream.stream.SinkAdapter
    • edgeAttributeRemoved

      public void edgeAttributeRemoved​(String sourceId, long timeId, String edgeId, String attribute)
      Specified by:
      edgeAttributeRemoved in interface org.graphstream.stream.AttributeSink
      Overrides:
      edgeAttributeRemoved in class org.graphstream.stream.SinkAdapter
    • nodeAttributeAdded

      public void nodeAttributeAdded​(String sourceId, long timeId, String nodeId, String attribute, Object value)
      Specified by:
      nodeAttributeAdded in interface org.graphstream.stream.AttributeSink
      Overrides:
      nodeAttributeAdded in class org.graphstream.stream.SinkAdapter
    • nodeAttributeChanged

      public void nodeAttributeChanged​(String sourceId, long timeId, String nodeId, String attribute, Object oldValue, Object newValue)
      Specified by:
      nodeAttributeChanged in interface org.graphstream.stream.AttributeSink
      Overrides:
      nodeAttributeChanged in class org.graphstream.stream.SinkAdapter
    • nodeAttributeRemoved

      public void nodeAttributeRemoved​(String sourceId, long timeId, String nodeId, String attribute)
      Specified by:
      nodeAttributeRemoved in interface org.graphstream.stream.AttributeSink
      Overrides:
      nodeAttributeRemoved in class org.graphstream.stream.SinkAdapter
    • edgeAdded

      public void edgeAdded​(String sourceId, long timeId, String edgeId, String fromNodeId, String toNodeId, boolean directed)
      Specified by:
      edgeAdded in interface org.graphstream.stream.ElementSink
      Overrides:
      edgeAdded in class org.graphstream.stream.SinkAdapter
    • edgeRemoved

      public void edgeRemoved​(String sourceId, long timeId, String edgeId)
      Specified by:
      edgeRemoved in interface org.graphstream.stream.ElementSink
      Overrides:
      edgeRemoved in class org.graphstream.stream.SinkAdapter
    • nodeAdded

      public void nodeAdded​(String sourceId, long timeId, String nodeId)
      Specified by:
      nodeAdded in interface org.graphstream.stream.ElementSink
      Overrides:
      nodeAdded in class org.graphstream.stream.SinkAdapter
    • nodeRemoved

      public void nodeRemoved​(String sourceId, long timeId, String nodeId)
      Specified by:
      nodeRemoved in interface org.graphstream.stream.ElementSink
      Overrides:
      nodeRemoved in class org.graphstream.stream.SinkAdapter
    • graphCleared

      public void graphCleared​(String sourceId, long timeId)
      Specified by:
      graphCleared in interface org.graphstream.stream.ElementSink
      Overrides:
      graphCleared in class org.graphstream.stream.SinkAdapter
    • printBFS

      public void printBFS​(PrintStream ps)
      Prints a table containing informations about the current basic feasible solution. Useful for testing and debugging purposes.
      Parameters:
      ps - A stream where the output goes.