pub struct Graph { /* private fields */ }
Expand description
A structure that stores a pointer to a computation graph, where every node corresponds to an operation.
§Rust crates
Clone trait duplicates the pointer, not the underlying graph.
PartialEq trait compares pointers, not the related graphs.
§Example
let c = create_context().unwrap();
let g1 = c.create_graph().unwrap();
let g2 = c.create_graph().unwrap();
assert_ne!(g1, g2);
let g3 = g1.clone();
assert_eq!(g1, g3);
Implementations§
Source§impl Graph
Public methods which supposed to be imported in Python.
impl Graph
Public methods which supposed to be imported in Python.
Sourcepub fn set_as_main(&self) -> Result<Graph>
pub fn set_as_main(&self) -> Result<Graph>
Applies Context::set_main_graph to the parent context and this
graph. Returns the clone of this
.
§Returns
This graph
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], INT32);
let n = g.input(t).unwrap();
n.set_as_output().unwrap();
g.finalize().unwrap();
g.set_as_main().unwrap();
Sourcepub fn set_name(&self, name: &str) -> Result<Graph>
pub fn set_name(&self, name: &str) -> Result<Graph>
Applies Context::set_graph_name to the parent context and this
graph. Returns the clone of this
.
§Arguments
name
- name of the graph
§Returns
This graph
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
g.set_name("relu").unwrap();
Sourcepub fn get_name(&self) -> Result<String>
pub fn get_name(&self) -> Result<String>
Applies Context::get_graph_name to the parent context and this
graph.
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
g.set_name("relu").unwrap();
assert_eq!(g.get_name().unwrap(), "relu".to_owned());
Sourcepub fn retrieve_node(&self, name: &str) -> Result<Node>
pub fn retrieve_node(&self, name: &str) -> Result<Node>
Applies Context::retrieve_node to the parent context and this
graph.
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let n = g.input(scalar_type(BIT)).unwrap();
n.set_name("input_node").unwrap();
assert!(n == g.retrieve_node("input_node").unwrap());
Sourcepub fn input(&self, input_type: Type) -> Result<Node>
pub fn input(&self, input_type: Type) -> Result<Node>
Adds an input node to the graph and returns it.
During evaluation, input nodes require values to be supplied.
§Arguments
input_type
- type of a new input node
§Returns
New input node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = scalar_type(BIT);
let n = g.input(t).unwrap();
Sourcepub fn zeros(&self, t: Type) -> Result<Node>
pub fn zeros(&self, t: Type) -> Result<Node>
Adds an node with zeros of given type.
Compared to constant
this node does produce a big value array in serialized graph.
§Arguments
t
- node type
§Returns
New node with zeros of given type.
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let z = g.zeros(array_type(vec![10, 20], UINT8)).unwrap();
Sourcepub fn ones(&self, t: Type) -> Result<Node>
pub fn ones(&self, t: Type) -> Result<Node>
Adds an node with ones of given type.
Compared to constant
this node does produce a big value array in serialized graph.
§Arguments
t
- node type
§Returns
New node with ones of given type.
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let z = g.ones(array_type(vec![10, 20], UINT8)).unwrap();
Sourcepub fn add(&self, a: Node, b: Node) -> Result<Node>
pub fn add(&self, a: Node, b: Node) -> Result<Node>
Adds a node that sums two arrays or scalars of the same scalar type elementwise.
If input shapes are different, the broadcasting rules are applied (see the NumPy broadcasting rules). For example, adding two arrays of shapes [10,1,7]
and [8,1]
results in an array of shape [10,8,7]
.
§Arguments
a
- node containing the first term (array or scalar)b
- node containing the second term (array or scalar)
§Returns
New addition node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = scalar_type(BIT);
let n1 = g.input(t.clone()).unwrap();
let n2 = g.input(t).unwrap();
let n3 = g.add(n1, n2).unwrap();
Sourcepub fn subtract(&self, a: Node, b: Node) -> Result<Node>
pub fn subtract(&self, a: Node, b: Node) -> Result<Node>
Adds a node that subtracts two arrays or scalars of the same scalar type elementwise.
If input shapes are different, the broadcasting rules are applied (see the NumPy broadcasting rules). For example, subtracting two arrays of shapes [10,1,7]
and [8,1]
results in an array of shape [10,8,7]
.
§Arguments
a
- node containing the minuend (array or scalar)b
- node containing the subtrahend (array or scalar)
§Returns
New subtraction node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = scalar_type(BIT);
let n1 = g.input(t.clone()).unwrap();
let n2 = g.input(t).unwrap();
let n3 = g.subtract(n1, n2).unwrap();
Sourcepub fn multiply(&self, a: Node, b: Node) -> Result<Node>
pub fn multiply(&self, a: Node, b: Node) -> Result<Node>
Adds a node that multiplies two arrays or scalars of the same scalar type elementwise.
If input shapes are different, the broadcasting rules are applied (see the NumPy broadcasting rules). For example, multiplication of two arrays of shapes [10,1,7]
and [8,1]
results in an array of shape [10,8,7]
.
§Arguments
a
- node containing the first factor (array or scalar)b
- node containing the second factor (array or scalar)
§Returns
New multiplication node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = scalar_type(BIT);
let n1 = g.input(t.clone()).unwrap();
let n2 = g.input(t).unwrap();
let n3 = g.multiply(n1, n2).unwrap();
Sourcepub fn mixed_multiply(&self, a: Node, b: Node) -> Result<Node>
pub fn mixed_multiply(&self, a: Node, b: Node) -> Result<Node>
Adds a node that multiplies an integer array or scalar by a binary array or scalar elementwise. For each integer element, this operation returns this element or zero depending on the corresponding bit element.
If input shapes are different, the broadcasting rules are applied (see the NumPy broadcasting rules). For example, multiplication of two arrays of shapes [10,1,7]
and [8,1]
results in an array of shape [10,8,7]
.
§Arguments
a
- node containing an integer array or scalarb
- node containing a binary array or scalar
§Returns
New mixed multiplication node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = scalar_type(INT32);
let t2 = scalar_type(BIT);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.mixed_multiply(n1, n2).unwrap();
Sourcepub fn dot(&self, a: Node, b: Node) -> Result<Node>
pub fn dot(&self, a: Node, b: Node) -> Result<Node>
Adds a node that computes the dot product according to the NumPy rules:
- if both factors are 1-dimensional arrays, return their inner product;
- if both factors are 2-dimensional arrays, return their matrix product;
- if one of the factors is scalar, return the result of multiply;
- if the first factor is n-dimensional and the second one is 1-dimensional, compute the elementwise multiplication and return the sum over the last axis.
- if both factors are n-dimensional (n>2), return the sum product over the last axis of the first factor and the second-to-last axis of the second factor, i.e.
dot(A, B)[i,j,k,m] = sum(A[i,j,:] * B[k,:,m])
(in the NumPy notation).
§Arguments
a
- node containing the first factor (array or scalar)b
- node containing the second factor (array or scalar)
§Returns
New dot product node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![10], INT32);
let n1 = g.input(t.clone()).unwrap();
let n2 = g.input(t).unwrap();
let n3 = g.dot(n1, n2).unwrap();
Sourcepub fn matmul(&self, a: Node, b: Node) -> Result<Node>
pub fn matmul(&self, a: Node, b: Node) -> Result<Node>
Adds a node that computes the matrix product of two arrays according to the NumPy rules.
Each array is represented as an array of 2-dimensional matrix elements and this node returns the elementwise product of such matrix arrays.
§Arguments
a
- node containing the first arrayb
- node containing the second array
§Returns
New matrix product node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = array_type(vec![2, 3], INT32);
let t2 = array_type(vec![3, 2], INT32);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.matmul(n1, n2).unwrap();
Sourcepub fn join(
&self,
a: Node,
b: Node,
t: JoinType,
headers: HashMap<String, String>,
) -> Result<Node>
pub fn join( &self, a: Node, b: Node, t: JoinType, headers: HashMap<String, String>, ) -> Result<Node>
Adds a node that computes a join of a given type on two named tuples along given key headers.
Each tuple should consist of arrays having the same number of rows, i.e. the first dimensions of these arrays should be equal.
In addition, each named tuple should have a binary array named with NULL_HEADER that contains zeros in rows void of content; otherwise, it contains ones. This column is called the null column.
Let row key
be the bitstring obtained by concatenating data elements for given key headers.
WARNING: Rows must have unique row keys, except for rows where NULL_HEADER is zero: those rows are ignored.
This operation returns:
- Inner join: a named tuple containing rows where input tuples have matching row keys.
- Left join: a named tuple containing all the rows of the first input tuple merged with the rows of the second input tuple having same row keys.
- Union join: a named tuple containing rows of the first input tuple that are not in the inner join and all the rows of the second tuple. In contrast to the SQL union, this operation does not require that input datasets have respective columns of the same type. This means that columns of both datasets are included and filled with zeros where no data can be retrieved. Namely, the rows of the second set in the union join will contain zeros in non-key columns of the first set and vice versa.
- Full join: a named tuple containing all the rows of input tuples. If the row key of a row of the first set match with the row key of a row of the second set, they are merged into one. The order of rows goes as follows:
- the rows of the first set that don’t belong to the inner join.
- all the rows of the second set including those merged with the rows of the first set as in inner join.
In this form, full join is computed as
union_join(a, left_join(b, a))
.
§Arguments
a
- node containing the first named tupleb
- node containing the second named tuplet
- join type (Inner/Left/Union/Full)headers
- headers of columns along which the join is performed
§Returns
New join node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1n = array_type(vec![100], BIT);
let t11 = array_type(vec![100], INT32);
let t12 = array_type(vec![100, 128], BIT);
let t13 = array_type(vec![100], INT64);
let t2n = array_type(vec![50], BIT);
let t21 = array_type(vec![50], INT32);
let t22 = array_type(vec![50, 128], BIT);
let t23 = array_type(vec![50], UINT8);
let t1 = named_tuple_type(vec![
(NULL_HEADER.to_owned(), t1n),
("ID".to_owned(), t11),
("Occupation".to_owned(), t12),
("Revenue".to_owned(), t13),
]);
let t2 = named_tuple_type(vec![
(NULL_HEADER.to_owned(), t2n),
("ID".to_owned(), t21),
("Job".to_owned(), t22),
("Age".to_owned(), t23),
]);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.join(n1, n2, JoinType::Inner, HashMap::from([
("ID".to_owned(), "ID".to_owned()),
("Occupation".to_owned(), "Job".to_owned()),
])).unwrap();
Sourcepub fn join_with_column_masks(
&self,
a: Node,
b: Node,
t: JoinType,
headers: HashMap<String, String>,
) -> Result<Node>
pub fn join_with_column_masks( &self, a: Node, b: Node, t: JoinType, headers: HashMap<String, String>, ) -> Result<Node>
Adds a node that computes a join of a given type on two named tuples along given key headers.
Each tuple should consist of pairs of arrays having the same number of rows, i.e. the first dimensions of these arrays should be equal. Each pair has a binary array that contains zeros in rows where the data array has no content and an array with data.
In addition, each named tuple should have a binary array named with NULL_HEADER that contains zeros in rows void of content; otherwise, it contains ones. This column is called the null column.
Let row key
be the bitstring obtained by concatenating data elements for given key headers where all the corresponding mask elements are set to one.
WARNING: Rows must have unique row keys, except for rows where NULL_HEADER is zero or at least one mask element in given key headers is zero.
Rows with zero NULL_HEADER are ignored.
We assume that rows with zero mask elements don’t match with other rows.
Thus, they can’t show up in inner and left joins, but can be copied over to the result of union or full joins.
This operation returns:
- Inner join: a named tuple containing rows where input tuples have matching row keys.
- Left join: a named tuple containing all the rows of the first input tuple merged with the rows of the second input tuple having same row keys.
- Union join: a named tuple containing rows of the first input tuple that are not in the inner join and all the rows of the second tuple. In contrast to the SQL union, this operation does not require that input datasets have respective columns of the same type. This means that columns of both datasets are included and filled with zeros where no data can be retrieved. Namely, the rows of the second set in the union join will contain zeros in non-key columns of the first set and vice versa.
- Full join: a named tuple containing all the rows of input tuples. If the row key of a row of the first set match with the row key of a row of the second set, they are merged into one. The order of rows goes as follows:
- the rows of the first set that don’t belong to the inner join.
- all the rows of the second set including those merged with the rows of the first set as in inner join.
In this form, full join is computed as
union_join(a, left_join(b, a))
.
§Arguments
a
- node containing the first named tupleb
- node containing the second named tuplet
- join type (Inner/Left/Union/Full)headers
- headers of columns along which the join is performed
§Returns
New join node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1n = array_type(vec![100], BIT);
let t11 = tuple_type(vec![array_type(vec![100], BIT), array_type(vec![100], INT32)]);
let t12 = tuple_type(vec![array_type(vec![100], BIT), array_type(vec![100, 128], BIT)]);
let t13 = tuple_type(vec![array_type(vec![100], BIT), array_type(vec![100], INT64)]);
let t2n = array_type(vec![50], BIT);
let t21 = tuple_type(vec![array_type(vec![50], BIT), array_type(vec![50], INT32)]);
let t22 = tuple_type(vec![array_type(vec![50], BIT), array_type(vec![50, 128], BIT)]);
let t23 = tuple_type(vec![array_type(vec![50], BIT), array_type(vec![50], UINT8)]);
let t1 = named_tuple_type(vec![
(NULL_HEADER.to_owned(), t1n),
("ID".to_owned(), t11),
("Occupation".to_owned(), t12),
("Revenue".to_owned(), t13),
]);
let t2 = named_tuple_type(vec![
(NULL_HEADER.to_owned(), t2n),
("ID".to_owned(), t21),
("Job".to_owned(), t22),
("Age".to_owned(), t23),
]);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.join_with_column_masks(n1, n2, JoinType::Inner, HashMap::from([
("ID".to_owned(), "ID".to_owned()),
("Occupation".to_owned(), "Job".to_owned()),
])).unwrap();
Sourcepub fn sort(&self, a: Node, key: String) -> Result<Node>
pub fn sort(&self, a: Node, key: String) -> Result<Node>
Adds a node that sorts a table given as named tuple according to the column given by the key argument. The key column must be a 2-d BIT array of shape [n, b], interpreted as bitstrings of length b. Other columns in the named tuple must be arrays of arbitrary type and shape, as long as they share the first dimension: [n, …]. Bitstrings are sorted lexicographically, and the sorting algorithm is stable: preserving relative order of entries in other arrays where the corresponding key entries match.
§Arguments
a
- node containing a named tuple – arrays to sort.key
- name of the field to sort on it, this array must be 2-d of type BIT.
§Returns
New sorted node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let v1 = g.input(array_type(vec![20], INT32)).unwrap();
let v2 = g.input(array_type(vec![20, 10, 2], UINT64)).unwrap();
let k = g.input(array_type(vec![20, 32], BIT)).unwrap();
let a = g.create_named_tuple(vec![("key".to_string(), k), ("value1".to_string(), v1), ("value2".to_string(), v2)]).unwrap();
let a = g.sort(a, "key".to_string()).unwrap();
Sourcepub fn truncate(&self, a: Node, scale: u128) -> Result<Node>
pub fn truncate(&self, a: Node, scale: u128) -> Result<Node>
Adds a node that divides a scalar or each entry of an array by a positive constant integer scale
.
§Arguments
a
- node containing a scalar or an arrayscale
- positive integer
§Returns
New truncate node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![2, 3], INT32);
let n1 = g.input(t).unwrap();
let n2 = g.truncate(n1, 4).unwrap();
Sourcepub fn sum(&self, a: Node, axes: ArrayShape) -> Result<Node>
pub fn sum(&self, a: Node, axes: ArrayShape) -> Result<Node>
Adds a node that computes the sum of entries of an array along given axes (see numpy.sum).
For example, summing the array [[1000, 200], [30, 4]]
along the first or the second axes results in the arrays [1030,204]
or [1200,34]
, respectively. Summing along both axes yields 1234
.
§Arguments
a
- node containing an arrayaxes
- indices of the axes ofa
§Returns
New sum node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let axes = vec![1, 0];
let n1 = g.input(t).unwrap();
let n2 = g.sum(n1, axes).unwrap();
Sourcepub fn cum_sum(&self, a: Node, axis: u64) -> Result<Node>
pub fn cum_sum(&self, a: Node, axis: u64) -> Result<Node>
Adds a node that computes the cumulative sum of elements along a given axis. (see numpy.cumsum).
For example, summing the array [[1000, 200], [30, 4]]
along the first or the second axes results in the arrays [[1000, 200], [1030, 204]]
or [[1000, 1200], [30, 34]]
, respectively.
§Arguments
a
- node containing an arrayaxis
- axis along which the cumulative sum is computed
§Returns
New cumulative sum node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], INT32);
let n1 = g.input(t).unwrap();
let n2 = g.cum_sum(n1, 1).unwrap();
Sourcepub fn permute_axes(&self, a: Node, axes: ArrayShape) -> Result<Node>
pub fn permute_axes(&self, a: Node, axes: ArrayShape) -> Result<Node>
Adds a node that permutes an array along given axes (see numpy.transpose). This function generalizes matrix transposition.
For example, permutation of an array of shape [a,b,c]
with permutation [2,0,1]
results in an array of shape [c,a,b]
.
§Arguments
a
- node containing an arrayaxes
- indices of the axes ofa
§Returns
New node with permuted axes
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let axes = vec![1, 0, 2];
let n1 = g.input(t).unwrap();
let n2 = g.permute_axes(n1, axes).unwrap();
Sourcepub fn get(&self, a: Node, index: ArrayShape) -> Result<Node>
pub fn get(&self, a: Node, index: ArrayShape) -> Result<Node>
Adds a node that extracts a sub-array with a given index. This is a special case of get_slice and corresponds to single element indexing as in NumPy.
For example, given an array A
of shape [a,b,c,d]
, its subarray B
of shape [c,d]
with index [i,j]
can be extracted as follows
B = A[i,j,:,:]
(in the NumPy notation)
§Arguments
a
- node containing an arrayindex
- index of a sub-array
§Returns
New node containing an extracted sub-array
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let index = vec![2];
let n1 = g.input(t).unwrap();
let n2 = g.get(n1, index).unwrap();
Sourcepub fn get_slice(&self, a: Node, slice: Slice) -> Result<Node>
pub fn get_slice(&self, a: Node, slice: Slice) -> Result<Node>
Adds a node that extracts a sub-array corresponding to a given slice.
Our slicing conventions follow the NumPy rules.
For example, given an array A
of shape [a,b]
, its subarray B
containing only the last 3 rows of A
can be extracted as follows
get_slice(A, [-3::])[i,j] = A[a-3+i,j]
.
Slices are defined as vectors of SliceElements that have 3 possible types:
- SingleIndex(
i64
) is used to extract all the elements with a given index in a respective dimension, - SubArray(
Option<i64>, Option<i64>, Option<i64>
) describes the range of indices that should be extracted over a certain dimension (similar to thea:b:c
notation in NumPy) - Ellipsis describes several consecutive dimensions that must be extracted in full, e.g. the slice
[i,...,j]
can be used to extract all the elements with the indexi
in the first dimension and the indexj
in the last one, while the indices of all the other dimensions have no constraints. See the NumPy slicing for more details.
§Arguments
a
- node containing an arrayslice
- array slice
§Returns
New node containing an extracted sub-array
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let slice = vec![SliceElement::Ellipsis, SliceElement::SubArray(None, None, Some(-2))];
let n1 = g.input(t).unwrap();
let n2 = g.get_slice(n1, slice).unwrap();
Sourcepub fn reshape(&self, a: Node, new_type: Type) -> Result<Node>
pub fn reshape(&self, a: Node, new_type: Type) -> Result<Node>
Adds a node that reshapes a value to a given compatible type (similar to numpy.reshape, but more general). Specifically,
- if the input value is an array, it can be reshaped to any array with the same number of elements;
- if the input value in the flattened form contains
n
arrays or scalars, it can be reshaped to any type with the same number of arrays and scalars. Each array can be reshaped as in the above rule.
For example, an array of shape [3,10,5]
can be reshaped to [2,75]
. A tuple with arrays of shapes [3,4]
, [12]
, [2,6]
can be reshaped to a vector with 3 array elements of shape [2,2,3]
.
§Arguments
a
- node containing a valuenew_type
- type
§Returns
New node with a reshaped value
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let old_t = array_type(vec![3, 2, 3], INT32);
let new_t = array_type(vec![3,6], INT32);
let n1 = g.input(old_t).unwrap();
let n2 = g.reshape(n1, new_t).unwrap();
Sourcepub fn stack(&self, nodes: Vec<Node>, outer_shape: ArrayShape) -> Result<Node>
pub fn stack(&self, nodes: Vec<Node>, outer_shape: ArrayShape) -> Result<Node>
Adds a node that joins a sequence of arrays governed by a given shape.
The input arrays should have the same shape or be able to be broadcast to the same shape.
For example, stacking 2 arrays of shapes [2,2]
and [2,1]
with the outer shape [2]
works as follows
stack(arrays=[[[1,2],[3,4]], [5,6]], shape=[2]) = [[[1,2],[3,4]], [[5,5], [6,6]]]
§Arguments
nodes
- vector of nodes containing arraysouter_shape
- shape defining how the input arrays are arranged in the resulting array
§Returns
New stack node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = array_type(vec![3, 2, 3], INT32);
let t2 = array_type(vec![2, 3], INT32);
let shape = vec![2];
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.stack(vec![n1,n2], shape).unwrap();
Sourcepub fn concatenate(&self, nodes: Vec<Node>, axis: u64) -> Result<Node>
pub fn concatenate(&self, nodes: Vec<Node>, axis: u64) -> Result<Node>
Adds a node that joins a sequence of arrays along a given axis. This operation is similar to the NumPy concatenate.
The input arrays should have the same shape except in the given axis.
§Arguments
nodes
- vector of nodes containing arraysaxis
- axis along which the above arrays are joined
§Returns
New Concatenate node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = array_type(vec![3, 2, 3], INT32);
let t2 = array_type(vec![3, 2, 10], INT32);
let shape = vec![2];
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.concatenate(vec![n1,n2], 2).unwrap();
Sourcepub fn constant(&self, output_type: Type, value: Value) -> Result<Node>
pub fn constant(&self, output_type: Type, value: Value) -> Result<Node>
Adds a node creating a constant of a given type and value.
§Arguments
output_type
- type of a constantvalue
- value of a constant
§Returns
New constant node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = scalar_type(BIT);
let v = Value::from_scalar(0, BIT).unwrap();
let n = g.constant(t, v).unwrap();
Sourcepub fn a2b(&self, a: Node) -> Result<Node>
pub fn a2b(&self, a: Node) -> Result<Node>
Adds a node converting an integer array or scalar to the binary form.
Given an array of shape [a,b,c]
and scalar type st
, this node returns an array of shape [a,b,c,s]
where s
is the bit size of st
. For example, an array of shape [1,2,3]
with INT32
entries will be converted to a binary array of shape [1,2,3,32]
.
§Arguments
a
- node containing an array or scalar
§Returns
New node converting an array/scalar to the binary form
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], INT32);
let n1 = g.input(t).unwrap();
let n2 = g.a2b(n1).unwrap();
Sourcepub fn b2a(&self, a: Node, scalar_type: ScalarType) -> Result<Node>
pub fn b2a(&self, a: Node, scalar_type: ScalarType) -> Result<Node>
Adds a node converting a binary array to an array of a given scalar type.
Given a binary array of shape [a,b,c]
and a scalar type st
of bit size c
, this node returns an array of shape [a,b]
with st
entries. For example, a binary array of shape [2,3,32]
can be converted to an array of shape [2,3]
with INT32
entries.
§Arguments
a
- node containing an array or scalarscalar_type
- scalar type
§Returns
New node converting an array from the binary form
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 32], BIT);
let n1 = g.input(t).unwrap();
let n2 = g.b2a(n1, INT32).unwrap();
Sourcepub fn create_tuple(&self, elements: Vec<Node>) -> Result<Node>
pub fn create_tuple(&self, elements: Vec<Node>) -> Result<Node>
Adds a node that creates a tuple from several (possibly, zero) elements.
§Arguments
elements
- vector of nodes
§Returns
New node with a tuple
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = array_type(vec![3, 2, 3], INT32);
let t2 = array_type(vec![2, 3], INT32);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.create_tuple(vec![n1,n2]).unwrap();
Sourcepub fn create_vector(
&self,
element_type: Type,
elements: Vec<Node>,
) -> Result<Node>
pub fn create_vector( &self, element_type: Type, elements: Vec<Node>, ) -> Result<Node>
Adds a node that creates a vector from several (possibly, zero) elements of the same type.
§Arguments
elements
- vector of nodes
§Returns
New node with a created vector
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let n1 = g.input(t.clone()).unwrap();
let n2 = g.input(t.clone()).unwrap();
let n3 = g.create_vector(t, vec![n1,n2]).unwrap();
Sourcepub fn create_named_tuple(&self, elements: Vec<(String, Node)>) -> Result<Node>
pub fn create_named_tuple(&self, elements: Vec<(String, Node)>) -> Result<Node>
Adds a node that creates a named tuple from several (possibly, zero) elements.
§Arguments
elements
- vector of pairs (node name, node)
§Returns
New node creating a named tuple
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = array_type(vec![3, 2, 3], INT32);
let t2 = array_type(vec![2, 3], INT32);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.create_named_tuple(vec![("node1".to_owned(), n1), ("node2".to_owned(), n2)]).unwrap();
Sourcepub fn tuple_get(&self, tuple: Node, index: u64) -> Result<Node>
pub fn tuple_get(&self, tuple: Node, index: u64) -> Result<Node>
Adds a node that extracts an element of a tuple.
§Arguments
tuple
- node containing a tupleindex
- index of a tuple element between 0 and tuple length minus 1
§Returns
New node with an extracted element
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = array_type(vec![3, 2, 3], INT32);
let t2 = array_type(vec![2, 3], INT32);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.create_tuple(vec![n1, n2]).unwrap();
let n4 = g.tuple_get(n3, 1).unwrap();
Sourcepub fn named_tuple_get(&self, tuple: Node, key: String) -> Result<Node>
pub fn named_tuple_get(&self, tuple: Node, key: String) -> Result<Node>
Adds a node that extracts an element of a named tuple.
§Arguments
tuple
- node containing a named tuplekey
- key of a tuple element
§Returns
New node extracting a tuple element
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t1 = array_type(vec![3, 2, 3], INT32);
let t2 = array_type(vec![2, 3], INT32);
let n1 = g.input(t1).unwrap();
let n2 = g.input(t2).unwrap();
let n3 = g.create_named_tuple(vec![("node1".to_owned(), n1), ("node2".to_owned(), n2)]).unwrap();
let n4 = g.named_tuple_get(n3, "node2".to_owned()).unwrap();
Sourcepub fn vector_get(&self, vec: Node, index: Node) -> Result<Node>
pub fn vector_get(&self, vec: Node, index: Node) -> Result<Node>
Adds a node that extracts an element of a vector.
§Arguments
vec
- node containing a vectorindex
- node containing the index of a tuple element
§Returns
New node extracting a vector element
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let n1 = g.input(t.clone()).unwrap();
let n2 = g.input(t.clone()).unwrap();
let n3 = g.create_vector(t, vec![n1,n2]).unwrap();
let index = g.constant(scalar_type(UINT32), Value::from_scalar(0, UINT32).unwrap()).unwrap();
let n4 = g.vector_get(n3, index).unwrap();
Sourcepub fn zip(&self, nodes: Vec<Node>) -> Result<Node>
pub fn zip(&self, nodes: Vec<Node>) -> Result<Node>
Adds a node that takes vectors V1(n, t1), V2(n, t2), …, Vk(n, tk) of the same length and returns a vector V(n, tuple(t1, …, tk)) (similar to zip).
§Arguments
nodes
- vector of nodes containing input vectors
§Returns
New zip node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let vec_t = vector_type(3, t);
let n1 = g.input(vec_t.clone()).unwrap();
let n2 = g.input(vec_t.clone()).unwrap();
let n3 = g.zip(vec![n1,n2]).unwrap();
Sourcepub fn repeat(&self, a: Node, n: u64) -> Result<Node>
pub fn repeat(&self, a: Node, n: u64) -> Result<Node>
Adds a node that creates a vector with n
copies of a value of a given node.
§Arguments
a
- node containing a valuen
- number of copies
§Returns
New repeat node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let n1 = g.input(t).unwrap();
let n2 = g.repeat(n1, 10).unwrap();
Sourcepub fn call(&self, graph: Graph, arguments: Vec<Node>) -> Result<Node>
pub fn call(&self, graph: Graph, arguments: Vec<Node>) -> Result<Node>
Adds a node that calls another graph with inputs contained in given nodes.
The input graph must be finalized and have as many inputs as the number of provided arguments.
For example, let G
be a graph implementing the function max(x,0)
, then call(G, [17]) = max(17, 0)
.
§Arguments
graph
- graph withn
input nodesarguments
- vector ofn
nodes
§Returns
New call node
§Example
let c = create_context().unwrap();
let g1 = c.create_graph().unwrap();
let t = array_type(vec![3, 2, 3], INT32);
let n1 = g1.input(t.clone()).unwrap();
let n2 = g1.repeat(n1, 10).unwrap();
let n3 = g1.vector_to_array(n2).unwrap();
n3.set_as_output().unwrap();
g1.finalize().unwrap();
let g2 = c.create_graph().unwrap();
let n4 = g2.input(t).unwrap();
let n5 = g2.add(n4.clone(), n4).unwrap();
let n6 = g2.call(g1, vec![n5]).unwrap();
Sourcepub fn iterate(&self, graph: Graph, state: Node, input: Node) -> Result<Node>
pub fn iterate(&self, graph: Graph, state: Node, input: Node) -> Result<Node>
Adds a node that iteratively computes a given finalized graph on the elements of a given vector and updates the state value accordingly.
This node calls another graph
with 2 input nodes old_state
and input
and an output node that returns a tuple (new_state, output)
. This graph is used to map the elements of a given vector V
to another vector W
as follows:
graph(state_0, V[0]) -> (state1, W[0]),
graph(state_1, V[1]) -> (state2, W[1]),
...
graph(state_k, V[k]) -> (final_state, W[k]).
The output is a tuple (final_state, W)
. The initial state state_0
should be provided as an argument.
This node generalize map
and reduce
procedures (see MapReduce for more details).
For example, let G
be a graph implementing the function max(x,0)
and incrementing state
if its output is negative, then iterate(G, 0, [-1,2,0,3,2]) = (1, [0,2,0,3,2])
. The final state is equal to the number of negative values in the input vector.
§Arguments
graph
- graph with 2 input nodes of types Ts and Ti and returning a tuple of type (Ts, To)state
- node containing an initial state of type Tsinput
- node containing a vector with elements of type Ti
§Returns
New iterate node
§Example
let c = create_context().unwrap();
let t_s = scalar_type(BIT);
let t = scalar_type(INT32);
let vec_t = vector_type(10, t.clone());
// Graph that outputs 0 at even indices or input value at odd indices.
let g1 = c.create_graph().unwrap();
{
let old_state = g1.input(t_s.clone()).unwrap();
let input = g1.input(t.clone()).unwrap();
let result = g1.mixed_multiply(input, old_state.clone()).unwrap();
let new_state = g1.add(old_state, constant_scalar(&g1, 1, BIT).unwrap()).unwrap();
let out_tuple = g1.create_tuple(vec![new_state, result]).unwrap();
out_tuple.set_as_output().unwrap();
g1.finalize().unwrap();
}
let g2 = c.create_graph().unwrap();
let initial_state = constant_scalar(&g2, 0, BIT).unwrap();
let input_vector = g2.input(vec_t).unwrap();
g2.iterate(g1, initial_state, input_vector).unwrap();
Sourcepub fn array_to_vector(&self, a: Node) -> Result<Node>
pub fn array_to_vector(&self, a: Node) -> Result<Node>
Adds a node converting an array to a vector.
Given an array of shape [a,b,c]
, this node returns a vector of a
arrays of shape [b,c]
.
§Arguments
a
- node containing an array
§Returns
New node converting an array to a vector
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![4, 3, 2], INT32);
let n1 = g.input(t).unwrap();
let n2 = g.array_to_vector(n1).unwrap();
let index = g.constant(scalar_type(UINT32), Value::from_scalar(0, UINT32).unwrap()).unwrap();
let n3 = g.vector_get(n2.clone(), index).unwrap();
assert!(n2.get_type().unwrap().is_vector());
assert_eq!(n3.get_type().unwrap().get_shape(), vec![3,2]);
Sourcepub fn vector_to_array(&self, a: Node) -> Result<Node>
pub fn vector_to_array(&self, a: Node) -> Result<Node>
Adds a node converting a vector to an array.
Given a vector of a
arrays of shape [b,c]
, this node returns an array of shape [a,b,c]
.
§Arguments
a
- node containing a vector
§Returns
New node converting a vector to an array
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], INT32);
let vec_t = vector_type(4, t);
let n1 = g.input(vec_t).unwrap();
let n2 = g.vector_to_array(n1).unwrap();
assert!(n2.get_type().unwrap().is_array());
assert_eq!(n2.get_type().unwrap().get_shape(), vec![4, 3, 2]);
Sourcepub fn finalize(&self) -> Result<Graph>
pub fn finalize(&self) -> Result<Graph>
Checks that the graph has an output node and finalizes the graph.
After finalization the graph can’t be changed.
§Returns
Finalized graph
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], INT32);
let vec_t = vector_type(4, t);
let n1 = g.input(vec_t).unwrap();
let n2 = g.vector_to_array(n1).unwrap();
n2.set_as_output().unwrap();
g.finalize().unwrap();
Sourcepub fn get_nodes(&self) -> Vec<Node>
pub fn get_nodes(&self) -> Vec<Node>
Returns the vector of nodes contained in the graph in order of construction.
§Returns
Vector of nodes of the graph
Sourcepub fn set_output_node(&self, output_node: Node) -> Result<()>
pub fn set_output_node(&self, output_node: Node) -> Result<()>
Promotes a given node to the output node of the parent graph.
§Arguments
output_node
- node to be set as output
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], INT32);
let vec_t = vector_type(4, t);
let n1 = g.input(vec_t).unwrap();
let n2 = g.vector_to_array(n1).unwrap();
g.set_output_node(n2).unwrap();
g.finalize().unwrap();
Sourcepub fn get_output_node(&self) -> Result<Node>
pub fn get_output_node(&self) -> Result<Node>
Sourcepub fn get_id(&self) -> u64
pub fn get_id(&self) -> u64
Returns the ID of the graph.
A graph ID is a serial number of a graph between 0
and n-1
where n
is the number of graphs in the parent context.
§Returns
Graph ID
Sourcepub fn get_num_nodes(&self) -> u64
pub fn get_num_nodes(&self) -> u64
Sourcepub fn get_node_by_id(&self, id: u64) -> Result<Node>
pub fn get_node_by_id(&self, id: u64) -> Result<Node>
Sourcepub fn get_context(&self) -> Context
pub fn get_context(&self) -> Context
Sourcepub fn custom_op(
&self,
op: CustomOperation,
arguments: Vec<Node>,
) -> Result<Node>
pub fn custom_op( &self, op: CustomOperation, arguments: Vec<Node>, ) -> Result<Node>
Adds a node computing a given custom operation.
Custom operations can be created by the user as public structs implementing the CustomOperationBody.
§Arguments
op
- custom operationarguments
- vector of nodes used as input for the custom operation
§Returns
New custom operation node
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], BIT);
let n1 = g.input(t).unwrap();
let n2 = g.custom_op(CustomOperation::new(Not {}), vec![n1]).unwrap();
Sourcepub fn print(&self, message: String, input: Node) -> Result<Node>
pub fn print(&self, message: String, input: Node) -> Result<Node>
Adds a node which logs its input at runtime, and returns the input. This is intended to be used for debugging.
§Arguments
message
- Informational message to be printedinput
- Node to be printed
§Returns
The value of the node.
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = array_type(vec![3, 2], BIT);
let n1 = g.input(t).unwrap();
let n2 = g.print("n1:".into(), n1).unwrap();
Sourcepub fn assert(
&self,
message: String,
condition: Node,
input: Node,
) -> Result<Node>
pub fn assert( &self, message: String, condition: Node, input: Node, ) -> Result<Node>
Adds a node which fails the execution at runtime if condition
is false, and returns the input
otherwise.
This is intended to be used for debugging.
§Arguments
message
- message to be returned for the failed assertion.condition
- BIT to be checked in the assertion.input
- Node to be returned for pass-through.
§Returns
The value of the node.
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let cond = g.input(scalar_type(BIT)).unwrap();
let t = array_type(vec![3, 2], BIT);
let n1 = g.input(t).unwrap();
let n2 = g.assert("Condition".into(), cond, n1).unwrap();
Source§impl Graph
Methods which aren’t supposed to be imported in Python.
impl Graph
Methods which aren’t supposed to be imported in Python.
Sourcepub fn add_node(
&self,
node_dependencies: Vec<Node>,
graph_dependencies: Vec<Graph>,
operation: Operation,
) -> Result<Node>
pub fn add_node( &self, node_dependencies: Vec<Node>, graph_dependencies: Vec<Graph>, operation: Operation, ) -> Result<Node>
Adds an operation node to the graph and returns it.
§Arguments
node_dependencies
- vector of nodes necessary to perform the given operationgraph_dependencies
- vector of graphs necessary to perform the given operationoperation
- operation performed by the node
§Returns
New operation node that gets added
pub fn get_annotations(&self) -> Result<Vec<GraphAnnotation>>
Sourcepub fn prepare_input_values<T: Clone>(
&self,
values: HashMap<&str, T>,
) -> Result<Vec<T>>
pub fn prepare_input_values<T: Clone>( &self, values: HashMap<&str, T>, ) -> Result<Vec<T>>
Rearrange given input values according to the names and the order of the related input nodes.
For example, given a graph with the first input node named ‘A’ and the second one named ‘B’ and input values {'B': v, 'A': w}
, this function returns a vector [w, v]
.
§Arguments
values
- hashmap of values keyed by node names
§Returns
Vector of values arranged by node names
§Example
let c = create_context().unwrap();
let g = c.create_graph().unwrap();
let t = scalar_type(BIT);
let n1 = g.input(t.clone()).unwrap();
n1.set_name("input1").unwrap();
let n2 = g.input(t.clone()).unwrap();
n2.set_name("input2").unwrap();
let mut input_map = HashMap::new();
input_map.insert("input2", 2);
input_map.insert("input1", 1);
let ordered_input = g.prepare_input_values(input_map).unwrap();
assert_eq!(vec![1,2], ordered_input);
Trait Implementations§
Source§impl Hash for Graph
impl Hash for Graph
impl Eq for Graph
Auto Trait Implementations§
impl Freeze for Graph
impl !RefUnwindSafe for Graph
impl Send for Graph
impl Sync for Graph
impl Unpin for Graph
impl !UnwindSafe for Graph
Blanket Implementations§
Source§impl<T> BorrowMut<T> for Twhere
T: ?Sized,
impl<T> BorrowMut<T> for Twhere
T: ?Sized,
Source§fn borrow_mut(&mut self) -> &mut T
fn borrow_mut(&mut self) -> &mut T
Source§impl<T> CloneToUninit for Twhere
T: Clone,
impl<T> CloneToUninit for Twhere
T: Clone,
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§impl<Q, K> Equivalent<K> for Q
impl<Q, K> Equivalent<K> for Q
Source§fn equivalent(&self, key: &K) -> bool
fn equivalent(&self, key: &K) -> bool
key
and return true
if they are equal.