xgi.core.dihypergraph.DiHypergraph

Warning

This is an experimental module. It is not yet stable and may change in the future.

class xgi.core.dihypergraph.DiHypergraph(incoming_data=None, **attr)[source]

Bases: object

A dihypergraph is a collection of directed interactions of arbitrary size.

Warning

This is currently an experimental feature.

More formally, a directed hypergraph (dihypergraph) is a pair \((V, E)\), where \(V\) is a set of elements called nodes or vertices, and \(E\) is the set of directed hyperedges. A directed hyperedge is an ordered pair, \((e^+, e^-)\), where \(e^+ \subset V\), the set of senders, is known as the “tail” and \(e^-\subset V\), the set of receivers, is known as the “head”. The equivalent undirected edge, is \(e = e^+ \cap e^-\) and the edge size is defined as \(|e|\).

The DiHypergraph class allows any hashable object as a node and can associate attributes to each node, edge, or the hypergraph itself, in the form of key/value pairs.

Multiedges and self-loops are allowed.

Parameters:
  • incoming_data (input directed hypergraph data (optional, default: None)) –

    Data to initialize the dihypergraph. If None (default), an empty hypergraph is created, i.e. one with no nodes or edges. The data can be in the following formats:

    • directed hyperedge list

    • directed hyperedge dictionary

    • DiHypergraph object.

  • **attr (dict, optional, default: None) – Attributes to add to the hypergraph as key, value pairs.

Notes

Unique IDs are assigned to each node and edge internally and are used to refer to them throughout.

The attr keyword arguments are added as hypergraph attributes. To add node or edge attributes see add_node() and add_edge().

In addition to the methods listed in this page, other methods defined in the stats package are also accessible via the DiHypergraph class. For more details, see the tutorial.

References

Bretto, Alain. “Hypergraph theory: An introduction.” Mathematical Engineering. Cham: Springer (2013).

Examples

>>> import xgi
>>> DH = xgi.DiHypergraph([([1, 2, 3], [4]), ([5, 6], [6, 7, 8])])
>>> DH.nodes
DiNodeView((1, 2, 3, 4, 5, 6, 7, 8))
>>> DH.edges
DiEdgeView((0, 1))
>>> [[sorted(h), sorted(t)] for h, t in DH.edges.dimembers()]
[[[1, 2, 3], [4]], [[5, 6], [6, 7, 8]]]
>>> [sorted(e) for e in DH.edges.members()]
[[1, 2, 3, 4], [5, 6, 7, 8]]

Attributes

edges

An DiEdgeView of this network.

nodes

A DiNodeView of this network.

num_edges

The number of directed edges in the dihypergraph.

num_nodes

The number of nodes in the dihypergraph.

is_frozen

Checks whether a hypergraph is frozen

Methods that modify the structure

add_node

Add one node with optional attributes.

add_edge

Add one edge with optional attributes.

add_nodes_from

Add multiple nodes with optional attributes.

add_edges_from

Add multiple directed edges with optional attributes.

remove_node

Remove a single node.

remove_edge

Remove one edge.

remove_nodes_from

Remove multiple nodes.

remove_edges_from

Remove multiple edges.

clear

Remove all nodes and edges from the graph.

copy

A deep copy of the dihypergraph.

cleanup

freeze

Method for freezing a dihypergraph which prevents it from being modified

add_edge(members, id=None, **attr)[source]

Add one edge with optional attributes.

Parameters:
  • members (Iterable) – An list or tuple (size 2) of iterables. The first entry contains the elements of the tail and the second entry contains the elements of the head.

  • id (hashable, default None) – Id of the new edge. If None, a unique numeric ID will be created.

  • **attr (dict, optional) – Attributes of the new edge.

Raises:

XGIError – If members is empty or is not a list or tuple.

See also

add_edges_from

Add a collection of edges.

Examples

Add edges with or without specifying an edge id.

>>> import xgi
>>> DH = xgi.DiHypergraph()
>>> DH.add_edge(([1, 2, 3], [2, 3, 4]))
>>> DH.add_edge(([3, 4], set()), id='myedge')
add_edges_from(ebunch_to_add, **attr)[source]

Add multiple directed edges with optional attributes.

Parameters:
  • ebunch_to_add (Iterable) –

    Note that here, when we refer to an edge, as in the add_edge method, it is a list or tuple (size 2) of iterables. The first entry contains the elements of the tail and the second entry contains the elements of the head.

    An iterable of edges. This may be an iterable of edges (Format 1), where each edge is in the format described above.

    Alternatively, each element could also be a tuple in any of the following formats:

    • Format 2: 2-tuple (edge, edge_id), or

    • Format 4: 3-tuple (edge, edge_id, attr),

    where edge is in the format described above, edge_id is a hashable to use as edge ID, and attr is a dict of attributes. Finally, ebunch_to_add may be a dict of the form {edge_id: edge_members} (Format 5).

    Formats 2 and 3 are unambiguous because attr dicts are not hashable, while id`s must be. In Formats 2-4, each element of `ebunch_to_add must have the same length, i.e. you cannot mix different formats. The iterables containing edge members cannot be strings.

  • attr (**kwargs, optional) – Additional attributes to be assigned to all edges. Attribues specified via ebunch_to_add take precedence over attr.

See also

add_edge

Add a single edge.

Notes

Adding the same edge twice will create a multi-edge. Currently cannot add empty edges; the method skips over them.

Examples

>>> import xgi
>>> DH = xgi.DiHypergraph()

When specifying edges by their members only, numeric edge IDs will be assigned automatically.

>>> DH.add_edges_from([([0, 1], [1, 2]), ([2, 3, 4], [])])
>>> DH.edges.dimembers(dtype=dict)
{0: ({0, 1}, {1, 2}), 1: ({2, 3, 4}, set())}

Custom edge ids can be specified using a dict.

>>> DH = xgi.DiHypergraph()
>>> DH.add_edges_from({'one': ([0, 1], [1, 2]), 'two': ([2, 3, 4], [])})
>>> DH.edges.dimembers(dtype=dict)
{'one': ({0, 1}, {1, 2}), 'two': ({2, 3, 4}, set())}

You can use the dict format to easily add edges from another hypergraph.

>>> DH2 = xgi.DiHypergraph()
>>> DH2.add_edges_from(DH.edges.dimembers(dtype=dict))
>>> DH.edges == DH2.edges
True

Alternatively, edge ids can be specified using an iterable of 2-tuples.

>>> DH = xgi.DiHypergraph()
>>> DH.add_edges_from([(([0, 1], [1, 2]), 'one'), (([2, 3, 4], []), 'two')])
>>> DH.edges.dimembers(dtype=dict)
{'one': ({0, 1}, {1, 2}), 'two': ({2, 3, 4}, set())}

Attributes for each edge may be specified using a 2-tuple for each edge. Numeric IDs will be assigned automatically.

>>> DH = xgi.DiHypergraph()
>>> edges = [
...     (([0, 1], [1, 2]), {'color': 'red'}),
...     (([2, 3, 4], []), {'color': 'blue', 'age': 40}),
... ]
>>> DH.add_edges_from(edges)
>>> {e: DH.edges[e] for e in DH.edges}
{0: {'color': 'red'}, 1: {'color': 'blue', 'age': 40}}

Attributes and custom IDs may be specified using a 3-tuple for each edge.

>>> DH = xgi.DiHypergraph()
>>> edges = [
...     (([0, 1], [1, 2]), 'one', {'color': 'red'}),
...     (([2, 3, 4], []), 'two', {'color': 'blue', 'age': 40}),
... ]
>>> DH.add_edges_from(edges)
>>> {e: DH.edges[e] for e in DH.edges}
{'one': {'color': 'red'}, 'two': {'color': 'blue', 'age': 40}}
add_node(node, **attr)[source]

Add one node with optional attributes.

Parameters:
  • node (node) – A node can be any hashable Python object except None.

  • attr (keyword arguments, optional) – Set or change node attributes using key=value.

See also

add_nodes_from

Notes

If node is already in the dihypergraph, its attributes are still updated.

add_nodes_from(nodes_for_adding, **attr)[source]

Add multiple nodes with optional attributes.

Parameters:
  • nodes_for_adding (iterable) – An iterable of nodes (list, dict, set, etc.). OR An iterable of (node, attribute dict) tuples. Node attributes are updated using the attribute dict.

  • attr (keyword arguments, optional (default= no attributes)) – Update attributes for all nodes in nodes. Node attributes specified in nodes as a tuple take precedence over attributes specified via keyword arguments.

See also

add_node

clear(hypergraph_attr=True)[source]

Remove all nodes and edges from the graph.

Also removes node and edge attributes, and optionally hypergraph attributes.

Parameters:

hypergraph_attr (bool, optional) – Whether to remove hypergraph attributes as well. By default, True.

copy()[source]

A deep copy of the dihypergraph.

A deep copy of the dihypergraph, including node, edge, and hypergraph attributes.

Returns:

DH – A copy of the hypergraph.

Return type:

DiHypergraph

property edges

An DiEdgeView of this network.

freeze()[source]

Method for freezing a dihypergraph which prevents it from being modified

See also

frozen

Method that raises an error when a user tries to modify the hypergraph

is_frozen

Check whether a dihypergraph is frozen

Examples

>>> import xgi
>>> diedgelist = [([1, 2], [2, 3, 4])]
>>> DH = xgi.DiHypergraph(diedgelist)
>>> DH.freeze()
>>> DH.add_node(5)
Traceback (most recent call last):
xgi.exception.XGIError: Frozen higher-order network can't be modified
property is_frozen

Checks whether a hypergraph is frozen

Returns:

True if hypergraph is frozen, false if not.

Return type:

bool

See also

freeze

A method to prevent a hypergraph from being modified.

Examples

>>> import xgi
>>> edges = [([1, 2], [2, 3, 4])]
>>> DH = xgi.DiHypergraph(edges)
>>> DH.freeze()
>>> DH.is_frozen
True
property nodes

A DiNodeView of this network.

property num_edges

The number of directed edges in the dihypergraph.

Returns:

The number of directed edges in the dihypergraph.

Return type:

int

See also

num_nodes

returns the number of nodes in the dihypergraph

Examples

>>> import xgi
>>> hyperedge_list = [([1, 2], [2, 3, 4])]
>>> DH = xgi.DiHypergraph(hyperedge_list)
>>> DH.num_edges
1
property num_nodes

The number of nodes in the dihypergraph.

Returns:

The number of nodes in the dihypergraph.

Return type:

int

See also

num_edges

returns the number of edges in the dihypergraph

Examples

>>> import xgi
>>> hyperedge_list = [([1, 2], [2, 3, 4])]
>>> DH = xgi.DiHypergraph(hyperedge_list)
>>> DH.num_nodes
4
remove_edge(id)[source]

Remove one edge.

Parameters:

id (Hashable) – edge ID to remove

Raises:

XGIError – If no edge has that ID.

See also

remove_edges_from

Remove multiple edges.

remove_edges_from(ebunch)[source]

Remove multiple edges.

Parameters:

ebunch (Iterable) – Edges to remove.

Raises:

xgi.exception.IDNotFound – If an id in ebunch is not part of the network.

See also

remove_edge

remove a single edge.

remove_node(n, strong=False)[source]

Remove a single node.

The removal may be weak (default) or strong. In weak removal, the node is removed from each of its containing edges. If it is contained in any singleton edges, then these are also removed. In strong removal, all edges containing the node are removed, regardless of size.

Parameters:
  • n (node) – A node in the dihypergraph

  • strong (bool (default False)) – Whether to execute weak or strong removal.

Raises:

XGIError – If n is not in the dihypergraph.

remove_nodes_from(nodes)[source]

Remove multiple nodes.

Parameters:

nodes (iterable) – An iterable of nodes.

See also

remove_node

set_edge_attributes(values, name=None)[source]

Set the edge attributes from a value or a dictionary of values.

Parameters:
  • values (scalar value, dict-like) – What the edge attribute should be set to. If values is not a dictionary, then it is treated as a single attribute value that is then applied to every edge in DH. This means that if you provide a mutable object, like a list, updates to that object will be reflected in the edge attribute for each edge. The attribute name will be name. If values is a dict or a dict of dict, it should be keyed by edge ID to either an attribute value or a dict of attribute key/value pairs used to update the edge’s attributes.

  • name (string, optional) – Name of the edge attribute to set if values is a scalar. By default, None.

Notes

Note that if the dict contains edge IDs that are not in DH, they are silently ignored.

set_node_attributes(values, name=None)[source]

Sets node attributes from a given value or dictionary of values.

Parameters:
  • values (scalar value, dict-like) –

    What the node attribute should be set to. If values is not a dictionary, then it is treated as a single attribute value that is then applied to every node in DH. This means that if you provide a mutable object, like a list, updates to that object will be reflected in the node attribute for every node. The attribute name will be name.

    If values is a dict or a dict of dict, it should be keyed by node to either an attribute value or a dict of attribute key/value pairs used to update the node’s attributes.

  • name (string, optional) – Name of the node attribute to set if values is a scalar, by default None.

Notes

After computing some property of the nodes of a hypergraph, you may want to assign a node attribute to store the value of that property for each node.

If you provide a list as the second argument, updates to the list will be reflected in the node attribute for each node.

If you provide a dictionary of dictionaries as the second argument, the outer dictionary is assumed to be keyed by node to an inner dictionary of node attributes for that node.

Note that if the dictionary contains nodes that are not in G, the values are silently ignored.