fg
– Graph Container [doc TODO]#
FunctionGraph#
- class aesara.graph.fg.FunctionGraph(inputs: Sequence[Variable] | None = None, outputs: Sequence[Variable] | None = None, features: Sequence[Feature] | None = None, clone: bool = True, update_mapping: Dict[int, int] | None = None, **clone_kwds)[source]#
A
FunctionGraph
represents a subgraph bound by a set of input variables and a set of output variables, ie a subgraph that specifies an Aesara function. The inputs list should contain all the inputs on which the outputs depend.Variable
s of typeConstant
are not counted as inputs.The
FunctionGraph
supports the replace operation which allows to replace a variable in the subgraph by another, e.g. replace(x + x).out
by(2 * x).out
. This is the basis for optimization in Aesara.This class is also responsible for verifying that a graph is valid (ie, all the dtypes and broadcast patterns are compatible with the way the
Variable
s are used) and for tracking theVariable
s with aFunctionGraph.clients
dict
that specifies whichApply
nodes use theVariable
. TheFunctionGraph.clients
field, combined with theVariable.owner
and eachApply.inputs
, allows the graph to be traversed in both directions.It can also be extended with new features using
FunctionGraph.attach_feature()
. SeeFeature
for event types and documentation. Extra features allow theFunctionGraph
to verify new properties of a graph as it is optimized.The constructor creates a
FunctionGraph
which operates on the subgraph bound by the inputs and outputs sets.This class keeps lists for the inputs and outputs and modifies them in-place.
*TODO*
Note
FunctionGraph(inputs, outputs) clones the inputs by default. To avoid this behavior, add the parameter clone=False. This is needed as we do not want cached constants in fgraph.
- add_client(var: Variable, new_client: Tuple[Apply | Literal['output'], int]) None [source]#
Update the clients of
var
withnew_clients
.
- add_input(var: Variable, check: bool = True) None [source]#
Add a new variable as an input to this
FunctionGraph
.- Parameters:
var (aesara.graph.basic.Variable) –
- add_output(var: Variable, reason: str | None = None, import_missing: bool = False)[source]#
Add a new variable as an output to this
FunctionGraph
.
- attach_feature(feature: Feature) None [source]#
Add a
graph.features.Feature
to this function graph and trigger itson_attach
callback.
- change_node_input(node: Apply | Literal['output'], i: int, new_var: Variable, reason: str | None = None, import_missing: bool = False, check: bool = True) None [source]#
Change
node.inputs[i]
tonew_var
.new_var.type.is_super(old_var.type)
must beTrue
, whereold_var
is the current value ofnode.inputs[i]
which we want to replace.For each feature that has an
on_change_input
method, this method calls:feature.on_change_input(function_graph, node, i, old_var, new_var, reason)
- Parameters:
node – The node for which an input is to be changed. If the value is the string
"output"
then theself.outputs
will be used instead ofnode.inputs
.i – The index in
node.inputs
that we want to change.new_var – The new variable to take the place of
node.inputs[i]
.import_missing – Add missing inputs instead of raising an exception.
check – When
True
, perform a type check between the variable being replaced and its replacement. This is primarily used by theHistory
Feature
, which needs to revert types that have been narrowed and would otherwise fail this check.
- clone(check_integrity=True) FunctionGraph [source]#
Clone the graph.
- clone_get_equiv(check_integrity: bool = True, attach_feature: bool = True, **kwargs) Tuple[FunctionGraph, Dict[Apply | Variable | Op, Apply | Variable | Op]] [source]#
Clone the graph and return a
dict
that maps old nodes to new nodes.- Parameters:
check_integrity – Whether or not to check the resulting graph’s integrity.
attach_feature – Whether or not to attach
self
’s features to the cloned graph.
- Returns:
e – The cloned
FunctionGraph
. Every node in the cloned graph is cloned.equiv – A
dict
that maps old nodes to the new nodes.
- collect_callbacks(name: str, *args) Dict[Feature, Any] [source]#
Collects callbacks
Returns a dictionary d such that
d[feature] == getattr(feature, name)(*args)
For each feature which has a method called after name.
- execute_callbacks(name: str, *args, **kwargs) None [source]#
Execute callbacks.
Calls
getattr(feature, name)(*args)
for each feature which has a method called after name.
- get_clients(var: Variable) List[Tuple[Apply | Literal['output'], int]] [source]#
Return a list of all the
(node, i)
pairs such thatnode.inputs[i]
isvar
.
- import_node(apply_node: Apply, check: bool = True, reason: str | None = None, import_missing: bool = False) None [source]#
Recursively import everything between an
Apply
node and theFunctionGraph
’s outputs.- Parameters:
apply_node (Apply) – The node to be imported.
check (bool) – Check that the inputs for the imported nodes are also present in the
FunctionGraph
.reason (str) – The name of the optimization or operation in progress.
import_missing (bool) – Add missing inputs instead of raising an exception.
- import_var(var: Variable, reason: str | None = None, import_missing: bool = False) None [source]#
Import a
Variable
into thisFunctionGraph
.This will import the
var
’sApply
node and inputs.- Parameters:
variable (aesara.graph.basic.Variable) – The variable to be imported.
reason (str) – The name of the optimization or operation in progress.
import_missing (bool) – Add missing inputs instead of raising an exception.
- orderings() Dict[Apply, List[Apply]] [source]#
Return a map of node to node evaluation dependencies.
Each key node is mapped to a list of nodes that must be evaluated before the key nodes can be evaluated.
This is used primarily by the
DestroyHandler
Feature
to ensure that the clients of any destroyed inputs have already computed their outputs.Notes
This only calls the
Feature.orderings()
method of eachFeature
attached to theFunctionGraph
. It does not take care of computing the dependencies by itself.
- remove_client(var: Variable, client_to_remove: Tuple[Apply | Literal['output'], int], reason: str | None = None, remove_if_empty: bool = False) None [source]#
Recursively remove clients of a variable.
This is the main method to remove variables or
Apply
nodes from aFunctionGraph
.This will remove
var
from theFunctionGraph
if it doesn’t have any clients remaining. If it has an owner and all the outputs of the owner have no clients, it will also be removed.- Parameters:
var – The clients of
var
that will be removed.client_to_remove – A
(node, i)
pair such thatnode.inputs[i]
will no longer bevar
in thisFunctionGraph
.remove_if_empty – When
True
, ifvar
’sApply
node is removed, remove the entry forvar
inself.clients
.
- remove_feature(feature: Feature) None [source]#
Remove a feature from the graph.
Calls
feature.on_detach(function_graph)
if anon_detach
method is defined.
- remove_input(input_idx: int, reason: str | None = None)[source]#
Remove the input at index
input_idx
.
- remove_node(node: Apply, reason: str | None = None)[source]#
Remove an
Apply
node from theFunctionGraph
.This will remove everything that depends on the outputs of
node
, as well as any “orphaned” variables and nodes created bynode
’s removal.
- remove_output(output_idx: int, reason: str | None = None)[source]#
Remove the output at index
input_idx
.
- replace(var: Variable, new_var: Variable, reason: str | None = None, verbose: bool | None = None, import_missing: bool = False) None [source]#
Replace a variable in the
FunctionGraph
.This is the main interface to manipulate the subgraph in
FunctionGraph
. For every node that usesvar
as input, makes it usenew_var
instead.- Parameters:
var – The variable to be replaced.
new_var – The variable to replace
var
.reason – The name of the optimization or operation in progress.
verbose – Print
reason
,var
, andnew_var
.import_missing – Import missing variables.
- replace_all(pairs: Iterable[Tuple[Variable, Variable]], **kwargs) None [source]#
Replace variables in the
FunctionGraph
according to(var, new_var)
pairs in a list.
- setup_var(var: Variable) None [source]#
Set up a variable so it belongs to this
FunctionGraph
.- Parameters:
var (aesara.graph.basic.Variable) –
- toposort() List[Apply] [source]#
Return a toposorted list of the nodes.
Return an ordering of the graph’s
Apply
nodes such that:all the nodes of the inputs of a node are before that node, and
they satisfy the additional orderings provided by
FunctionGraph.orderings()
.
FunctionGraph Features#
- class aesara.graph.features.Feature[source]#
Base class for FunctionGraph extensions.
A Feature is an object with several callbacks that are triggered by various operations on FunctionGraphs. It can be used to enforce graph properties at all stages of graph optimization.
See also
aesara.graph.features
for common extensions.
- clone()[source]#
Create a clone that can be attached to a new
FunctionGraph
.This default implementation returns
self
, which carries the assumption that theFeature
is essentially stateless. If a subclass has state of its own that is in any way relative to a givenFunctionGraph
, this method should be overridden with an implementation that actually creates a fresh copy.
- on_attach(fgraph)[source]#
Called by
FunctionGraph.attach_feature
, the method that attaches the feature to theFunctionGraph
. Since this is called after theFunctionGraph
is initially populated, this is where you should run checks on the initial contents of theFunctionGraph
.The on_attach method may raise the
AlreadyThere
exception to cancel the attach operation if it detects that another Feature instance implementing the same functionality is already attached to theFunctionGraph
.The feature has great freedom in what it can do with the
fgraph
: it may, for example, add methods to it dynamically.
- on_change_input(fgraph, node: Apply, i: int, var: Variable, new_var: Variable, reason: str | None = None)[source]#
Called whenever
node.inputs[i]
is changed fromvar
tonew_var
. At the moment the callback is done, the change has already taken place.If you raise an exception in this function, the state of the graph might be broken for all intents and purposes.
- on_detach(fgraph)[source]#
Called by
FunctionGraph.remove_feature
. Should remove any dynamically-added functionality that it installed into the fgraph.
- on_import(fgraph, node: Apply, reason: str | None)[source]#
Called whenever a node is imported into
fgraph
, which is just before the node is actually connected to the graph.Note: this is not called when the graph is created. If you want to detect the first nodes to be implemented to the graph, you should do this by implementing
on_attach
.
- on_prune(fgraph, node: Apply, reason: str | None) None [source]#
Called whenever a node is pruned (removed) from the
fgraph
, after it is disconnected from the graph.
- orderings(fgraph, ordered: bool = True) Dict[Apply, Set[Apply]] [source]#
Called by
FunctionGraph.toposort
. It should return a dictionary of{node: predecessors}
wherepredecessors
is a list of nodes that should be computed before the key node.If you raise an exception in this function, the state of the graph might be broken for all intents and purposes.
FunctionGraph Feature List#
ReplaceValidate
DestroyHandler