org.graphstream.algorithm.networksimplex
Class NetworkSimplex

java.lang.Object
  extended by org.graphstream.stream.SinkAdapter
      extended by 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

Nested Class Summary
static class NetworkSimplex.ArcStatus
          Arc status
static class NetworkSimplex.PricingStrategy
          Pricing strategy used at each iteration of the algorithm.
static class NetworkSimplex.SolutionStatus
          The status of the current solution.
 
Field Summary
static String PREFIX
          The algorithm maintains some internal data whose names start with this prefix.
 
Constructor Summary
NetworkSimplex(String supplyName, String capaciyName, String costName)
          Creates a network simplex instance specifying attribute names to be used.
 
Method Summary
 void compute()
          Run the algorithm.
 void edgeAdded(String sourceId, long timeId, String edgeId, String fromNodeId, String toNodeId, boolean directed)
           
 void edgeAttributeAdded(String sourceId, long timeId, String edgeId, String attribute, Object value)
           
 void edgeAttributeChanged(String sourceId, long timeId, String edgeId, String attribute, Object oldValue, Object newValue)
           
 void edgeAttributeRemoved(String sourceId, long timeId, String edgeId, String attribute)
           
 void edgeRemoved(String sourceId, long timeId, String edgeId)
           
 String getCapacityName()
          Returns the name of the attribute used to store the capacity of each edge.
 String getCostName()
          Returns the name of the attribute used to store the cost per unit flow of each edge.
<T extends org.graphstream.graph.Edge>
T
getEdgeFromParent(org.graphstream.graph.Node node)
          Returns the edge to the parent of a node in the current BFS tree.
 int getFlow(org.graphstream.graph.Edge edge)
          Returns the flow on an edge from its source node to its target node.
 int getFlow(org.graphstream.graph.Edge edge, boolean sameDirection)
          Returns the flow on an edge.
 org.graphstream.graph.Graph getGraph()
          Returns the graph on which the algorithm is applied.
 int getInfeasibility(org.graphstream.graph.Node node)
          Returns the infeasibility of a node.
 int getNetworkBalance()
          Returns the sum of the supplies of all the nodes in the network.
<T extends org.graphstream.graph.Node>
T
getParent(org.graphstream.graph.Node node)
          Returns the parent of a node in the current BFS tree.
 NetworkSimplex.PricingStrategy getPricingStrategy()
          Returns the currently used pricing strategy.
 long getSolutionCost()
          Returns the total cost of the current network flow
 long getSolutionInfeasibility()
          Returns the infeasibility of the current solution.
 NetworkSimplex.SolutionStatus getSolutionStatus()
          If the current solution is up to date, returns the status of the problem.
 NetworkSimplex.ArcStatus getStatus(org.graphstream.graph.Edge edge)
          Returns the status of an edge in the current solution.
 NetworkSimplex.ArcStatus getStatus(org.graphstream.graph.Edge edge, boolean sameDirection)
          Returns the status of an edge in the current solution.
 String getSupplyName()
          Returns the name of the attribute used to store the supply of each node.
 void graphCleared(String sourceId, long timeId)
           
 void init(org.graphstream.graph.Graph graph)
          Initialization of the algorithm.
 void nodeAdded(String sourceId, long timeId, String nodeId)
           
 void nodeAttributeAdded(String sourceId, long timeId, String nodeId, String attribute, Object value)
           
 void nodeAttributeChanged(String sourceId, long timeId, String nodeId, String attribute, Object oldValue, Object newValue)
           
 void nodeAttributeRemoved(String sourceId, long timeId, String nodeId, String attribute)
           
 void nodeRemoved(String sourceId, long timeId, String nodeId)
           
 void printBFS(PrintStream ps)
          Prints a table containing informations about the current basic feasible solution.
 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.
 void setLogFrequency(int pivots)
          Sets the log frequency.
 void setLogStream(PrintStream log)
          Sets the log stream.
 void setPricingStrategy(NetworkSimplex.PricingStrategy pricingStrategy)
          Sets the pricing strategy
 void setUIClasses()
          This method can be used to visualize the current solution.
 void terminate()
          Terminate the dynamic algorithm.
 
Methods inherited from class org.graphstream.stream.SinkAdapter
graphAttributeAdded, graphAttributeChanged, graphAttributeRemoved, stepBegins
 
Methods inherited from class java.lang.Object
equals, getClass, hashCode, notify, notifyAll, toString, wait, wait, wait
 

Field Detail

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 Detail

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 Detail

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 <T extends org.graphstream.graph.Edge> T 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 <T extends org.graphstream.graph.Node> T 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.


Copyright © 2013. All Rights Reserved.