Package tulip :: Package transys :: Module labeled_graphs :: Class LabeledDiGraph
[frames] | no frames]

Class LabeledDiGraph


Directed multi-graph with constrained labeling.

Provides facilities to define labeling functions on vertices and edges, with given co-domains, so that labels are type-checked, not arbitrary.

Each state (or edge) is annotated with labels. Before removing a value from a label type, first make sure no state (or edge) is labeled with it.

Multiple edges with the same attr_dict are not possible. So the difference from networkx.MultiDiGraph is that the dict of edges between u,v is a bijection.

Between two nodes either:

but mixing labeled with unlabeled edges for the same edge is not allowed, to simplify and avoid confusion.

Deprecated dot export

BEWARE: the dot interface will be separated from the class itself. Some basic style definitions as below may remain, but masking selected labels and other features will be accessible only via functions.

For dot export subclasses must define:

Note: this interface will be improved in the future.

Credits

Some code in overridden methods of networkx.MultiDiGraph is adapted from networkx, which is distributed under the BSD license.

Instance Methods
 
__init__(self, node_label_types=None, edge_label_types=None, deterministic=False)
Initialize the types of labelings on states and edges.
bool
is_consistent(self)
Check if labels are consistent with their type definitions.
 
add_node(self, n, attr_dict=None, check=True, **attr)
Use a TypedDict as attribute dict.
 
add_nodes_from(self, nodes, check=True, **attr)
Create or label multiple nodes.
 
add_edge(self, u, v, key=None, attr_dict=None, check=True, **attr)
Use a TypedDict as attribute dict.
 
add_edges_from(self, labeled_ebunch, attr_dict=None, check=True, **attr)
Add multiple labeled edges.
 
remove_labeled_edge(self, u, v, attr_dict=None, **attr)
Remove single labeled edge.
 
remove_labeled_edges_from(self, labeled_ebunch, attr_dict=None, **attr)
Remove labeled edges.
 
has_deadends(self)
Return False if all nodes have outgoing edges.
 
remove_deadends(self)
Recursively delete nodes with no outgoing transitions.
 
dot_str(self, wrap=10, **kwargs)
Return dot string.
bool
save(self, filename=None, fileformat=None, rankdir='LR', prog=None, wrap=10, tikz=False)
Save image to file.
 
plot(self, rankdir='LR', prog=None, wrap=10, ax=None)
Plot image using dot.

Inherited from networkx.classes.multidigraph.MultiDiGraph: degree_iter, edges_iter, in_degree_iter, in_edges, in_edges_iter, is_directed, is_multigraph, out_degree_iter, out_edges, out_edges_iter, remove_edge, reverse, subgraph, to_directed, to_undirected

Inherited from networkx.classes.multigraph.MultiGraph: edges, get_edge_data, has_edge, number_of_edges, remove_edges_from, selfloop_edges

Inherited from networkx.classes.digraph.DiGraph: clear, has_predecessor, has_successor, in_degree, neighbors, neighbors_iter, out_degree, predecessors, predecessors_iter, remove_node, remove_nodes_from, successors, successors_iter

Inherited from networkx.classes.graph.Graph: __contains__, __getitem__, __iter__, __len__, __str__, add_cycle, add_path, add_star, add_weighted_edges_from, adjacency_iter, adjacency_list, copy, degree, has_node, nbunch_iter, nodes, nodes_iter, nodes_with_selfloops, number_of_nodes, number_of_selfloops, order, size

Inherited from object: __delattr__, __format__, __getattribute__, __hash__, __new__, __reduce__, __reduce_ex__, __repr__, __setattr__, __sizeof__, __subclasshook__

Properties

Inherited from networkx.classes.graph.Graph: name

Inherited from object: __class__

Method Details

__init__(self, node_label_types=None, edge_label_types=None, deterministic=False)
(Constructor)

 

Initialize the types of labelings on states and edges.

Label types by example

Use a dict for each label type you want to define, like this:

>>> types = [
        {'name': 'drink',
         'values': {'tea', 'coffee'},
         'setter': True,
         'default': 'tea'},
    ]

This will create a label type named 'drink' that can take the values 'tea' and 'coffee'.

Assuming this label type applies to nodes, you can now label a new node as:

>>> g = LabeledDiGraph(types)
>>> g.add_node(1, drink='coffee')

If you omit the label when adding a new node, it gets the default value:

>>> g.add_node(2)
>>> g.node[2]
{'drink': 'tea'}

The main difference with vanilla networkx is that the dict above includes type checking:

>>> type(g.node[2])
tulip.transys.mathset.TypedDict

The 'setter' key with value True creates also a field g.drink. Be careful to avoid name conflicts with existing networkx MultiDiGraph attributes.

This allows us to add more values after creating the graph:

>>> g.drink
{'coffee', 'tea'}
>>> g.drink.add('water')
{'coffee', 'tea', 'water'}

Finally, the graph will prevent us from accidentally using an untyped label name, by raising an AttributeError:

>>> g.add_node(3, day='Jan')
AttributeError: ...

To add untyped labels, do so explicitly:

>>> g.add_node(3, day='Jan', check=False)
>>> g.node[3]
{'day': 'Jan', 'drink': 'tea'}

Details on label types

Each label type is defined by a dict that must have the keys 'name' and 'values':

  • 'name': with str value
  • 'values' : B implements __contains__ used to check label validity.

    If you want the codomain B to be extensible even after initialization, it must implement method add.

and optionally the keys:

  • 'setter': C with 3 possibilities:
    • if absent, then no setter attribute is created
    • otherwise an attribute self.A is created, pointing at:
      • the given co-domain B if C is True
      • C, otherwise.
  • 'default': d is a value in B to be returned for node and edge labels not yet explicitly specified by the user.
Parameters:
  • node_label_types (list of dict) - applies to nodes, as described above.
  • edge_label_types - applies to edges, as described above.
  • deterministic - if True, then edge-label-deterministic
Overrides: object.__init__

is_consistent(self)

 

Check if labels are consistent with their type definitions.

Use case: removing values from a label type can invalidate existing labels that use them.

Returns: bool

add_node(self, n, attr_dict=None, check=True, **attr)

 

Use a TypedDict as attribute dict.

Log warning if node already exists.

All other functionality remains the same.

Parameters:
  • check - if True and untyped keys are passed, then raise AttributeError.
Overrides: networkx.classes.graph.Graph.add_node

add_nodes_from(self, nodes, check=True, **attr)

 

Create or label multiple nodes.

For details see add_node and networkx.MultiDiGraph.add_nodes_from

Overrides: networkx.classes.graph.Graph.add_nodes_from

add_edge(self, u, v, key=None, attr_dict=None, check=True, **attr)

 

Use a TypedDict as attribute dict.

  • Raise ValueError if u or v are not already nodes.
  • Raise Exception if edge (u, v, {}) exists.
  • Log warning if edge (u, v, attr_dict) exists.
  • Raise ValueError if attr_dict contains typed key with invalid value.
  • Raise AttributeError if attr_dict contains untyped keys, unless check=False.

Each label defines a different labeled edge. So to "change" the label, either:

  • remove the edge with this label, then add a new one, or
  • find the edge key, then use subscript notation:

    G[i][j][key]['attr_name'] = attr_value

For more details see networkx.MultiDiGraph.add_edge.

Notes

  1. Argument key has been removed compared to networkx.MultiDiGraph.add_edge, because edges are defined by their labeling, i.e., multiple edges with same labeling are not allowed.
Parameters:
  • check - raise AttributeError if attr_dict has untyped attribute keys, otherwise warn
Overrides: networkx.classes.graph.Graph.add_edge

add_edges_from(self, labeled_ebunch, attr_dict=None, check=True, **attr)

 

Add multiple labeled edges.

For details see networkx.MultiDiGraph.add_edges_from. Only difference is that only 2 and 3-tuple edges allowed. Keys cannot be specified, because a bijection is maintained.

Parameters:
Overrides: networkx.classes.graph.Graph.add_edges_from

remove_labeled_edge(self, u, v, attr_dict=None, **attr)

 

Remove single labeled edge.

Parameters:
  • attr_dict (dict) - attributes with which to identify the edge.
  • attr - keyword arguments with which to update attr_dict.

remove_labeled_edges_from(self, labeled_ebunch, attr_dict=None, **attr)

 

Remove labeled edges.

Example

>>> g = LabeledDiGraph()
>>> g.add_edge(1, 2, day='Mon')
>>> g.add_edge(1, 2, day='Tue')
>>> edges = [(1, 2, {'day':'Mon'}),
             (1, 2, {'day':'Tue'})]
>>> g.remove_edges_from(edges)
Parameters:
  • labeled_ebunch - iterable container of edge tuples Each edge tuple can be:
    • 2-tuple: (u, v) All edges between u and v are removed.
    • 3-tuple: (u, v, attr_dict) all edges between u and v annotated with that attr_dict are removed.

has_deadends(self)

 

Return False if all nodes have outgoing edges.

Edge labels are not taken into account.

dot_str(self, wrap=10, **kwargs)

 

Return dot string.

Requires pydot.

save(self, filename=None, fileformat=None, rankdir='LR', prog=None, wrap=10, tikz=False)

 

Save image to file.

Recommended file formats:

  • tikz (via dot2tex)
  • pdf
  • svg
  • dot
  • png

Any other format supported by pydot.write is available.

Experimental:

  • html (uses d3.js)
  • 'scxml'

Requires

  • graphviz dot: http://www.graphviz.org/
  • pydot: https://pypi.python.org/pypi/pydot

and for tikz:

  • dot2tex: https://pypi.python.org/pypi/dot2tex
  • dot2texi: http://www.ctan.org/pkg/dot2texi (to automate inclusion)

See Also

plot, pydot.Dot.write

Parameters:
  • filename (str) - file path to save image to Default is self.name, unless name is empty, then use 'out.pdf'.

    If extension is missing '.pdf' is used.

  • fileformat - replace the extension of filename with this. For example:
       filename = 'fig.pdf'
       fileformat = 'svg'
    

    result in saving 'fig.svg'

  • rankdir (str = 'TB' | 'LR' (i.e., Top->Bottom | Left->Right)) - direction for dot layout
  • prog (dot | circo | ... see pydot.Dot.write) - executable to call
  • wrap (int) - max width of node strings
  • tikz - use tikz automata library in dot
Returns: bool
True if saving completed successfully, False otherwise.

plot(self, rankdir='LR', prog=None, wrap=10, ax=None)

 

Plot image using dot.

No file I/O involved. Requires GraphViz dot and either Matplotlib or IPython.

NetworkX does not yet support plotting multiple edges between 2 nodes. This method fixes that issue, so users don't need to look at files in a separate viewer during development.

See Also

save

Depends

dot and either of IPython or Matplotlib