Common Functions¶
-
tensornetwork.
norm
(tensor: tensornetwork.tensor.Tensor) → tensornetwork.tensor.Tensor¶ Calculate the L2-norm of the elements of
tensor
-
tensornetwork.
conj
(tensor: tensornetwork.tensor.Tensor) → tensornetwork.tensor.Tensor¶ Return the complex conjugate of
Tensor
:param Tensor: A Tensor.Returns: The complex conjugated Tensor.
-
tensornetwork.
copy
(nodes: Iterable[tensornetwork.network_components.AbstractNode], conjugate: bool = False) → Tuple[dict, dict]¶ Copy the given nodes and their edges.
This will return a tuple linking original nodes/edges to their copies. If nodes A and B are connected but only A is passed in to be copied, the edge between them will become a dangling edge.
Parameters: - nodes – An Iterable (Usually a
list
orset
) ofnodes
. - conjugate – Boolean. Whether to conjugate all of the nodes (useful for calculating norms and reduced density matrices).
Returns: - node_dict:
A dictionary mapping the nodes to their copies.
- edge_dict:
A dictionary mapping the edges to their copies.
Return type: A tuple containing
- nodes – An Iterable (Usually a
-
tensornetwork.
transpose
(tensor: tensornetwork.tensor.Tensor, perm: Optional[Sequence[int]] = None) → tensornetwork.tensor.Tensor¶ Return a new
Tensor
transposed according to the permutation set byaxes
. By default the axes are reversed. :param axes: The permutation. If None (default) the index order is reversed.Returns: The transposed Tensor
.
-
tensornetwork.
remove_node
(node: tensornetwork.network_components.AbstractNode) → Tuple[Dict[str, tensornetwork.network_components.Edge], Dict[int, tensornetwork.network_components.Edge]]¶ Remove a node from the network.
Parameters: node – The node to be removed. Returns: - disconnected_edges_by_name:
- A Dictionary mapping
node
’s axis names to the newly broken edges. - disconnected_edges_by_axis:
- A Dictionary mapping
node
’s axis numbers to the newly broken edges.
Return type: A tuple of
-
tensornetwork.
split_node
(node: tensornetwork.network_components.AbstractNode, left_edges: List[tensornetwork.network_components.Edge], right_edges: List[tensornetwork.network_components.Edge], max_singular_values: Optional[int] = None, max_truncation_err: Optional[float] = None, relative: Optional[bool] = False, left_name: Optional[str] = None, right_name: Optional[str] = None, edge_name: Optional[str] = None) → Tuple[tensornetwork.network_components.AbstractNode, tensornetwork.network_components.AbstractNode, Any]¶ Split a
node
using Singular Value Decomposition.Let \(M\) be the matrix created by flattening
left_edges
andright_edges
into 2 axes. Let \(U S V^* = M\) be the SVD of \(M\). This will split the network into 2 nodes. The left node’s tensor will be \(U \sqrt{S}\) and the right node’s tensor will be \(\sqrt{S} V^*\) where \(V^*\) is the adjoint of \(V\).The singular value decomposition is truncated if
max_singular_values
ormax_truncation_err
is notNone
.The truncation error is the 2-norm of the vector of truncated singular values. If only
max_truncation_err
is set, as many singular values will be truncated as possible while maintaining:norm(truncated_singular_values) <= max_truncation_err
. Ifrelative
is setTrue
thenmax_truncation_err
is understood relative to the largest singular value.If only
max_singular_values
is set, the number of singular values kept will bemin(max_singular_values, number_of_singular_values)
, so thatmax(0, number_of_singular_values - max_singular_values)
are truncated.If both
max_truncation_err
andmax_singular_values
are set,max_singular_values
takes priority: The truncation error may be larger thanmax_truncation_err
if required to satisfymax_singular_values
.Parameters: - node – The node you want to split.
- left_edges – The edges you want connected to the new left node.
- right_edges – The edges you want connected to the new right node.
- max_singular_values – The maximum number of singular values to keep.
- max_truncation_err – The maximum allowed truncation error.
- relative – Multiply
max_truncation_err
with the largest singular value. - left_name – The name of the new left node. If
None
, a name will be generated automatically. - right_name – The name of the new right node. If
None
, a name will be generated automatically. - edge_name – The name of the new
Edge
connecting the new left and right node. IfNone
, a name will be generated automatically. The new axis will get the same name as the edge.
Returns: - left_node:
A new node created that connects to all of the
left_edges
. Its underlying tensor is \(U \sqrt{S}\)- right_node:
A new node created that connects to all of the
right_edges
. Its underlying tensor is \(\sqrt{S} V^*\)- truncated_singular_values:
The vector of truncated singular values.
Return type: A tuple containing
Raises: AttributeError
– Ifnode
has no backend attribute
-
tensornetwork.
split_node_qr
(node: tensornetwork.network_components.AbstractNode, left_edges: List[tensornetwork.network_components.Edge], right_edges: List[tensornetwork.network_components.Edge], left_name: Optional[str] = None, right_name: Optional[str] = None, edge_name: Optional[str] = None) → Tuple[tensornetwork.network_components.AbstractNode, tensornetwork.network_components.AbstractNode]¶ Split a
node
using QR decomposition.Let \(M\) be the matrix created by flattening
left_edges
andright_edges
into 2 axes. Let \(QR = M\) be the QR Decomposition of \(M\). This will split the network into 2 nodes. Theleft node
’s tensor will be \(Q\) (an orthonormal matrix) and theright node
’s tensor will be \(R\) (an upper triangular matrix)Parameters: - node – The node you want to split.
- left_edges – The edges you want connected to the new left node.
- right_edges – The edges you want connected to the new right node.
- left_name – The name of the new left node. If
None
, a name will be generated automatically. - right_name – The name of the new right node. If
None
, a name will be generated automatically. - edge_name – The name of the new
Edge
connecting the new left and right node. IfNone
, a name will be generated automatically.
Returns: - left_node:
A new node created that connects to all of the
left_edges
. Its underlying tensor is \(Q\)- right_node:
A new node created that connects to all of the
right_edges
. Its underlying tensor is \(R\)
Return type: A tuple containing
Raises: AttributeError
– Ifnode
has no backend attribute
-
tensornetwork.
split_node_rq
(node: tensornetwork.network_components.AbstractNode, left_edges: List[tensornetwork.network_components.Edge], right_edges: List[tensornetwork.network_components.Edge], left_name: Optional[str] = None, right_name: Optional[str] = None, edge_name: Optional[str] = None) → Tuple[tensornetwork.network_components.AbstractNode, tensornetwork.network_components.AbstractNode]¶ Split a
node
using RQ (reversed QR) decomposition.Let \(M\) be the matrix created by flattening
left_edges
andright_edges
into 2 axes.Let \(QR = M^*\) be the QR Decomposition of \(M^*\). This will split the network into 2 nodes.
The left node’s tensor will be \(R^*\) (a lower triangular matrix) and the right node’s tensor will be \(Q^*\) (an orthonormal matrix)
Parameters: - node – The node you want to split.
- left_edges – The edges you want connected to the new left node.
- right_edges – The edges you want connected to the new right node.
- left_name – The name of the new left node. If
None
, a name will be generated automatically. - right_name – The name of the new right node. If
None
, a name will be generated automatically. - edge_name – The name of the new
Edge
connecting the new left and right node. IfNone
, a name will be generated automatically.
Returns: - left_node:
A new node that connects to all of the
left_edges
. Its underlying tensor is \(R^*\)- right_node:
A new node that connects to all of the
right_edges
. Its underlying tensor is \(Q^*\)
Return type: A tuple containing
Raises: AttributeError
– Ifnode
has no backend attribute
-
tensornetwork.
split_node_full_svd
(node: tensornetwork.network_components.AbstractNode, left_edges: List[tensornetwork.network_components.Edge], right_edges: List[tensornetwork.network_components.Edge], max_singular_values: Optional[int] = None, max_truncation_err: Optional[float] = None, relative: Optional[bool] = False, left_name: Optional[str] = None, middle_name: Optional[str] = None, right_name: Optional[str] = None, left_edge_name: Optional[str] = None, right_edge_name: Optional[str] = None) → Tuple[tensornetwork.network_components.AbstractNode, tensornetwork.network_components.AbstractNode, tensornetwork.network_components.AbstractNode, Any]¶ Split a node by doing a full singular value decomposition.
Let \(M\) be the matrix created by flattening
left_edges
andright_edges
into 2 axes. Let \(U S V^* = M\) be the Singular Value Decomposition of \(M\).The left most node will be \(U\) tensor of the SVD, the middle node is the diagonal matrix of the singular values, ordered largest to smallest, and the right most node will be the \(V*\) tensor of the SVD.
The singular value decomposition is truncated if
max_singular_values
ormax_truncation_err
is notNone
.The truncation error is the 2-norm of the vector of truncated singular values. If only
max_truncation_err
is set, as many singular values will be truncated as possible while maintaining:norm(truncated_singular_values) <= max_truncation_err
. Ifrelative
is setTrue
thenmax_truncation_err
is understood relative to the largest singular value.If only
max_singular_values
is set, the number of singular values kept will bemin(max_singular_values, number_of_singular_values)
, so thatmax(0, number_of_singular_values - max_singular_values)
are truncated.If both
max_truncation_err
andmax_singular_values
are set,max_singular_values
takes priority: The truncation error may be larger thanmax_truncation_err
if required to satisfymax_singular_values
.Parameters: - node – The node you want to split.
- left_edges – The edges you want connected to the new left node.
- right_edges – The edges you want connected to the new right node.
- max_singular_values – The maximum number of singular values to keep.
- max_truncation_err – The maximum allowed truncation error.
- relative – Multiply
max_truncation_err
with the largest singular value. - left_name – The name of the new left node. If None, a name will be generated automatically.
- middle_name – The name of the new center node. If
None
, a name will be generated automatically. - right_name – The name of the new right node. If
None
, a name will be generated automatically. - left_edge_name – The name of the new left
Edge
connecting the new left node (\(U\)) and the new central node (\(S\)). IfNone
, a name will be generated automatically. - right_edge_name – The name of the new right
Edge
connecting the new central node (\(S\)) and the new right node (\(V*\)). IfNone
, a name will be generated automatically.
Returns: - left_node:
A new node created that connects to all of the
left_edges
. Its underlying tensor is \(U\)- singular_values_node:
A new node that has 2 edges connecting
left_node
andright_node
. Its underlying tensor is \(S\)- right_node:
A new node created that connects to all of the
right_edges
. Its underlying tensor is \(V^*\)- truncated_singular_values:
The vector of truncated singular values.
Return type: A tuple containing
Raises: AttributeError
– Ifnode
has no backend attribute
-
tensornetwork.
split_edge
(edge: tensornetwork.network_components.Edge, shape: Tuple[int, ...], new_edge_names: Optional[List[str]] = None) → List[tensornetwork.network_components.Edge]¶ Split an
Edge
into multiple edges according toshape
. Reshapes the underlying tensors connected to the edge accordingly.This method acts as the inverse operation of flattening edges and distinguishes between the following edge cases when adding new edges:
- standard edge connecting two different nodes: reshape node dimensions
- dangling edge (node2 is None): reshape node1 dimension
- trace edge (node1 is node2): reshape node1 dimension
Parameters: - edge – Edge to split.
- shape – Tuple of integers used to split edge into multiple edges.
Returns: A list of new edges where the product of the dimensions of the new edges corresponds to the dimension of the edge before splitting.
Raises: ValueError
– If the edge dimension mismatches with the split shape.ValueError
– If the edge is connecting nodes with different backends.
-
tensornetwork.
slice_edge
(edge: tensornetwork.network_components.Edge, start_index: int, length: int) → tensornetwork.network_components.Edge¶ Slices an edge and the connected tensors beginning at
start_index
for lengthlength
, along the axis determined byedge
.This method modifies the tensors stored in the two nodes connected by
edge
to corresponding tensor slices (along the axis determined byedge
) and returns an updated edge connecting the two nodes along the same axis as the originaledge
.Parameters: - edge – The edge to slice.
- start_index – Integer specifying the beginning of the slice.
- length – Integer specifying the length of the slice.
Returns: The updated edge after slicing.
Raises: ValueError
– If the length of the slice is negative.ValueError
– If the slice is incompatible with the edge dimension.ValueError
– If the edge is connecting nodes with different backends.
-
tensornetwork.
reachable
(inputs: Union[tensornetwork.network_components.AbstractNode, Iterable[tensornetwork.network_components.AbstractNode], tensornetwork.network_components.Edge, Iterable[tensornetwork.network_components.Edge]]) → Set[tensornetwork.network_components.AbstractNode]¶ Computes all nodes reachable from
node
oredge.node1
by connected edges.Parameters: inputs – A AbstractNode
/Edge
or collection ofAbstractNodes
/Edges
Returns: A set of AbstractNode
objects that can be reached fromnode
via connected edges.Raises: TypeError
– If inputs contains other thenEdge
orNode
.
-
tensornetwork.
check_connected
(nodes: Iterable[tensornetwork.network_components.AbstractNode]) → None¶ Check if all nodes in
nodes
are connected.Parameters: nodes – A list of nodes
.Returns: None
Raises: ValueError
– If not all nodes innodes
are connected.
-
tensornetwork.
check_correct
(nodes: Iterable[tensornetwork.network_components.AbstractNode], check_connections: Optional[bool] = True) → None¶ Check if the network defined by
nodes
fulfills necessary consistency relations.Parameters: - nodes – A list of
AbstractNode
objects. - check_connections – Check if the network is connected.
Returns: None
Raises: ValueError
– If the network defined bynodes
is not correctly structured.- nodes – A list of
-
tensornetwork.
get_all_nodes
(edges: Iterable[tensornetwork.network_components.Edge]) → Set[tensornetwork.network_components.AbstractNode]¶ Return the set of nodes connected to edges.
-
tensornetwork.
get_all_edges
(nodes: Iterable[tensornetwork.network_components.AbstractNode]) → Set[tensornetwork.network_components.Edge]¶ Return the set of edges of all nodes.
-
tensornetwork.
get_subgraph_dangling
(nodes: Iterable[tensornetwork.network_components.AbstractNode]) → Set[tensornetwork.network_components.Edge]¶ Get all of the edges that are “relatively dangling” to the given nodes.
A “relatively dangling” edge is an edge that is either actually dangling or is connected to another node that is outside of the given collection of
nodes
.Parameters: nodes – A set of nodes. Returns: The set of “relatively dangling” edges.
-
tensornetwork.
reduced_density
(traced_out_edges: Iterable[tensornetwork.network_components.Edge]) → Tuple[dict, dict]¶ Constructs the tensor network for a reduced density matrix, if it is pure.
The tensor network connected to
traced_out_edges
is assumed to be a pure quantum state (a state vector). This modifies the network so that it describes the reduced density matrix obtained by “tracing out” the specified edges.This is done by making a conjugate copy of the original network and connecting each edge in
traced_out_edges
with its conjugate counterpart.The edges in
edge_dict
corresponding totraced_out_edges
will be the new non-dangling edges connecting the state with its conjugate.Parameters: traced_out_edges – A list of dangling edges. Returns: - node_dict: A dictionary mapping the nodes in the original network to
- their conjugate copies.
- edge_dict: A dictionary mapping edges in the original network to their
- conjugate copies.
Return type: A tuple containing
-
tensornetwork.
switch_backend
(nodes: Iterable[tensornetwork.network_components.AbstractNode], new_backend: str) → None¶ Change the backend of the nodes.
This will convert all
node
’s tensors to thenew_backend
’s Tensor type.Parameters: - nodes – iterable of nodes
- new_backend (str) – The new backend.
- dtype (datatype) – The dtype of the backend. If
None
, a defautl dtype according to config.py will be chosen.
Returns: None
-
tensornetwork.
contract_trace_edges
(node: tensornetwork.network_components.AbstractNode) → tensornetwork.network_components.AbstractNode¶ contract all trace edges of
node
.Parameters: node – A AbstractNode
object.Returns: A new AbstractNode
obtained from contracting all trace edges.
-
tensornetwork.
contract
(edge: tensornetwork.network_components.Edge, name: Optional[str] = None, axis_names: Optional[List[str]] = None) → tensornetwork.network_components.AbstractNode¶ Contract an edge connecting two nodes.
All edges of
node1
andnode2
are passed on to the new node, andnode1
andnode2
get a new set of dangling edges.edge
is disabled before returning.Parameters: - edge – The edge to contract.
- name – Name of the new node created.
Returns: The new node created after the contraction.
Raises: ValueError
– When edge is a dangling edge or if it already has been contracted.
-
tensornetwork.
contract_copy_node
(copy_node: tensornetwork.network_components.CopyNode, name: Optional[str] = None) → tensornetwork.network_components.AbstractNode¶ Contract all edges incident on given copy node.
Parameters: - copy_node – Copy tensor node to be contracted.
- name – Name of the new node created.
Returns: New node representing contracted tensor.
Raises: ValueError
– If copy_node has dangling edge(s).
-
tensornetwork.
contract_between
(node1: tensornetwork.network_components.AbstractNode, node2: tensornetwork.network_components.AbstractNode, name: Optional[str] = None, allow_outer_product: bool = False, output_edge_order: Optional[Sequence[tensornetwork.network_components.Edge]] = None, axis_names: Optional[List[str]] = None) → tensornetwork.network_components.AbstractNode¶ Contract all of the edges between the two given nodes.
If
output_edge_order
is not set, the output axes will be ordered as:[...free axes of node1..., ...free axes of node2...]
. Within the axes of eachnode
, the input order is preserved.Parameters: - node1 – The first node.
- node2 – The second node.
- name – Name to give to the new node created.
- allow_outer_product – Optional boolean. If two nodes do not share any edges
and
allow_outer_product
is set toTrue
, then we return the outer product of the two nodes. Else, we raise aValueError
. - output_edge_order – Optional sequence of Edges. When not
None
, must contain all edges belonging to, but not shared bynode1
andnode2
. The axes of the new node will be permuted (if necessary) to match this ordering of Edges. - axis_names – An optional list of names for the axis of the new node in order of the output axes.
Returns: The new node created.
Raises: ValueError
– If no edges are found between node1 and node2 andallow_outer_product
is set toFalse
.
-
tensornetwork.
outer_product
(node1: tensornetwork.network_components.AbstractNode, node2: tensornetwork.network_components.AbstractNode, name: Optional[str] = None, axis_names: Optional[List[str]] = None) → tensornetwork.network_components.AbstractNode¶ Calculates an outer product of the two nodes.
This causes the nodes to combine their edges and axes, so the shapes are combined. For example, if
a
had a shape (2, 3) andb
had a shape :math`(4, 5, 6)`, then the nodenet.outer_product(a, b)
will have shape \((2, 3, 4, 5, 6)\). All edges ofnode1
andnode2
are passed on to the new node, andnode1
andnode2
get a new set of dangling edges.Parameters: - node1 – The first node. The axes on this node will be on the left side of the new node.
- node2 – The second node. The axes on this node will be on the right side of the new node.
- name – Optional name to give the new node created.
- axis_names – An optional list of names for the axis of the new node.
Returns: A new node. Its shape will be
node1.shape + node2.shape
.Raises: TypeError
– Ifnode1
andnode2
have wrong types.
-
tensornetwork.
outer_product_final_nodes
(nodes: Iterable[tensornetwork.network_components.AbstractNode], edge_order: List[tensornetwork.network_components.Edge]) → tensornetwork.network_components.AbstractNode¶ Get the outer product of
nodes
For example, if there are 3 nodes remaining in
nodes
with shapes \((2, 3)\), \((4, 5, 6)\), and \((7)\) respectively, the newly returned node will have shape \((2, 3, 4, 5, 6, 7)\).Parameters: - nodes – A collection of nodes.
- edge_order – Edge order for the final node.
Returns: The outer product of the remaining nodes.
Raises: ValueError
– If any of the remaining nodes are not fully contracted.
-
tensornetwork.
contract_parallel
(edge: tensornetwork.network_components.Edge) → tensornetwork.network_components.AbstractNode¶ Contract all edges parallel to this edge.
This method calls
contract_between
with the nodes connected by the edge.Parameters: edge – The edge to contract. Returns: The new node created after contraction.
-
tensornetwork.
flatten_edges
(edges: List[tensornetwork.network_components.Edge], new_edge_name: Optional[str] = None) → tensornetwork.network_components.Edge¶ Flatten edges into single edge.
If two nodes have multiple edges connecting them, it may be beneficial to flatten these edges into a single edge to avoid having several unnecessary trace edges. This can speed up computation time and reduce memory cost.
Warning: This will remove all axes names.
Parameters: - edges – A list of edges to flatten.
- new_edge_name – Optional name to give to the newly created edge.
Returns: The new flattened edge.
Raises: ValueError
– If edges is an empty list.ValueError
– If not all of the edges connect to the same node(s).ValueError
– If one of the nodes connecting to these edges does not have edge definitions for all of its axes.
-
tensornetwork.
get_all_nondangling
(nodes: Iterable[tensornetwork.network_components.AbstractNode]) → Set[tensornetwork.network_components.Edge]¶ Return the set of all non-dangling edges.
-
tensornetwork.
get_all_dangling
(nodes: Iterable[tensornetwork.network_components.AbstractNode]) → List[tensornetwork.network_components.Edge]¶ Return the set of all dangling edges.
-
tensornetwork.
flatten_all_edges
(nodes: Iterable[tensornetwork.network_components.AbstractNode]) → List[tensornetwork.network_components.Edge]¶ Flatten all edges that belong to the nodes.
Returns: A list of all the flattened edges. If there was only one edge between two given nodes, that original edge is included in this list.
-
tensornetwork.
flatten_edges_between
(node1: tensornetwork.network_components.AbstractNode, node2: tensornetwork.network_components.AbstractNode) → Optional[tensornetwork.network_components.Edge]¶ Flatten all of the edges between the given two nodes.
Parameters: - node1 – The first node.
- node2 – The second node.
Returns: - The flattened
Edge
object. If there was only one edge between the two nodes, then the original edge is returned. If there were no edges between the nodes, a None is returned.
-
tensornetwork.
get_parallel_edges
(edge: tensornetwork.network_components.Edge) → Set[tensornetwork.network_components.Edge]¶ Get all of the edges parallel to the given
edge
. :param edge: The given edge.Returns: A set
of all of the edges parallel to the given edge (including the given edge).
Get all edges shared between two nodes.
Parameters: - node1 – The first node.
- node2 – The second node.
Returns: A (possibly empty)
set
of `Edge`s shared by the nodes.
-
tensornetwork.
get_neighbors
(node: tensornetwork.network_components.AbstractNode) → List[tensornetwork.network_components.AbstractNode]¶ Get all of the neighbors that are directly connected to the given node.
Note:
node
will never be in the returned list, even ifnode
has a trace edge.Parameters: node – A node. Returns: All of the neighboring edges that share an Edge
withnode
.
-
tensornetwork.
kron
(tensorA: tensornetwork.tensor.Tensor, tensorB: tensornetwork.tensor.Tensor) → tensornetwork.tensor.Tensor¶ Compute the (tensor) kronecker product between
tensorA
andtensorB
.tensorA
andtensorB
can be tensors of any even order (i.e.tensorA.ndim % 2 == 0
,tensorB.ndim % 2 == 0
). The returned tensor has index ordering such that when reshaped into a matrix withpivot =t ensorA.ndim//2 + tensorB.ndim//2
, the resulting matrix is identical to the result of numpy’snp.kron(matrixA, matrixB)
, withmatrixA, matrixB
matrices obtained from reshapingtensorA
andtensorB
into matrices withpivotA = tensorA.ndim//2
,pivotB = tensorB.ndim//2
Example:
tensorA.shape = (2,3,4,5)
,tensorB.shape(6,7)
->kron(tensorA, tensorB).shape = (2, 3, 6, 4, 5, 7)
Parameters: - tensorA – A
Tensor
. - tensorB – A
Tensor
.
Returns: The kronecker product.
Return type: Tensor
Raises: ValueError
– - If backends, are not matching. - If ndims of the input tensors are not even.- tensorA – A