relentless.model.variable.VariableGraph#

class relentless.model.variable.VariableGraph#

Directed graph of variables and dependencies.

A graph is used to track all the variables in the project and enable automatic differentiation. The graph nodes are all the Variable objects, and the graph edges represent ependencies as connections between variables. Each edge points from the variable to a dependency and carries the name of the parameter. Multiple edges are allowed between two variables. The graph is required to be acyclic (i.e., there are no circular dependencies).

Currently, only one global VariableGraph is created for the project. It is available as relentless.variable.graph.

Methods

add(x)

Add a variable to the graph.

check_variables_and_types(x, types)

Coerce variables to a tuple and check types.

evaluate(x)

Evaluate the value of a variable.

evaluate_derivative(f, x)

Evaluate the derivative of a variable with respect to another.

set_dependencies(x, depends)

Set dependencies of a variable in the graph.

update(x)

Mark a variable as being updated.

Attributes

constants

All constant variables in the graph.

dependent_variables

All dependent variables in the graph.

independent_variables

All design variables in the graph.

is_acyclic

True if the graph is acyclic.

variables

All variables in the graph.

add(x)#

Add a variable to the graph.

A new node is inserted into the project graph if the variable has not yet been added. This function is safe to call multiple times on the same variable. If x is not already a variable, an attempt is made to coerce it into a Variable. If this process fails, an error will be raised.

Adding a variable invalidates the cached is_acyclic property, which must be recomputed the next time it is accessed.

Parameters:

x (Variable or float) – The variable to add.

check_variables_and_types(x, types)#

Coerce variables to a tuple and check types.

Parameters:
  • x (Variable or tuple) – Variable(s) to check.

  • types (tuple) – Valid types for the variables to have (per isinstance).

Returns:

The variables converted to a tuple (even if there is only one).

Return type:

tuple

Raises:

TypeError – If the type does not match the allowed ones.

property constants#

All constant variables in the graph.

Type:

tuple

property dependent_variables#

All dependent variables in the graph.

Type:

tuple

evaluate(x)#

Evaluate the value of a variable.

If x is a DependentVariable, its value is computed by updating the graph using depth-first search. Postorder search is used to ensure that variables are evaluated in the proper order (i.e., from the sinks of the graph up). The results are stored in private attributes of the variables and cached to make subsequent evaluation faster.

If x is not a DependentVariable, nothing needs to be done and the value is simply returned.

Parameters:

x (Variable) – The variable to evaluate.

Returns:

The value of x.

Return type:

float

evaluate_derivative(f, x)#

Evaluate the derivative of a variable with respect to another.

Performs automatic differentiation of f with respect to x by tracing all dependency paths of the graph and applying the chain rule. Two special cases are f is x, in which case the derivative is trivially 1.0, and when f does not depend on x, in which case the derivative is trivially 0.0.

Parameters:

x (Variable) – The variable to evaluate.

Returns:

The value of x.

Return type:

float

property independent_variables#

All design variables in the graph.

Type:

tuple

property is_acyclic#

True if the graph is acyclic.

Type:

bool

set_dependencies(x, depends)#

Set dependencies of a variable in the graph.

The dependencies of x should be specified as a dictionary whose keys are the names of the parameters and whose values are Variable objects (or values that can be coerced to variables). Any existing dependencies are cleared from x before setting the ones in depends.

Parameters:
  • x (DependentVariable) – Dependent variable to set dependencies for.

  • depends (dict) – Variable(s) specifying the parameters on which x depends.

Raises:

KeyError – If a dependency is missing from depends.

update(x)#

Mark a variable as being updated.

When an IndependentVariable is updated, the graph is updated to reflect that DependentVariable objects that depend on it need to be recomputed. This is done in a lazy way by marking a private property, so the values are only recomputed when they are needed. The update is performed using depth-first search of the graph with the dependency edge directions reversed.

Warning

If an IndependentVariable is updated without updating the graph, the values of other variables will likely be incorrect. It is the responsibility of developers to ensure this is done!

Parameters:

x (IndependentVariable) – Independent variable to update.

property variables#

All variables in the graph.

Type:

tuple