TODO How do we initialize a FunctionGraph?
TODO What does a FunctionGraph do that a variable given by a TensorVariable does not?
TODO What are Features?
TODO What functionalities of FunctionGraphs are needed where?
Need to draw a map of where the different FunctionGraph functionalities could be used.
Misc
From the documentation:
A
FunctionGraphrepresents 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{=latex} of typeConstantare not counted as inputs.The
FunctionGraphsupports the replace operation which allows to replace a variable in the subgraph by another, e.g. replace(x + x).outby(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{=latex} are used) and for tracking theVariable``\s{=latex} with a :attr:FunctionGraph.clientsdictthat specifies whichApplynodes use theVariable. The :attr:FunctionGraph.clientsfield, combined with the :attr:Variable.ownerand each :attr:Apply.inputs, allows the graph to be traversed in both directions.It can also be extended with new features using :meth:
FunctionGraph.attach~feature~. SeeFeaturefor event types and documentation. Extra features allow theFunctionGraphto verify new properties of a graph as it is optimized.
What I am wondering is: when is a FunctionGraph needed? When does it become cumbersome?
import aesara
from aesara.graph.fg import FunctionGraph
import aesara.tensor as at
x = at.vector('x')
z = at.log(at.exp(x + x)) + x + x
fg = FunctionGraph(outputs=[z])
aesara.dprint(fg)print(fg.clients)TODO What is the clients dictionary used for?
It looks like this is what allows to traverse the graph?