de.saar.chorus.domgraph.graph
Class DomGraph

Object
  extended by DomGraph
All Implemented Interfaces:
Cloneable

public class DomGraph
extends Object
implements Cloneable

A dominance graph. Dominance graphs are directed graphs. Nodes are either labelled or unlabelled; edges are either dominance or tree edges. We say that a node is a root if it has no incoming tree edges; a leaf if it has no outgoing tree edges; and a hole if it is unlabelled.

Graph objects provide several basic methods for accessing nodes, edges, and node and edge data. In addition, they provide a number of methods for checking whether the graph belongs to one of the important graph classes, such as (weakly) normal and hypernormally connected graphs.

Several methods can take a subgraph of this graph as an argument. In this context, a subgraph is always a set of nodes.

While nodes are marked as labelled or unlabelled here, the actual node labels are not stored here, but in objects of the class NodeLabels.

Author:
Alexander Koller

Constructor Summary
DomGraph()
           
 
Method Summary
 void addEdge(String src, String tgt, EdgeData data)
          Adds an edge from "src" to "tgt" with the given edge data to the graph.
 void addNode(String name, NodeData data)
          Adds a node with the given node name and node data to the graph.
 void clear()
          Removes all nodes and edges from this graph.
 Object clone()
           
 DomGraph compactify()
          Computes a compact version of this graph.
 Map<String,Integer> computeWccMap(List<Set<String>> wccs)
          Computes a mapping of nodes to wcc indices from a list of wccs.
 List<Edge> getAdjacentEdges(String node)
          Computes the set of all adjacent edges of a node.
 List<Edge> getAdjacentEdges(String node, EdgeType type)
          Computes the set of all adjacent edges of a node with a given type.
 List<DomEdge> getAllDomEdges()
           
 Set<Edge> getAllEdges()
          Computes the set of all edges in this graph.
 Set<String> getAllNodes()
          Computes the set of all nodes in this graph.
 Set<String> getAllRoots()
          Collects all roots in the graph.
 Set<String> getAllRoots(Collection<String> nodes)
          Collects all nodes in a given subgraph which are roots.
 List<String> getChildren(String node, EdgeType type)
          Computes the set of children of a node via edges of a given type.
 EdgeData getData(Edge edge)
          Gets the data associated with the given edge.
 NodeData getData(String node)
          Gets the data associated with the given node.
 Set<String> getFragment(String node)
          Computes the fragment of a given node.
 List<String> getHoles(Collection<String> fragment)
          Computes the holes out of a given collection of nodes.
 List<String> getHoles(String node)
          Computes the holes below the given node.
 List<Edge> getInEdges(String node, EdgeType type)
          Computes the set of all incoming edges of a node with a given type.
 List<String> getOpenHoles(String node)
          Computes the open holes below a given node.
 List<Edge> getOutEdges(String node, EdgeType type)
          Computes the set of all outgoing edges of a node with a given type.
 List<String> getParents(String node, EdgeType type)
          Computes the set of parents of a node via edges of a given type.
 String getRoot(String node)
          Computes the root of the fragment of the given node.
 boolean hasCycle(Set<String> subgraph, EdgeType type)
          Determines whether a subgraph has a directed cycle.
 boolean hasNode(String name)
          Checks whether the graph has a node with the given name.
 int indeg(String node)
          Computes the number of incoming edges of a given node.
 int indeg(String node, EdgeType type)
          Computes the number of incoming edges of a given node with a given type.
 int indegOfSubgraph(String node, EdgeType type, Set<String> subgraph)
          Computes the number of incoming edges of a given node, with a given edge type, and whose source nodes are in the given subgraph.
 boolean isCompact()
          Checks whether this graph is compact.
 boolean isCompactifiable()
          Checks whether this graph can be compactified.
static boolean isEqual(DomGraph graph1, NodeLabels labels1, DomGraph graph2, NodeLabels labels2)
           
 boolean isHypernormallyConnected()
          Checks whether the graph is hypernormally connected.
 boolean isHypernormallyConnectedFast()
          Checks whether the graph is hypernormally connected.
 boolean isHypernormallyConnectedSlow()
          Checks whether the graph is hypernormally connected.
 boolean isHypernormallyReachable(String source, String target)
          Checks whether there is a hypernormal path between two nodes.
 boolean isHypernormallyReachable(String source, String target, Set<String> avoidThese)
          Checks whether there is a hypernormal path between source and target which doesn't visit any of the nodes in avoidThese.
 boolean isLeaf(String node)
          Checks whether a node is a leaf.
 boolean isLeafLabelled()
          Checks whether the graph is leaf-labelled.
 boolean isNormal()
          Checks whether this graph is normal.
 boolean isRoot(String node)
          Checks whether a node is a root.
 boolean isSimpleSolvedForm()
          Checks whether the graph is a simple solved form, i.e.
 boolean isWeaklyNormal()
          Checks whether this graph is weakly normal.
 boolean isWellFormed()
          Check whether the weakly normal graph is "well-formed" in the sense of Bodirsky et al.
 int outdeg(String node)
          Computes the number of outgoing edges of a given node.
 int outdeg(String node, EdgeType type)
          Computes the number of outgoing edges of a given node with a given type.
 boolean reachable(String upper, String lower)
          Checks whether there is a directed path from "upper" to "lower" in the graph.
 void remove(Edge edge)
          Removes a given edge from the graph.
 void remove(String node)
          Removes a given node and all adjacent edges from the graph.
 String toString()
           
 List<Set<String>> wccs()
          Computes the weakly connected components of the graph.
 List<Set<String>> wccs(Set<String> nodes)
          Computes the weakly connected components of a subgraph.
 DomGraph withDominanceEdges(Collection<DomEdge> domedges)
          Returns a dominance graph that is just like the current graph, except that the dominance edges are replaced by those specified in domedges.
 
Methods inherited from class Object
equals, getClass, hashCode, notify, notifyAll, wait, wait, wait
 

Constructor Detail

DomGraph

public DomGraph()
Method Detail

getRoot

public String getRoot(String node)
Computes the root of the fragment of the given node.

Parameters:
node - a node in the graph
Returns:
the root of this node's fragment, or null if the fragment is cyclic.

getHoles

public List<String> getHoles(String node)
Computes the holes below the given node.

Parameters:
node - a node in the graph
Returns:
the holes of this node's fragment.

getHoles

public List<String> getHoles(Collection<String> fragment)
Computes the holes out of a given collection of nodes.

Parameters:
fragment - a collection of nodes in this graph
Returns:
those nodes out of "fragment" which are holes.

getOpenHoles

public List<String> getOpenHoles(String node)
Computes the open holes below a given node. Open holes are holes without outgoing dominance edges.

Parameters:
node - a node in this graph
Returns:
the list of open holes below "node"

getFragment

public Set<String> getFragment(String node)
Computes the fragment of a given node. A fragment is a maximal set of nodes that are connected via tree edges.

Parameters:
node - a node of this graph
Returns:
the fragment of this node

reachable

public boolean reachable(String upper,
                         String lower)
Checks whether there is a directed path from "upper" to "lower" in the graph.

Parameters:
upper - a node in the graph
lower - a node in the graph
Returns:
true iff there is a directed path from upper to lower

clear

public void clear()
Removes all nodes and edges from this graph.


addNode

public void addNode(String name,
                    NodeData data)
Adds a node with the given node name and node data to the graph.

Parameters:
name - the name of the new node
data - the data for the new node

addEdge

public void addEdge(String src,
                    String tgt,
                    EdgeData data)
Adds an edge from "src" to "tgt" with the given edge data to the graph.

Parameters:
src - an existing node in the graph
tgt - an existing node in the graph
data - the data for the new edge

remove

public void remove(String node)
Removes a given node and all adjacent edges from the graph.

Parameters:
node - a node in this graph

remove

public void remove(Edge edge)
Removes a given edge from the graph.

Parameters:
edge - an edge in this graph

getAllNodes

public Set<String> getAllNodes()
Computes the set of all nodes in this graph.

Returns:
the set of all nodes

hasNode

public boolean hasNode(String name)
Checks whether the graph has a node with the given name.

Parameters:
name - a node name
Returns:
true iff "name" is a node of this graph.

getAllEdges

public Set<Edge> getAllEdges()
Computes the set of all edges in this graph.

Returns:
the set of all edges

getInEdges

public List<Edge> getInEdges(String node,
                             EdgeType type)
Computes the set of all incoming edges of a node with a given type. You can select edges of all types by passing null as the "type" argument.

Parameters:
node - a node in the graph
type - an edge type, or null for edges of all types
Returns:
the list of incoming edges of this type

getParents

public List<String> getParents(String node,
                               EdgeType type)
Computes the set of parents of a node via edges of a given type. You can select parents via edges of all types by passing null as the "type" argument.

Parameters:
node - a node in the graph
type - an edge type, or null for edges of all types
Returns:
the list of parents via edges of this type

getOutEdges

public List<Edge> getOutEdges(String node,
                              EdgeType type)
Computes the set of all outgoing edges of a node with a given type. You can select edges of all types by passing null as the "type" argument.

Parameters:
node - a node in the graph
type - an edge type, or null for edges of all types
Returns:
the list of outgoing edges of this type

getAdjacentEdges

public List<Edge> getAdjacentEdges(String node,
                                   EdgeType type)
Computes the set of all adjacent edges of a node with a given type. You can select edges of all types by passing null as the "type" argument.

Parameters:
node - a node in the graph
type - an edge type, or null for edges of all types
Returns:
the list of adjacent edges of this type

getAdjacentEdges

public List<Edge> getAdjacentEdges(String node)
Computes the set of all adjacent edges of a node. This is equivalent to getAdjacentEdges(node,null).

Parameters:
node - a node in the graph
Returns:
the list of adjacent edges

getChildren

public List<String> getChildren(String node,
                                EdgeType type)
Computes the set of children of a node via edges of a given type. You can select children via edges of all types by passing null as the "type" argument.

Parameters:
node - a node in this graph
type - an edge type, or null for edges of all types
Returns:
the list of children via edges of this type

getData

public NodeData getData(String node)
Gets the data associated with the given node.

Parameters:
node - a node in this graph
Returns:
the node data

getData

public EdgeData getData(Edge edge)
Gets the data associated with the given edge.

Parameters:
edge - an edge in this graph
Returns:
the edge data

indeg

public int indeg(String node)
Computes the number of incoming edges of a given node. This is equivalent to indeg(node,null).

Parameters:
node - a node in this graph
Returns:
the indegree of the node

outdeg

public int outdeg(String node)
Computes the number of outgoing edges of a given node. This is equivalent to outdeg(node,null).

Parameters:
node - a node in this graph
Returns:
the outdegree of this node

indeg

public int indeg(String node,
                 EdgeType type)
Computes the number of incoming edges of a given node with a given type. You can specify that you want to count edges of any type by passing null in the "type" argument.

Parameters:
node - a node in the graph
type - the type of the in-edges you want to count, or null for edges of any type
Returns:
the number of in-edges of this type

indegOfSubgraph

public int indegOfSubgraph(String node,
                           EdgeType type,
                           Set<String> subgraph)
Computes the number of incoming edges of a given node, with a given edge type, and whose source nodes are in the given subgraph.

Parameters:
node - a node in the graph
type - an edge type, or null for edges of any type
subgraph - the subgraph (i.e. set of nodes) in which the parents must be
Returns:
the number of such in-edges

outdeg

public int outdeg(String node,
                  EdgeType type)
Computes the number of outgoing edges of a given node with a given type. You can specify that you want to count edges of any type by passing null in the "type" argument.

Parameters:
node - a node in the graph
type - the type of the out-edges you want to count, or null for edges of any type
Returns:
the number of out-edges of this type

isRoot

public boolean isRoot(String node)
Checks whether a node is a root. Roots are nodes with no incoming tree edges.

Parameters:
node - a node
Returns:
true iff the node has no incoming tree edges

isLeaf

public boolean isLeaf(String node)
Checks whether a node is a leaf. Leaves are nodes with no outgoing tree edges. In particular, all holes are leaves by definition (but not vice versa).

Parameters:
node - a node in the graph
Returns:
true iff the node has no outgoing tree edges

getAllRoots

public Set<String> getAllRoots(Collection<String> nodes)
Collects all nodes in a given subgraph which are roots.

Parameters:
nodes - a collection of nodes (defining a subgraph)
Returns:
the set of all nodes among "nodes" which are roots

getAllRoots

public Set<String> getAllRoots()
Collects all roots in the graph. This is equivalent to getAllRoots(getAllNodes()).

Returns:
all roots in this graph

hasCycle

public boolean hasCycle(Set<String> subgraph,
                        EdgeType type)
Determines whether a subgraph has a directed cycle. You can specify the subgraph whose nodes can be used for the cycle (or pass null for the complete graph) and the edge type which can be used for the cycle (or pass null for edges of any type). The subgraph need not be (strongly) connected; the method will restart the DFS at unvisited nodes of the subgraph while any exist.

Parameters:
subgraph - the nodes which the DFS may visit, or null for the whole graph
type - the edge types which the DFS may use, or null for any type
Returns:
true iff a cycle was found given these constraints

wccs

public List<Set<String>> wccs()
Computes the weakly connected components of the graph. A weakly connected component is a maximal subgraph which is connected via edges or inverse edges of any type. This is equivalent to wccs(getAllNodes()).

Returns:
the list of wccs; each wcc is a set of nodes.

wccs

public List<Set<String>> wccs(Set<String> nodes)
Computes the weakly connected components of a subgraph. A weakly connected component is a maximal subgraph which is connected via edges or inverse edges of any type.

Parameters:
nodes - the subgraph whose wccs we want
Returns:
the list of wccs; each wcc is a set of nodes.

computeWccMap

public Map<String,Integer> computeWccMap(List<Set<String>> wccs)
Computes a mapping of nodes to wcc indices from a list of wccs. Such a mapping assigns to each node in any of the wccs the index between 0 and wccs.size()-1 which contains this node.

Parameters:
wccs - a list of WCCs, as computed by the wccs methods.
Returns:
the mapping described above.

getAllDomEdges

public List<DomEdge> getAllDomEdges()

withDominanceEdges

public DomGraph withDominanceEdges(Collection<DomEdge> domedges)
Returns a dominance graph that is just like the current graph, except that the dominance edges are replaced by those specified in domedges. The original graph is not modified.

Parameters:
domedges - the dominance edges of the new graph
Returns:
a new dominance graph with these dominance edges

isWeaklyNormal

public boolean isWeaklyNormal()
Checks whether this graph is weakly normal. A graph is weakly normal under the following conditions:

Returns:
true iff the graph is weakly normal

isNormal

public boolean isNormal()
Checks whether this graph is normal. A graph is normal under the following conditions:

Returns:
true iff the graph is normal.

isCompact

public boolean isCompact()
Checks whether this graph is compact. A graph is compact iff it is weakly normal and only holes have incoming tree edges, i.e. every node is either a root or a hole (or both).

Returns:
true iff the graph is compact.

isCompactifiable

public boolean isCompactifiable()
Checks whether this graph can be compactified. A graph can be compactified iff it is weakly normal, and all dominance edges go either out of holes or out of roots.

Returns:
true iff the graph can be compactified

isLeafLabelled

public boolean isLeafLabelled()
Checks whether the graph is leaf-labelled. A graph is leaf-labelled iff it is weakly normal and all nodes either have a label or an outgoing dominance edge.

Returns:
true iff the graph is leaf-labelled

isHypernormallyConnected

public boolean isHypernormallyConnected()
Checks whether the graph is hypernormally connected. A graph is hypernormally connected iff it is normal and each pair of nodes is connected by a hypernormal path.

This method checks whether the graph is solvable, and then calls isHypernormallyConnectedFast (if it is) or isHypernormallyConnectedSlow (if it isn't). Its overall runtime is O(n(n+m)) for solvable graphs and O(n^2 (n+m)) for unsolvable ones.

Returns:
true iff the graph is hnc

isHypernormallyConnectedSlow

public boolean isHypernormallyConnectedSlow()
Checks whether the graph is hypernormally connected. A graph is hypernormally connected iff it is normal and each pair of nodes is connected by a hypernormal path.

This method performs a depth-first search through the dominance graph for each pair of nodes, and thus runs in time O((m+n) n^2). This is ridiculously slow, although still efficient enough for many practical purposes. However, unlike isHypernormallyConnectedFast, this method is also correct for unsolvable dominance graphs.

Returns:
true iff the graph is hnc

isHypernormallyConnectedFast

public boolean isHypernormallyConnectedFast()
Checks whether the graph is hypernormally connected. A graph is hypernormally connected iff it is normal and each pair of nodes is connected by a hypernormal path.

This method performs a single depth-first search through the dominance graph, and thus runs in time O(m+n). However, it is only correct if the graph is solvable; if the graph is unsolvable, the method may claim that the graph is not hypernormally connect although it is.

Returns:
true iff the graph is hnc

isSimpleSolvedForm

public boolean isSimpleSolvedForm()
Checks whether the graph is a simple solved form, i.e. if it is a tree and every node has at most one outgoing dominance edge.

Returns:
true iff the graph is a simple solved form.

isWellFormed

public boolean isWellFormed()
Check whether the weakly normal graph is "well-formed" in the sense of Bodirsky et al. 04. This means that every root of a dominance edge dominates a hole of its fragment.

This method assumes that the graph is weakly normal and compact.

Returns:
true iff the graph is well-formed.

isHypernormallyReachable

public boolean isHypernormallyReachable(String source,
                                        String target)
Checks whether there is a hypernormal path between two nodes. This method performs a modified depth-first search through the dominance graph, and thus takes time O(m+n).

Parameters:
source - one node in this graph
target - another node in this graph
Returns:
true iff there is a hypernormal path connecting the two

isHypernormallyReachable

public boolean isHypernormallyReachable(String source,
                                        String target,
                                        Set<String> avoidThese)
Checks whether there is a hypernormal path between source and target which doesn't visit any of the nodes in avoidThese. This method performs a modified depth-first search through the dominance graph, and thus takes time O(m+n).

The method will modify the contents of avoidThese; if you don't want this, you should pass new HashSet(...) as third argument.

Parameters:
source - one node in this graph
target - another node in this graph
avoidThese - nodes that must not be on a connecting hn path
Returns:
true iff there is a hn path connecting source and target which doesn't visit avoidThese.

compactify

public DomGraph compactify()
Computes a compact version of this graph. If the graph is already compact, the graph itself is returned. Otherwise, the compactified graph will consist of the roots and holes of the original graph; roots and holes of the same fragment are connected by new tree edges, and holes and roots of different fragments are connected by dominance edges.

The compact graph and the original graph have corresponding solved forms.

The result is only guaranteed to be compact if the graph is compactifiable according to the method isCompactifiable.

Returns:
a compact version of this graph.

toString

public String toString()
Overrides:
toString in class Object

clone

public Object clone()
Overrides:
clone in class Object

isEqual

public static boolean isEqual(DomGraph graph1,
                              NodeLabels labels1,
                              DomGraph graph2,
                              NodeLabels labels2)