# graph

Python API: `luxonis_ml.utils.graph`

## Functions

### is_acyclic

```python
def is_acyclic(graph: dict[str, list[str]]) -> bool:
```

Test if graph is acyclic.

> **Examples**
> ```pycon
>>> is_acyclic({"a": ["b"], "b": []})
True
>>> is_acyclic({"a": ["b"], "b": ["a"]})
False
>>> is_acyclic({})
True
```

Parameters

 * `graph` (`dict[str, list[str]]`): Graph represented as a dictionary of predecessors.

Returns

 * `bool`: `True` if graph is acyclic, `False` otherwise.

### traverse_graph

```python
def traverse_graph(graph: dict[str, list[str]], nodes: Mapping[str, T]) -> Iterator[tuple[str, T, list[str], list[str]]]:
```

Traverse the graph in topological order, starting from the nodes with no predecessors.

> **Example**
> ```pycon
>>> graph = {"a": ["b"], "b": []}
>>> nodes = {"a": 1, "b": 2}
>>> for name, value, preds, rem in traverse_graph(graph, nodes):
...     print(name, value, preds, rem)
b 2 [] ['a']
a 1 ['b'] []
```

Parameters

 * `graph` (`dict[str, list[str]]`): Graph represented as a dictionary of predecessors. Keys are node names, values are node
   predecessors.
 * `nodes` (`Mapping[str, T]`): Dictionary mapping node names to values.

Returns

 * `Iterator[tuple[str, T, list[str], list[str]]]`

Yields

 * Tuples containing node name, node value, node predecessors, and remaining unprocessed nodes.

Raises

 * `RuntimeError`: If the graph is malformed.

## Attributes

### T
