turbograph.run subpackage#
Build computation graph and compute vertices.
This package contains all the necessary functions to build a computation graph, specify the computation functions, and compute the vertices in the graph.
turbograph.graphbuilding module#
Construct and validate directed acyclic graphs (DAGs) of quantities.
This module provides functions to create a dependency graph where vertices represent quantities, and directed edges define dependencies between them. The graph ensures that there are no cyclic dependencies and can be built from various vertex specifications.
- turbograph.run.graphbuilding.build_graph(raw_specifications, vertices=None, *, call_mode='args', backend=None)[source]#
Build a validated directed acyclic graph (DAG) from raw vertex specifications.
This function processes raw vertex specifications to construct a dependency graph. Each vertex represents a quantity, and directed edges indicate dependencies. The graph is validated to ensure it is acyclic.
- Return type:
GraphWrapper
[Any
,TypeVar
(V
, bound=Hashable
)]- Parameters:
raw_specifications (Mapping[V, VertexSpecification[V] | Mapping[str, Any] | Sequence[Any] | Callable[[...], Any] | Any]) –
A mapping of vertex names to their specifications, defining how each vertex is computed and its dependencies. Specifications can take one of four forms:
Function: The function’s signature determines dependencies:
If
call_mode='args'
, positional arguments are considered predecessors.If
call_mode='kwargs'
, keyword arguments are considered predecessors.
Value: A non-callable value for the vertex.
- Dictionary:
func
is an optional function computing the vertex (default:None
).predecessors
is an optional list of dependency names (default:()
).value
is an optional precomputed value (default:turbograph.NA
).
Sequence:: A tuple of up to three elements
(func, predecessors, value)
.
vertices (Iterable[V] | None) – An optional subset of vertices to include in the graph. If
None
, all vertices inraw_specifications
are included. Otherwise, only the specified vertices and their ancestors are retained.call_mode (Literal['args', 'kwargs', 'arg']) –
The mode used for passing input values to functions, stored as a graph attribute:
"args"
(default): Inputs are passed as positional arguments."kwargs"
: Inputs are passed as keyword arguments."arg"
: Inputs are passed as a single dictionary argument.
backend (Literal['networkx', 'igraph'] | None) – The graph backend to use. If
None
, the first available backend is used.
- Returns:
A
GraphWrapper
object representing the constructed dependency graph.The graph contains:
- Vertices with attributes:
"func"
: Function computing the vertex (orNone
if absent)."value"
: Precomputed value, or a default placeholderturbograph.NA
if absent."predecessors"
: Ordered list of predecessor vertices.
Directed edges representing dependencies.
The
call_mode
stored as a graph attribute.
- Raises:
ValueError – If the specified dependencies create a cyclic graph.
ValueError – If the graph contains isolated vertices.
Example
Construct a simple graph computing
a - b
:>>> graph = build_graph({"sub": lambda a, b: a - b}) >>> compute_from_graph(graph, values={"a": 5, "b": 3}, vertices=["sub"]) {'sub': 2}
Construct a graph with precomputed values:
>>> graph = build_graph( ... {"a": 10, "b": 5, "sub": lambda a, b: a - b}, vertices=["sub"] ... ) >>> compute_from_graph(graph) {'a': 10, 'b': 5, 'sub': 5}
turbograph.graphchecking module#
Module for validating graph properties.
This module provides utility functions to check whether a given graph meets certain structural constraints, such as being a Directed Acyclic Graph (DAG).
Note
This module is not yet complete and may be extended with additional graph validation functions in the future.
- turbograph.run.graphchecking.check_graph(graph, *, dag=True)[source]#
Perform sanity checks on the given graph.
This function validates the structure of the graph based on the provided constraints. By default, it checks whether the graph is a Directed Acyclic Graph (DAG).
- Return type:
None
- Parameters:
graph (GraphWrapper[Any, Any]) – The graph to check.
dag (bool) – If True, verifies that the graph is a DAG. Defaults to True.
- Raises:
ValueError – If the graph does not meet the specified constraints.
turbograph.graphupdating module#
Provide functionality to update dependency graphs.
- turbograph.run.graphupdating.rebuild_graph(graph, vertices=None, values=None, funcs=None, *, reduce=False, call_mode=None)[source]#
Rebuild an existing dependency graph with new functions, values, or vertices.
This function allows modifying a computation graph by: :rtype:
TypeVar
(GW
, bound=GraphWrapper
[Any
,Any
])Retaining only a subset of vertices.
Updating functions assigned to vertices.
Assigning or overriding precomputed values.
Setting a new function call mode.
Reducing the graph by treating known values as constants.
- Parameters:
graph (GW) – The dependency graph to update.
vertices (Iterable[V] | None) – The set of vertices to retain. If specified, only these vertices and their ancestors are kept.
values (Mapping[V, Any | NACLS] | None) – A mapping from vertex names to precomputed values. If provided, these values override the existing ones in the graph.
funcs (Mapping[V, Callable[[...], Any] | None] | None) – A mapping from vertex names to updated functions. If provided, these functions override the existing ones in the graph.
reduce (bool) – If
True
, removes inbound edges for vertices with known values. This treats these vertices as constants and prevents unnecessary recomputation.call_mode (Literal['args', 'kwargs', 'arg'] | None) –
The mode used to pass inputs to functions. If
None
, the call mode remains unchanged."args"
(default): Dependencies are passed as positional arguments."kwargs"
: Dependencies are passed as keyword arguments."arg"
: Dependencies are passed as a single dictionary.
reduce – If
True
, removes inbound edges for vertices with known values, treating them as constants. This ensures that these vertices no longer depend on their predecessors, preventing unnecessary computations
- Returns:
The updated graph object with the modified functions, values, and vertices.
- Return type:
Example
Update a graph with new functions and values.
>>> from turbograph import rebuild_graph, compute_from_graph, build_graph >>> graph = build_graph( ... {"sum": ["a", "b"]}, ... funcs={"sum": lambda a, b: a + b}, ... values={"a": 1, "b": 2}, ... ) >>> compute_from_graph(graph) # 1 + 2 = 3 {'a': 1, 'b': 2, 'sum': 3} >>> updated_graph = rebuild_graph( ... graph, funcs={"sum": lambda a, b: a * b}, values={"a": 10} ... ) >>> compute_from_graph(updated_graph) # 10 * 2 = 20 {'a': 10, 'b': 2, 'sum': 20}
Reduce the graph to retain only “b” and its dependencies.
>>> graph = build_graph( ... {"b": ["a"], "c": ["b"]}, ... funcs={"b": lambda x: x + 1, "c": lambda x: x + 2}, ... values={"a": 1}, ... ) >>> smaller_graph = rebuild_graph(graph, vertices=["b"]) >>> compute_from_graph(smaller_graph) {'a': 1, 'b': 2}
Notes
If both a function update and a precomputed value are provided for a vertex, the precomputed value takes precedence.
If vertices is specified, computations are limited to those vertices and their ancestors.
If reduce is enabled, vertices with known values will not be recomputed.
turbograph.graphcomputing module#
Compute values from a dependency graph.
A module that provides functions to compute values in a directed acyclic graph (DAG) based on defined dependencies and vertex-specific functions and values.
- class turbograph.run.graphcomputing.NAType#
Type representing a missing value in vertex attributes.
alias of TypeVar(‘NAType’)
- turbograph.run.graphcomputing.compute_from_graph(graph, vertices=None, values=None, funcs=None, *, call_mode=None, auto_prune=True)[source]#
Compute values in a dependency graph.
This function evaluates the specified vertices in a directed acyclic graph (DAG), ensuring that computations follow the correct dependency order. It allows overriding values, updating functions dynamically, and pruning unnecessary intermediate values.
- Return type:
dict
[TypeVar
(V
, bound=Hashable
),Any
]- Parameters:
graph (GraphWrapper[Any, V]) – The dependency graph.
vertices (Iterable[V] | None) –
The set of vertices to compute.
If
None
, all vertices in the graph are computed.If specified, only the listed vertices and their dependencies are computed.
values (Mapping[V, Any | NACLS] | None) – A mapping from vertex names to precomputed values. If provided, these values override the existing ones in the graph.
funcs (Mapping[V, Callable[[...], Any] | None] | None) – A mapping from vertex names to updated functions. If provided, these functions override the existing ones in the graph.
call_mode (Literal['args', 'kwargs', 'arg'] | None) –
The mode used to pass dependencies to functions. If
None
, the mode is inferred from the graph."args"
: Dependencies are passed as positional arguments."kwargs"
: Dependencies are passed as keyword arguments."arg"
: Dependencies are passed as a single dictionary.
auto_prune (bool) – If
True
, automatically removes intermediate vertices that are no longer needed after computation to optimize memory usage.
- Returns:
A dictionary mapping vertex names to their computed values.
- Raises:
ValueError – If cycles are detected in the graph.
Example
Compute values from a dependency graph.
>>> from turbograph import compute_from_graph, build_graph >>> deps = {"a": [], "b": [], "c": ["a", "b"], "d": ["c"]} >>> funcs = { ... "a": lambda: 5, ... "b": lambda: 10, ... "c": lambda a, b: a + b, ... "d": lambda c: c * 2, ... } >>> graph = build_graph(deps, funcs=funcs) >>> compute_from_graph(graph) {'a': 5, 'b': 10, 'c': 15, 'd': 30}
Override a vertex value before computation:
>>> compute_from_graph(graph, values={"a": 7}) {'a': 7, 'b': 10, 'c': 17, 'd': 34}
Modify a function before computation:
>>> compute_from_graph(graph, funcs={"c": lambda a, b: a * b}) {'a': 5, 'b': 10, 'c': 50, 'd': 100}
Compute only a specific vertex:
>>> compute_from_graph(graph, vertices=["c"]) {'c': 50}
Notes
If both a function update and a precomputed value are provided for a vertex, the precomputed value takes precedence.
turbograph.computing module#
Compute values directly from vertex specifications.
This module provides a high-level interface for computing values from a collection of vertex specifications, where the graph is constructed under the hood.
- turbograph.run.computing.compute(raw_specifications, vertices=None, values=None, funcs=None, *, call_mode='args', auto_prune=True, backend=None)[source]#
Compute values from vertex specifications.
This function constructs a directed acyclic graph (DAG) from the given
raw_specifications
and determines the correct execution order for computing values. It allows users to specify predefined values or override functions for specific vertices.- Return type:
dict
[TypeVar
(V
, bound=Hashable
),Any
]- Parameters:
raw_specifications (Mapping[V, VertexSpecification[V] | Mapping[str, Any] | Sequence[Any] | Callable[[...], Any] | Any]) –
A mapping of vertex names to their specifications, defining how each vertex is computed and its dependencies. Specifications can take one of four forms:
Function: The function’s signature determines dependencies:
If
call_mode='args'
, positional arguments are considered predecessors.If
call_mode='kwargs'
, keyword arguments are considered predecessors.
Value: A non-callable value for the vertex.
- Dictionary:
func
is an optional function computing the vertex (default:None
).predecessors
is an optional list of dependency names (default:()
).value
is an optional precomputed value (default:turbograph.NA
).
Sequence:: A tuple of up to three elements
(func, predecessors, value)
.
vertices (Iterable[V] | None) – The set of vertices to compute. If specified, only the listed vertices and their dependencies are computed.
values (Mapping[V, Any | NACLS] | None) – A mapping of vertex names to pre-defined values. If a vertex has an entry in this mapping, the given value is used instead of computing it from the graph.
funcs (Mapping[V, Callable[[...], Any] | None] | None) – A mapping of vertex names to functions. If a vertex has an entry in this mapping, the provided function is used instead of the one in the graph.
call_mode (Literal['args', 'kwargs', 'arg']) –
Determines how dependencies are passed to functions
"args"
(default): Dependencies are passed as positional arguments."kwargs"
: Dependencies are passed as keyword arguments."arg"
: All dependencies are passed as a single dictionary argument.
auto_prune (bool) – If
True
, automatically removes intermediate vertices that are no longer needed after computation to optimize memory usage.backend (Literal['networkx', 'igraph'] | None) – The graph backend to use. If
None
, the first available backend isused.
- Returns:
A mapping from vertex names to their computed values.
- Raises:
ValueError – If the specified dependencies introduce a cyclic dependency,
preventing execution. –
Example
Compute the sum of two numbers:
>>> compute({"x": lambda: 3, "y": lambda: 4, "sum": lambda x, y: x + y}) {'x': 3, 'y': 4, 'sum': 7}
Compute only the sum, supplying values for
a
andb
, and explicitly defining dependencies:>>> compute( ... {"sum": (lambda x, y: x + y, ["a", "b"])}, ["sum"], {"a": 1, "b": 2} ... ) {'sum': 3}
Use the
"arg"
call mode to pass dependencies as a single dictionary argument:>>> compute( ... { ... "sum": { ... "func": lambda v: v["x"] + v["y"], ... "predecessors": ["x", "y"], ... }, ... }, ... ["sum"], ... values={"x": 1, "y": 2}, ... call_mode="arg", ... ) {'sum': 7}