1. Understanding CSDL

This section will overview how CSDL works, and introduce the Recorder, Graph, and Node classes. CSDL is a domain-specific language embedded in Python for building computational models.

dag

1.1. Building Graphs

When using CSDL, you will mainly be working with CSDL variables and operations, which are both CSDL Node objects. While CSDL code is written in a similar way to regular python code, CSDL code is compiled to a CSDL Graph object by the Recorder class, that can be optimized and executed efficiently. This means that operations are not executed immediately, and variables may not have a set value until the graph is executed. However, the Recorder class provides a way to execute CSDL code inline, which can be useful for debugging and testing. Inline values can be accessed by the value attribute of the variable.

For example, the following code snippet

recorder = Recorder()
recorder.start()
x = csdl.Variable((1,))
y = x * 2
z = y*x
recorder.stop()

becomes the following graph represented in the Recorder:

dag

Creating a variable via csdl.Variable() simultaneously creates a node in the graph, and performing operations on variables creates Operation nodes, in addition to creating nodes for output variables and any non-variable inputs. Additionally, edges are created between nodes to represent the flow of data through the graph. Note that the variable objects that exist in code you write and the variable nodes in the graph are on in the same.

CSDL graphs are directed acyclic graphs (DAGs), meaning that they have no cycles and data flows in one direction. This allows for efficient optimization and execution of the graph. Additionally, the graph is bipartite, meaning that nodes can be divided into two sets, variables and operations, and edges only connect nodes from different sets. While implicit relationships may exist within your model, they must be resolved into explicit relationships in the graph.

1.2. Subgraphs

To simplify the graph, CSDL collapses parts of the graph into single operation nodes, which themselves contain a graph. For example, a subtraction operation is represented by a single node in the graph, which itself contains a graph with a negation and an addition operation. This allows for more efficient optimization and execution of the graph. The Recorder keeps track of the subgraphs via a tree structure, where each node represents a subgraph.

supop

1.3. Variables

Variables represent values in CSDL, and are generally n-dimensional arrays. While a variable may not have a specific value until the graph is executed, they always have a fixed shape. Additionally, variables are immutable, meaning they can be the output of at most one operation.

1.4. Operations

Operations represent mathematical operations in CSDL, and are generally functions that take one or more variables as input and return one or more variables as output. While operation objects are added to the graph just like variables, you do not generally interact with the operation objects directly. Instead, CSDL provides functions that create operation objects and add them to the graph, returning the Variable outputs. CSDL provides a wide range of operations, including basic arithmetic operations, linear algebra operations, and activation functions. Additionally, users can define custom operations if needed.