Tensor network and its contractions¶
This page serves as documentation for our main tensor network contraction engine.
Overview¶
Tensor Valued Objects¶
A tensor is a multi-dimensional array of numbers. The number of dimensions associated to a tensor is called the rank of the tensor. For example, a tensor of rank 0 represent a scalar \(T\). A tensor of rank 1 is a vector \((T_i)_{i=0}^{d-1}\), and a tensor of rank 2 is a matrix \((T_{ij})_{(i,j)\in [d_0]\times [d_1]}\). The dimension corresponds to each of the indices are called bond dimensions associated to the indices.
A tensor network represents a multi-linear map of multiple tensors that results in a new tensor. For example:
The inner product of two vectors \(U, V\) can be expressed as \(T = \sum_i U_i\cdot V_i\).
The outer product of two vectors \(U, V\) can be expressed as \(T_{ij} = U_i\cdot V_j\).
The element-wise product of two vectors \(U, V\) can be expressed as \(T_i = U_i\cdot V_i\).
The matrix product of two matrices \(M, N\) can be expressed as \(T_{ij}=\sum_k U_{ik}\cdot V_{kj}\).
Explicit expressions like above are good for sake of demonstrations, but more complex tensor networks could arise from various scenarios, including many-body physics, machine learning and quantum computation. There are several equivalent ways of expressing a tensor network:
Einstein summation. An einstein summation takes the form [indices_0],[indices_1],…,[indices_k]->[indices_o]. Each term on the left hand side corresponds to the indices configuration of an operand, and the indices on the right hand side corresponds to the indices on the right hand side, also called the open indices. All matching indices are identified with each other, and the closed indices, i.e. the ones that do not appear on the right hand side, are being summed over. The four examples above, expressed in terms of the Einstein summation, are respectively i,i->, i,j->ij, i,i->i, ik,kj->ij. There is a more restrictive interpretation of the einstein summation that each index appears exactly twice in the expression and the right hand side is thus removed. We do not take such convention. Moreover, each edge can appear multiple times on the right hand side, and does not have to appear on the left hand side as long as each index is associated with a definite bond dimension.
Attributed Multi-hypergraph. A tensor network can be expressed as a multi-hypergraph, where each node corresponds to a tensor operand, and each hyperedge an index. This provides a graphical, intuitive representation of a tensor network.
Our package not only supports the definition and manipulation of tensors and tensor networks, but also unary functions acting on a tensor and summation of tensors with the same shape. These extensions help us handle different scenarios where tensors appear naturally in an easier manner.
-
class
acqdp.tensor_network.
TensorValued
(*args, **kwargs)[source]¶ Interface for all
TensorValued
objects, includingTensor
,TensorNetwork
,TensorSum
andTensorView
.- Variables
identifier – unique identifier for each
TensorValued
object.dtype – A
TensorValued
object is homogeneous, and contains elements described by a dtype object.
-
property
shape
¶ The common property of all
TensorValued
classes, indicating whether the bond dimensions for a tensor valued object. A tensor valued object is semantically a multi-dimensionally array, and its dimensions can be expressed as a tuple of integers. The tuple is called the shape of the tensor, whereas the length of the tuple is the rank of the tensor.In ACQDP, undetermined tensors and undetermined dimensions are allowed. In the former case, the shape of the tensor will return None; in the latter case, some of the bond_dimensions appearing in the tuple could be None.
- Returns
tuple
or None- Raises
NotImplementedError, ValueError
-
property
is_valid
¶ The common property of all
TensorValued
classes, indicating whether theTensorValued
object is valid or not. In every step of a program, all existingTensorValued
object must be valid, otherwise an exception should be thrown out.- Returns
- Raises
NotImplementedError
-
property
is_ready
¶ The common property of all
TensorValued
classes, indicating whether the currentTensorValued
object is ready for contraction, i.e. whether it semantically represents a tensor with a definite value. A TensorValued object needs to be ready upon contraction, but needs not to be ready throught the construction.- Returns
- Raises
NotImplementedError()
-
fix_index
(index, fix_to=0) → acqdp.tensor_network.tensor_valued.TensorValued[source]¶ Fix the given index to the given value. The result
TensorValued
object would have the same type as the original one, with rank 1 smaller than the original.- Parameters
- Returns
TensorValued
– TheTensorValued
object after fixing the given index.- Raises
NotImplementedError
-
contract
(**kwargs) → numpy.ndarray[source]¶ Evaluate the
TensorValued
object to anumpy.ndarray
.- Returns
numpy.ndarray
- Raises
NotImplementedError
-
class
acqdp.tensor_network.
Tensor
(*args, **kwargs)[source]¶ Bases:
acqdp.tensor_network.tensor_valued.TensorValued
A
Tensor
is an array of numbers with multiple dimensions. The most basic examples of aTensor
are a vector (1-dimensional arrays of numbers) and a matrix (2-dimensional arrays).In our implementation,
Tensor
is a subclass ofTensorValued
, where the value is stored in an numpy.ndarray. All other TensorValued represent operations over theTensor
objects.- Variables
_data – numpy.ndarray object representing the data corresponding to the tensor.
-
class
acqdp.tensor_network.
TensorSum
(*args, **kwargs)[source]¶ Bases:
acqdp.tensor_network.tensor_valued.TensorValued
A
TensorSum
object represents the summation of multiple tensors.- Variables
terms_by_name – a dictionary with key-value pairs, where the key is the name of a summand and the value is the corresponding summand
TensorValued
object.
-
__init__
(terms=None, dtype: type = <class 'complex'>) → None[source]¶ The constructor of a TensorSum object.
-
add_term
(term=None, tensor=None)[source]¶ Add a term to the summation.
- Parameters
term (hashable) – Name of the term to be added. If not given, an auto-assigned one will be given as the output.
tensor (
TensorValued
or None) – Value of the term to be added.
- Returns
The name of the newly added term.
-
update_term
(term, tensor=None)[source]¶ Update the value of a term in the summation.
- Parameters
term (hashable) – Name of the term to be updated.
tensor (
TensorValued
) – New value of the term
- Returns
Name of the term to be updated.
-
remove_term
(term)[source]¶ Remove a term from the summation.
- Parameters
term (hashable) – Name of the term to be removed.
- Returns
TensorValued
Value of the removed term
-
class
acqdp.tensor_network.
TensorView
(*args, **kwargs)[source]¶ Bases:
acqdp.tensor_network.tensor_valued.TensorValued
TensorView
is a subclass ofTensorValued
representing unary operations over anotherTensorValued
object that preserves the shape of the tensor. Common examples include element-wise conjugation and normalization with respect to the frobenius norm.
- Variables
tn – the underlying TensorValued object where the unary operation is performed onto.
func – the unary function to be applied.
homomorphism – indicator whether the unary function is homomorphic to the addition and multiplication of tensors. If so, the unary function can be broadcast to lower-level tensors, enabling potential simplification of the tensor network structure.
dtype – dtype for the tensor entries.
-
class
acqdp.tensor_network.
TensorNetwork
(*args, **kwargs)[source]¶ Bases:
acqdp.tensor_network.tensor_valued.TensorValued
A
TensorNetwork
is a collection ofTensor
, with indices from different tensors identified and summed up to present a new tensor. An example of tensor network is two 2-tensors with a common edge representing the matrix multiplication. ATensorNetwork
is a graphical representation of an Einstein summation.- Variables
network – attributed
networkx.Graph
object, representing the attributed hypergraph of the tensor network as a tanner graph.dtype – dtype of the
TensorValued
object.open_edges – a list of edge names, indicating the outgoing wires of the tensor network.
-
contract
(preset=None, config=None, **kwargs)[source]¶ Evaluate the
TensorNetwork
object as annumpy.ndarray
.- Parameters
preset (“default”, “khp” or None.) – Select a preset mode. If set to default, will contract the tensor network with default ordering and no post-processing. If set to khp, will invoke advanced KaHyPar-based contraction order finding routine. If set to None, will read config file or input keyword arguments for order finding specifications.
config (str) – File name for the config file. If preset option is not given and config file is given, the keyword arguments will be ignored and the specification will be read from the config file.
kwargs (dict) – If neither the preset option nor the config file name is given, the program will read the keyword arguments for order finding specifications. See
OrderFinder
,Compiler
,Contractor
for individual specifications.
- Returns
numpy.ndarray
.
-
find_order
(input_file=None, output_file=None, **kwargs)[source]¶ Find a contraction scheme of the
TensorNetwork
object. Equivalent to next(get_order_finder(**kwargs).find_order(self)). SeeOrderFinder.find_order()
.- Parameters
- Returns
-
compile
(order, **kwargs)[source]¶ Compile a
ContractionScheme
corresponding to theTensorNetwork
object into a runtime executable contraction process as aContractionTask
. Equivalent to Compiler(**kwargs.get(‘compiler_params’, {})).compile(self, order) (SeeCompiler.compile()
).- Returns
-
add_node
(node_name=None, edges=None, tensor=None, is_open=False)[source]¶ Add a node into the tensor network.
- Parameters
node_name (
hashable
) – The name of the node to be added. If not provided, a new name will be assigned.edges (
List
– list of edges in the tensor network corresponding to the open edges of the new node. If not given, defaults to edges [0, …, len(shape)]) – The edges the new tensor node is being connected to.tensor (
tensor_network.tensor_valued.TensorValued
.) – The value of the newly added tensor.is_open (
bool
) – Whether the new indices associated to the new node will be added to open_edges.
- Returns
hashable – Name of the node added. If none is given as input, return the one automatically signed.
- Raises
ValueError – An existing node in the tensor network is being added.
- Raises
IndexError – A node is added with ambiguous connection to the tensor network. Happens when neither the shape of the tensor nor the connecting edges are given.
- Raises
AssertionError – A mismatch in the bond dimensions.
-
pop_node
(node_name)[source]¶ Pop a tensor node from the tensor network. This operation simply removes the node from the hypergraph.
- Returns
dict – The dict containing all the information of the popped node, including its tensor and hyperedge connections.
- Parameters
node_name (hashable) – Name of the node to be popped.
-
remove_node
(node_name)[source]¶ Remove a tensor node from the tensor network. The difference between removing a node and popping anode is that popping a node does not change the output shape of the tensor network, while removing a node would result in a new tensor-valued object, where all edges connected to the removed node are appended to the end of the open edges list.
- Returns
dict – The dict containing all the information of the removed node, including its tensor and hyperedge connections.
- Parameters
node_name (hashable) – Name of the node to be removed.
-
update_node
(node_name, tensor=None)[source]¶ Update an existing node of the tensor network by another tensor-valued object.
- Parameters
node_name (hashable) – Name of the node to be updated.
tensor (
TensorValued
or None) – The new tensor to be put at the node. If None, the tensor must be updated with an actual value later in order for the tensor network to be ready for contraction.
- Raises
AssertionError – Node update results in a bond dimension mismatch.
-
add_edge
(edge_name=None, bond_dim=None)[source]¶ Generate an index which is not in this tensor network before.
- Parameters
edge_name (hashable) – Name of the edge to be added. Will be automatically assigned if none is given.
bond_dim (int or None) – Bond dimension of the edge. If set to None, the edge bond dimension will be wildcard until set otherwise.
- Returns
hashable – Name of the newly added edge.
-
open_edge
(edge_name=None, bond_dim=None)[source]¶ Append an edge to the list of open edges. If the edge does not exist, it will be created.
- Parameters
edge_name (hashable) – Name of the edge to be opened.
bond_dim (int) – Bond dimension of the edge. See add_edge.
-
close_edge
(edge_name)[source]¶ Make an edge closed. All appearances of the edge will be removed from the open edges list.
- Parameters
edge_name (hashable) – Edge to be closed.
-
fix_edge
(edge_name, fix_to=0, change_fix=False)[source]¶ Fix an edge to a fixed value. The tensor network structure is not yet modified; this method only puts an attribute to the fixed hyperedges. The structure will be changed upon calling the fix method.
- Parameters
edge_name (hashable) – Edge to be fixed to a specific value.
fix_to (int) – the value the edge is fixed to. Should be an integer ranging from 0 to bond_dim - 1.
change_fix (bool) – Mode of fix_edge. If change_fix is set to True, the edge will be fixed to the given value regardless of how it is fixed previously. If set to False, the fix will apply together with the previous fix, resulting in a zero tensor if the two fixes do not match.
-
merge_edges
(edges, merge_to=None)[source]¶ Merge a list of edges as one single edge by identification.
- Parameters
edges (
List
) – The list of edges to be merged into one.merge_to (hashable) – The name of the edge all the edges are merged to. If set to None, the merged edges will appear as edges[0]
-
rewire
(node_name, leg, rewire_to=None)[source]¶ Rewire an outgoing edge of a tensor node to another edge in the tensor network.
- Parameters
node_name (hashable) – Name of the tensor node for whom an outgoing edge is to be rewired.
leg (int) – Index of the outgoing edge regarding the tensor node. Should be an integer ranging from 0 to rank(t) - 1, t being the corresponding tensor.
rewire_to (hashable) – The edge name in the tensor network to redirect the leg to. If None, it will be rewired to a newly created edge.