Bio::Graph::SimpleGraph - create and manipulate undirected graphs
use Bio::Graph::SimpleGraph;
my $graph=new SimpleGraph;# read pairs of nodes from STDINwhile (<>) {my($node1,$node2)=split;$graph->add_edge($node1,$node2);}my @nodes=graph->nodes; # get list of nodesmy @edges=graph->edges; # get list of edgesforeach my $node (@nodes) {my @neighbors=$node->neighbors; # get list of neighboring nodes}
This is a simple, hopefully fast undirected graph package. The only reason this exists is that the standard CPAN Graph pacakge, Graph::Base, is seriously broken. The package implements a small and eclectic assortment of standard graph algorithms that we happened to need for our applications. This module is a subclass of Class::AutoClass (available at CPAN). AutoClass auotgenerates simple accessor and mutator methods (aka get and set methods). It also automates class initialization. Nodes can be any Perl values, including object references. Edges are pairs of nodes. (Caveat: be careful with values that contain embedded instances of $; (the character Perl uses to separate components of multi-dimensional subscripts), because we use this in the text representation of edges. The main data structures are:
An edge (x,y) is represented canonically as a two element list inwhich the lexically smaller value is first. Eg, the node ('b','a')is represented as ['a','b'].
The graph contains
1) A hash mapping the text representation of a node to the nodeitself. This is mostly relevant when the node is a reference.
2) A hash mapping the text representation of a node to a list ofthe node's neighbors.
3) A hash mapping the text representation of an edge to the edge itself.
This is still a work in progress. Email [email protected] Copyright (c) 2003 Institute for Systems Biology (ISB). All Rights Reserved. This module is free software; you can redistribute it and/or modify it under the same terms as Perl itself.
Conventions for nodes and edges A node can be any Perl values, including an object, ARRAY, or HASH reference. When nodes are references, the software often works with the text representaion of the reference, ie, what you get if you print the reference. This can be confusing. Sorry. For example if a node is the HASH
{name=>'caspase-9',symbol=>'CASP9'}
The text representation would be something like
HASH(0x804c830)
When nodes are scalar values, eg, a string, the value and the text representation are the same. This is a common case in test programs and examples, but less common in real applications. An edge is represented internally as an ARRAY ref of two nodes, in which the lexically smaller value is first. Actually, the first node is the one whose text representation is lexically smaller. When passing edges as arguments to SimpleGraph methods, the edge can be represented in several ways.
1) An ARRAY ref of the nodes, eg, ['a','b'].
2) A list of the two nodes, eg, ('a','b')
3) Form (1) or (2) using the text represention of the nodeinstead of the node itself
You needn't worry about which node is lexically smaller. SimpleGraph performs this calculation internally. When SimpleGraph returns edges as results, they are always in form (1), ie, as ARRAY refs of nodes in correct lexical order.
General conventions for methods When methods return lists, we generally check the context (via wantarray) and return an ARRSY or ARRAY ref as appropriate. We're not 100% consistent in this (sorry), so check the code if you have doubts. We often define singular and plural forms of methods, eg, node and nodes. These differ in how they behave in a scalar context. The singular form assumes you want one answer and returns that, while the plural form assumes you want a list of answers are returns it as an ARRAY ref. We're not 100% consistent in this (sorry), so check the code if you have doubts. The rest of the documentation describes the methods.
Constructors
Title : new (inherited from Class::AutoClass)Usage : my $graph=new SimpleGraph;Function: Create new SimpleGraph objectReturns : Newly created objectArgs : (optional)nodes=>ARRAY of nodes, eg, ['a','b','c']edges=>ARRAY of edges, see add_edges for details
Basic node and edge operations
Title : add_nodes, add_nodeUsage : $graph->add_nodes('a','b');$graph->add_node('a')) {Function: Add nodes to graph. Nodes that are already in graphare ignored.Args : ARRAY of nodes.Returns : Nothing usefulNote : Singular and plural forms are synonymous
Title : add_edges, add_edgeUsage : $graph->add_edges('a','b',['b','c']);$graph->add_edge('c','d')) {Function: Add edges to graph.Edges that are already in graph are not added again, butare placed in a separate 'duplicate edges' list.Automatically adds any nodes that are not yet in the graph.Args : ARRAY of edges in any of the forms described in theprevious section. The forms can be mixed as shown inthe Usage here.Returns : Nothing usefulNote : Singular and plural forms are synonymous
Title : nodesUsage : my @nodes=$graph->nodes;if (@{$graph->nodes('a','b')}==2) {print "a, b are both nodes\n";}Function: Return all nodes or the given ones.With no args returns all nodes.With args, returns the nodes corresponding to each arg, orundef if the arg is not a node. Useful for testing whethera given value is a node in the graph.Args : (optional)ARRAY of nodes or text representations of nodesReturns : ARRAY or ARRAY ref of nodes (for args that correspond tonodes), or undef (for args that are not nodes)
Title : edgesUsage : my @edges=$graph->edges;if (@{$graph->edges('a','b',['b','c'])}==2) {print "[a,b] and [b,c] are both edges\n";}Function: Return all edges or the given ones.With no args returns all edges.With args, returns the edges corresponding to each arg, orundef if the arg is not a edge. Useful for testing whethera given value is a edge in the graph.Args : (optional)One or more edges in any of the forms described in theprevious section. The forms can be mixed as shown inthe Usage here.Returns : ARRAY or ARRAY ref of edges for args that correspond toedges), or undef (for args that are not edges)
Title : nodeUsage : if ($graph->node('a')) {print "a is a node\n";}Function: Test whether a value is a node in the graph, or map thetext representation of a node to the node itself. Themethod can also be fed a list of values (like the 'nodes'method) and it will test all of them.Args : Usually, a single node.The function also accepts a list of nodes.Returns : In scalar context (the usual case): the node correspondingto the arg (if there's just one), or the node correspondingto the first arg (if a list of args were provided, which iskind of dumb in this case), or undef if the arg is not anode.
In array context, it behaves just like 'nodes', returningan ARRAY of nodes (for args that correspond to nodes), orundef (for args that are not nodes)
Title : edgeUsage : if ($graph->edge('a','b')) {print "a,b is a edge\n";}if ($graph->edge(['a','b'])) {print "[a,b] is a edge\n";}Function: Test whether a value is a edge in the graph, or map thetext representation of a edge to the edge itself. Themethod can also be fed a list of edges (like the 'edges'method) and it will test all of them.Args : Usually, a single edge. Same format as 'edges'The function also accepts a list of edges, exactly like'edges'Returns : In scalar context (the usual case): the edge correspondingto the arg (if there's just one), or the or the edgecorresponding to the first arg (if a list of args wereprovided, which is kind of dumb in this case), or undef ifthe arg is not a edge.
In array context, it behaves just like 'edge's, returningan ARRAY of edges (for args that correspond to edges), orundef (for args that are not edges)
Title : has_nodes, has_nodeUsage : if ($graph->has_nodes('a','b')) {print "a, b are both nodes\n";}if ($graph->has_node('a')) {print "a is a node\n";}Function: Return true is all args are nodes.Args : ARRAY of nodes or text representations of nodesReturns : BooleanNote : Singular and plural forms are synonymous
Title : has_edgesUsage : if ($graph->has_edges('a','b',['b','c'])) {print "[a,b] and [b,c] are both edges\n";}if ($graph->has_edge('a','b')) {print "[a,b] is an edge\n";}Function: Return true is all args are edges.Args : ARRAY of edges in the forms described in the section aboveReturns : BooleanNote : Singular and plural forms are synonymous
Title : neighbors, neighborUsage : my @nodes=$graph->neighbors($node)my @nodes=$graph->neighbors($node,'node')my @edges=$graph->neighbors($edge,'edge');Function: Return the node or edge neighbors of a given node or edge.Args : (mandatory)$source: node or edge whose neighbors are sought(optional)$what: the word 'node' or 'edge' (actually, anything startingwith 'n' or 'e' will do)default: 'node'Returns : ARRAY or ARRAY ref of nodes or edgesNote : Singular and plural forms are synonymous. This may not beright.
Title : dup_edgesUsage : my @dups=$graph->dup_edges;Function: Return duplicate edgesArgs : NoneReturns : ARRAY or ARRAY ref of edges that have been added more thanonce.
Graph properties
Title : is_connectedUsage : if ($graph->is_connected) {print "graph has only one connected component\n";}Function: Return true if the graph is connectedArgs : NoneReturns : Boolean
Title : is_emptyUsage : if ($graph->is_empty) {print "graph has no nodes or edges\n";}Function: Return true if the graph is empty, ie, has no nodes or edgesArgs : NoneReturns : Boolean
Title : is_treeUsage : if ($graph->is_tree) {print "graph is a tree\n";}Function: Return true if the graph is a tree, ie, it's connected andhas no cyclesArgs : NoneReturns : Boolean
Title : is_forestUsage : if ($graph->is_forest) {print "graph is a forest\n";}Function: Return true if the graph is a forest, ie, it has no cyclesbut may not be connectedArgs : NoneReturns : Boolean
Title : is_cyclicUsage : if ($graph->is_cyclic) {print "graph contains at least one cycle\n";}Function: Return true if the graph is a cyclic.Args : NoneReturns : Boolean
Title : densityUsage : my $density=$graph->densityFunction: Compute graph 'density' which is the number of edgesdivided by the maximum possible number of edgesArgs : NoneReturns : Number
Graph operations
Title : subgraphUsage : my $subgraph=$graph->subgraph('a','b','c');Function: Compute node subgraph. Constructs a new graph whose nodesare the arguments, and whose edges are the edges of theoriginal graph that only involve the given nodes.Args : ARRAY of nodes or text representations of nodesReturns : New graph
Title : neighbor_subgraphUsage : my $subgraph=$graph->subgraph('a');Function: Construct node subgraph graph whose nodes are the givennode and its neighbors. are the arguments, and whose edgesare the edges of the original graph that only involve thegiven nodes.Args : Node or text representations of nodeReturns : New graph
Title : unionUsage : my $union=$graph->union($other_graph);Function: Construct new graph whose nodes are the union of the nodesof the current graph and $other_graph, and whose edges arethe union of the edges of the current graph and$other_graph.Args : $other_graph: a graphReturns : New graph
Title : intersectionUsage : my $intersection=$graph->intersection($other_graph);Function: Construct new graph whose nodes are the intersection of thenodes of the current graph and $other_graph, and whoseedges are the intersection of the edges of the currentgraph and $other_graph.Args : $other_graph: a graphReturns : New graph
Graph algorithms
Title : traversalUsage : my $traversal=$graph->traversal('a','depth first','node');my @nodes;while (my $node=$traversal->get_next) {push(@nodes,$node);}my $traversal=$graph->traversal('a','depth first','node');my @nodes=$traversal->get_all;Function: Do node or edge traversal in depth or breadth first order.Args : (optional)$start: starting node or edge for traversaldefault: software picks arbitrary start$order: 'depth first' or 'breadth first' (actually,anything starting with 'd' or 'b' will do)default: 'depth first'$what: 'node' or 'edge' (actually, anything startingwith 'n' or 'e' will do)default: 'node'Returns : SimpleGraph::Traversal objectThis is an iterator with the following methods:
get_next: get next item in traversal or undef iftraversal is exhaustedget_this: get current item in traversalget_all : get all remaining items in traversal asARRAY (in array context) or ARRAY refhas_next: return true if there are more items intraversal, else undefreset : restart traversal
Note : It's also possible, and perhaps easier, to perform atraversal by creating a SimpleGraph::Traversal objectdirectly. The constructor is
new SimpleGraph::Traversal(-graph=>$graph,-start=>$start,-order=>$order,-what=>$what)
Title : node_traversalUsage : my $traversal=$graph->node_traversal('a','depth first');my @nodes;while (my $node=$traversal->get_next) {push(@nodes,$node);}my $traversal=$graph->node_traversal('a','depth first');;my @nodes;
my @nodes;
my @nodes=$traversal->get_all;Function: Do node traversal in depth or breadth first order.Wrapper for 'traversal' method. See above.Args : (optional)$start: starting node for traversaldefault: software picks arbitrary start$order: 'depth first' or 'breadth first' (actually,anything starting with 'd' or 'b' will do)default: 'depth first'Returns : SimpleGraph::Traversal object
Title : edge_traversalUsage : my $traversal=$graph->edge_traversal('a','depth first');my @edges;while (my $edge=$traversal->get_next) {push(@edges,$edge);}my $traversal=$graph->edge_traversal('a','depth first');my @edges=$traversal->get_all;Function: Do edge traversal in depth or breadth first order.Wrapper for 'traversal' method. See above.Args : (optional)$start: starting edge for traversaldefault: software picks arbitrary start$order: 'depth first' or 'breadth first' (actually,anything starting with 'd' or 'b' will do)default: 'depth first'Returns : SimpleGraph::Traversal object
Title : componentsUsage : my @components=$graph->components;for my $component (@components) {my @nodes=$component->nodes;my @edges=$component->edges;}Function: Compute the connected components of the graph. A connectedcomponent is a maximal connected subgraph. 'Connected'means you can get from any node of the component to anyother by following a path. 'Maximal' means that every nodeyou can reach from the component is in the component.Args : NoneReturns : ARRAY or ARRAY ref of SimpleGraphsNote : The software caches the components once computed, so it's efficientto call this repeatedly.
Title : shortest_pathsUsage : my @paths=$graph->shortest_paths;for my $path (@paths) {my @nodes_on_path=@$path;my $start=$nodes_on_path[0];my $end=$nodes_on_path[$#nodes_on_path];}Function: Compute shortest path between each pair of nodes.Args : NoneReturns : ARRAY or ARRAY ref of paths, where each path is an ARRAYref of nodes. The result contains one path for each pairof nodes for which a path exists.
Title : connected_nodesetsUsage : my @nodesets=$graph->connected_nodesets;for my $nodeset (@nodesets) {my @nodes=@$nodeset;}Function: Compute all sets of nodes that form connected subgraphs.A connected nodeset is a set of nodes such that it'spossible to get from any node to any other by following apath that only includes nodes in the set.Args : NoneReturns : ARRAY or ARRAY ref of nodeset, where each nodeset is an ARRAYref of nodes.Note : Use with caution. The number of nodesets is verylarge for graphs that are highly connected.
Title : connected_subgraphsUsage : my @subgraphs=$graph->connected_subgraphs;Function: Compute all connected subgraphs of the current graph.Args : NoneReturns : ARRAY or ARRAY ref of subgraphsNote : Use with caution. The number of connected subgraphs isvery large for graphs that are highly connected.