# Common Graph Operations¶

Many common graph operations map to simple operators in `graphi`. Unless parameters are needed, builtin operations usually suffice. For example, the outdegree of a node is simply its number of outgoing edges, i.e.

```out_degree = len(graph[node])
```

in a directed graph. Since `graphi` makes heavy use of data views (instead of copies), this has optimal performance.

## Pythonic Graph Operations¶

### Nodes of a graph¶

Graphs behave like a `set` with regard to nodes. Note that removing a node also invalidates all its edges and their values.

`graph[a] = True`
`graph.add(a)`
`graph.discard(a)`

Safely add or remove a node `a` from `graph`.

`del graph[a]`

Remove a node `a` from `graph`.

`a in graph`

Whether there is a node `a` in `graph`.

`list(graph)`
`iter(graph)`
`for a in graph:`

List/iterate/traverse all nodes in `graph` .

`len(graph)`

The number of nodes in the graph.

### Edges and values of a graph¶

Graphs special-case edges: an edge is a secondary key, being the value to nodes and the key to edge values.

`Edge[a:b] in graph`

Whether there is an edge from node `a` to node `b` in `graph`.

`Loop[a] in graph`
`Edge[a:a] in graph`

Whether there is a loop from node `a` to itself in `graph`.

`list(graph[a])`
`iter(graph[a])`
`for b in graph[a]:`

List/iterate/loop all nodes for which there is an edge from node `a`, i.e. its neighbours.

`len(graph[a])`

The number of outgoing edges of node `a`, i.e. its outdegree.

### Edge values of a graph¶

Graphs behave similar to a `dict`, tying values to edges. Note that removing a node also invalidates all its edges and their values.

`graph[a:b] = w`
`graph[Edge[a:b]] = w`

Add an edge from node `a` to node `b` with value `w`.

## Pythonic Graph Types¶

By default, every graph is a weighted, directed graph - edges are oriented from start to end node and have one edge value. However, other graph types can be created with standard language features.

`graph[a:b] = True`

Add an edge from node `a` to node `b` with the primitive value `True`.

This creates an unweighted graph edge.

`graph[a:b] = [w1, w2, w3, ...]`
`graph[a:b] = w1, w2, w3, ...`

Add an edge from node `a` to node `b` with multiple values `w1, w2, w3, ...`.

This creates a multigraph edge.