pytreenet.core package

Submodules

pytreenet.core.canonical_form module

This module is concerned with the canonical form of a TreeTensorNetwork.

The canonical form of a TreeTensorNetwork is a specific choice of the gauge freedom causing all tensors apart from the orthogonality center to be a equivalent to an isometry. This is achieved by performing a series of QR decompositions on the tensors of the network.

pytreenet.core.canonical_form.canonical_form(ttn: TreeTensorNetwork, orthogonality_center_id: str, mode: SplitMode = SplitMode.REDUCED)

Modifies a TreeTensorNetwork into canonical form.

Parameters:
  • ttn (TreeTensorNetwork) – The TTN for which to be transformed into canonical form.

  • orthogonality_center_id (str) – The identifier of the tensor node which is the orthogonality center for the canonical form.

  • mode – The mode to be used for the QR decomposition. For details refe to tensor_util.tensor_qr_decomposition.

pytreenet.core.canonical_form.split_qr_contract_r_to_neighbour(ttn: TreeTensorNetwork, node_id: str, neighbour_id: str, mode: SplitMode = SplitMode.REDUCED)
Takes a node an splits of the virtual leg to a neighbours via QR

decomposition. The resulting R tensor is contracted with the neighbour.:

   __|__      __|__        __|__      __      __|__
__|  N1 |____|  N2 | ---> | N1' |____|__|____|  N2 |
  |_____|    |_____|      |_____|            |_____|

          __|__      __|__
--->   __| N1' |____| N2' |
         |_____|    |_____|
Parameters:
  • ttn (TreeTensorNetwork) – The tree tensor network in which to perform this action.

  • node_id (str) – The identifier of the node to be split.

  • neighbour_id (str) – The identifier of the neigbour to which to split.

  • mode – The mode to be used for the QR decomposition. For details refer to tensor_util.tensor_qr_decomposition.

pytreenet.core.graph_node module

Provides the GraphNode class, which is the fundamental building block of trees.

A GraphNode is a node in a tree structure and contains the information about neighbouring nodes, i.e. parent and children nodes.

# Create a graph node
node = GraphNode("node"

# Add a parent
node.add_parent("parent")

# Add children
node.add_child("child1")
node.add_children(["child2", "child3"])

# We can do some checks
node.is_root()  # False
node.is_leaf()  # False
node.is_child_of("parent")  # True
node.is_parent_of("child1")  # True

# An check the numbers for conneciivity
node.nparents()  # 1
node.nchildren()  # 3
node.nneighbours()  # 4
node.neighbour_index("child2") # 2
node.child_index("child2")  # 1
node.neighbouring_nodes()  # ["parent", "child1", "child2", "child3"]

Note that GraphNodes are usually not used directly, but rather via the Node child class in tree tensor networks.

class pytreenet.core.graph_node.GraphNode(identifier='')

Bases: object

A graph node is the fundamental building block of a tree.

It contains the connectivity information of the graph node in the tree structure, i.e. parent and children nodes.

identifier

A unique identifier assigned to this node.

Type:

str

parent

The identifier of the parent node. There can only a single parent node. If there is no parent, this attribute is None.

Type:

Union[str,None]

children

A list of identifiers of the children nodes. We consider the order of this list to be the order of the children.

Type:

List[str]

add_child(child_id: str)

Add a new child to this node.

Parameters:

child_id (str) – The identifier of the child node. Will be added as a child to this node.

add_children(children_ids: List[str])

Adds mutliple children to this node.

Parameters:

children_ids (List[str]) – A list of identifiers of the children nodes. All will be added as children to this node.

add_parent(parent_id: str)

Add a parent to this node.

Parameters:

parent_id (str) – The identifier of the parent node. Will be added as the parent of this node.

Raises:

AssertionError – If the node already has a parent. Instead remove the parent first and then add the new parent.

child_index(child_id: str) int

Returns the index of a child of the node.

The order is (usually) defined by the order in which the children were added.

Parameters:

child_id (str) – The identifier of the child to look for.

copy_with_new_id(new_id: str) GraphNode

Creates a copy of this GraphNode with a new identifier.

Parameters:

new_id (str) – The new identifier.

Returns:

A copy of this GraphNode with a new identifier.

Return type:

GraphNode

has_x_children(x: int) bool

Returns whether this node has exactly x-many children.

property identifier: str

A string that is unique to this node.

is_child_of(other_node_id: str) bool

Determines whether this node is a child of the node with identifier ‘other_node_id’.

is_leaf() bool

Returns whether this node is a leaf, i.e. doesn’t have children

is_parent_of(other_node_id: str) bool

Determines whether this node is a parent of the node with identifier ‘other_node_id’.

is_root() bool

Returns whether this node is a root node, i.e. doesn’t have a parent.

nchildren() int

The number of children of this node

neighbour_index(node_id: str) int

Returns the index of the neighbour of this node.

This includes the parent with index 0 and the children.

Parameters:

node_id (str) – The identifier of the node to look for.

Returns:

The index of the node.

Return type:

int

neighbouring_nodes() List[str]

Provides the identifiers of all neighbours.

This means of all children and the parent, if it exists.

Returns:

Contains the neighbour identifiers, if this node is not

a root, the parent’s identifier is the first identifier.

Return type:

List[str]

nneighbours() int

Returns the number of neighbours of this node.

This includes the children and the parent.

nparents() int

Returns the number of parents of this node.

remove_child(child_id: str)

Removes a child from this node’s children.

Parameters:

child_id (str) – The identifier of the child to be removed.

remove_parent()

Removes parent and replaces it by None

replace_child(child_id: str, new_child_id: str)

Replaces one child with another.

This is done in place.

Parameters:
  • child_id (str) – The identifier of the child to be replaced.

  • new_child_id (str) – The identifier of the new child.

replace_neighbour(old_neighbour_id: str, new_neighbour_id: str)

Replaces a neighbour with a new one.

This is done in place.

Parameters:
  • old_neighbour_id (str) – The node identifier to be replaced.

  • new_neighbour_id (str) – The new node identifier to be inserted.

pytreenet.core.leg_specification module

This module is used to unambigously define tensor legs.

It contains the LegSpecification class. This class allows the definition of legs with regards to legs towards neighbours and open legs. It is commonly used to define the which legs belong to which resulting node yielded by the splitting of a tensor. It allows the use of node identifiers rather than leg indices, avoiding potential complications.

Example

Assume we want to perform the following split:

           |open1  |open 0                             |open1          |open0
        ___|_______|___                             ___|___         ___|___
child1 |               |   parent           child1 |       |  new  |       |   parent
   ----|       C       |-----          -->     ----|   A   |-------|   B   |----
       |_______________|                           |_______|       |_______|
           |       |                                   |               |
     child2|       |child3                       child2|         child3|

the corresponding code would be:

# Creating the mother node
ctensor = crandn((2,2,2,2,2,2))
C = Node(identifier="C",tensor=ctensor)
C.open_leg_to_parent("parent",0)
children = {"child1":1,"child2":2,"child3":3}
C.open_leg_to_children()

# Defining the neighbouring legs
parent_legA = None
parent_legB = "parent"
children_legsA = ["child1","child2"]
children_legsB = ["child3"]

# Defining the open legs
open_legsA = [5]
open_legsB = [4]

# The LegSpecification
legsA = LegSpecification(parent_legA, children_legsA, open_legsA,
                         node=C)
legsB = LegSpecification(parent_legB, children_legsB, open_legsB,
                         node=C)
class pytreenet.core.leg_specification.LegSpecification(parent_leg: str | None, child_legs: List[str], open_legs: List[int], node: Node | None = None, is_root: bool = False)

Bases: object

Contains data to describe a split-off node’s legs fully.

In case a splitting of node occurs, a LegSpecification contains all the data required to define one of the new nodes. Can also be used in other cases where a convenient storage of node legs is required.

parent_leg

The identifier of a potential parent. If it is None, the node is either a root or the parent node is created after the LegSpecification and the identifier is not yet known.

Type:

Union[str,None]

children_legs

The identifiers of the children that should be associated with this node.

Type:

List[str]

open_legs

A list of open leg indices. The indices are usually the indices of the tensor before a split or similar operation. They are usually not the indices of the open legs of newly created nodes.

Type:

List[int]

node

A node that is required to translate the stored identifiers into indices. Can be None, as the node needing it might be created at a later point. Defaults to None.

Type:

Union[Node,None]

is_root

Determines, if the node associated before a potential split is a root and the node this specification is for should suceed it in that. Not having a parent leg is insufficient, as this might be created at a later date.

Type:

bool

find_all_neighbour_ids() List[str]

Returns all identifiers of neighbours specified in this instance.

This is the neighbours specified in the legs, not the neighbours of an associated node.

Returns:

All identifiers of neighbours. The parent is the first.

Return type:

List[str]

find_leg_values() List[str]

Find the index values of the specified tensor legs.

This is done in reference to the node specified in the instance.

Returns:

The leg values specified in the order

[parent_leg, child_legs, open_legs]

Return type:

List[str]

pytreenet.core.node module

class pytreenet.core.node.Node(tensor: ndarray | None = None, identifier: str = '')

Bases: GraphNode

The node class is responsible for the control of the legs.

This means, it keeps track of the leg order or more precisely the permutation of the legs compared to the data tensor in order to keep the leg convention

(parent, child0, ..., childN-1, open_leg0, ..., open_legM-1)

A Node can be created independently from a tensor. It can then be linked to this tensor afterwards.

identifier

The identifier of the node.

Type:

str

leg_permutation

The permutation of the legs compared to the data tensor. The values are the indices of the tensor legs at the positions they need to be permuted to. In general leg indices are returned according to the positions in this list and not according to the actual tensor legs.

Type:

List[int]

shape

The shape of the tensor associated with this node. This is the shape of the tensor after the permutation of the legs and allows for more convenient checks and sanity checks.

Type:

Tuple

child_leg_to_open_leg(child_id: str)

Changes a leg towards a child node into an open leg.

The newly opened leg will be the last leg of the node.

Parameters:

child_id (str) – The identifier of the child_nodem to be disconnected.

property children_legs: List[int]

Returns the children_legs as index list.

Returns:

The children_legs where the values are the positions in

the permutation list.

Return type:

List[int]

children_legs_to_open_legs(children_id_list: List[str])

Changes multiple child legs into open legs.

The new legs will be the last legs of the node but in the same order as provided in the list.

Parameters:

children_id_list (List[str]) – A list of the identifiers of the child nodes which are to be turned into open legs.

exchange_open_leg_ranges(open_1: range, open_2: range)

Exchanges two continuous batches of open legs, with one another.

Parameters:
  • open_1 (range) – Each is one batch of open legs.

  • open_2 (range) – Each is one batch of open legs.

property leg_permutation

Get the leg permutation, cf. class docstring.

Links this node to a tensor, by saving its shape and dimension.

Parameters:

tensor (ndarray) – The tensor to be linked with this node.

nchild_legs() int

Returns the number of legs connected to child Nodes.

nlegs() int

Returns the total number of legs of this node.

nopen_legs()

Returns the number of open legs of this node.

nvirt_legs()

Returns the total number of legs to other nodes, i.e. parent + children.

open_dimension() int

Returns the total open dimension of this leg.

open_leg_to_child(child_id: str, open_leg: int)

Changes an open leg into the leg towards a child.

Children legs will be sorted in the same way as their ids are in the superclass.

Parameters:
  • child_id (str) – The identifier of the to be child node

  • open_leg (int) – The index of the tensor leg

open_leg_to_parent(parent_id: str, open_leg: int | None)

Changes an open leg into the leg towards a parent.

Parameters:
  • parent_id (str) – The identifier of the to be parent node

  • open_leg (int) – The index of the tensor leg

property open_legs: List[int]

Returns the indices of the open legs.

open_legs_to_children(child_dict: Dict[str, int])

Changes multiple open legs to be legs towards children.

Parameters:

child_dict (Dict[str, int]) – A dictionary that contains the identifiers of the to be children nodes as keys and the open leg that they should contract to as values.

property parent_leg: int

Returns the parent_leg as index.

Returns:

The parent_leg where the value is the position in the permutation

list. If there is no parent, None is returned.

Return type:

int

parent_leg_dim() int

Returns the dimension associated to the parent leg.

parent_leg_to_open_leg()

Changes the parent leg to be an open leg, if it exists.

The newly opened leg will be the last leg of the node.

property shape: Tuple | None

Returns the shape as it would be for the tranposed tensor.

E.g. the dimension of the parent leg is always output[0]. If no tensor is linked to this node, None is returned.

swap_two_child_legs(child_id1: str, child_id2: str)

Swaps the index position of two children.

swap_with_first_child(child_id: str)

Makes the leg of the given child the first of all children legs

pytreenet.core.tree_structure module

This module deals with the graph connectivity of a tree.

Essential to this is the tree structure class, that acts as a collection of all nodes of a tree. The methods provide various ways to gather information and change the connectivity of the tree.

class pytreenet.core.tree_structure.TreeStructure

Bases: object

The class holding the structure and connectivity of a tree.

Acts as a collection of nodes. These can be added and removed in relation to another. Furthermore information about the graph structure and connectivity can be extracted.

nodes

Hold the nodes belonging to the tree. It should be modified using the appropriate methods.

Type:

Dict[str,GraphNode]

root_id[str, None]

The identifier of the root node. This defines a direction on the tree. It is only None, if the tree contains no node.

add_child_to_parent(child: GraphNode, parent_id: str)

Adds a Node as a child to the specified parent_node.

Parameters:
  • child (GraphNode) – The node to be added

  • parent_id (str) – The identifier of the node which is to be the new parent.

add_parent_to_root(new_root: GraphNode)

Adds a parent to the root of this tree, making it the new root.

Parameters:

node (GraphNode) – The node to be added.

add_root(node: GraphNode)

Adds a root node to this tree.

Parameters:

node (GraphNode) – The node to be added.

determine_parentage(node_id1: str, node_id2: str) Tuple[str, str]

Orders two node identifiers by their parentage.

Parameters:
  • node_id1 (str) – Identifier of one node.

  • node_id2 (str) – A different identifier of a second node.

Returns:

The identifiers are in the forma

(parent_id, child_id)

Return type:

Tuple[str, str]

distance_to_node(center_node_id: str) Dict[str, int]

Finds the distance of every node in the tree to a given node.

The distance between two nodes is the number of edges that have to be traversed to go from one to the other.

Parameters:

center_node_id (str) – The identifier of the node to which the distance should be determined.

Returns:

The keys are node identifiers and the values are

the corresponding distance. The root will be the first entry followed by the first child, followed by the first grandchild. Once a leaf is reached, the closest unvisited node will be next.

Return type:

Dict[str, int]

ensure_existence(node_id: str)

Ensures that an identifier is already in this tree.

Parameters:

node_id (str) – Identifier to check.

Raises:

ValueError – Raised if there is no node with the identifier in this tree.

ensure_uniqueness(node_id: str)

Ensures that the given identifier is not already in use.

Parameters:

node_id (str) – Identifer to check.

Raises:

ValueError – Raised if the a node in this tree already has this identifier.

find_path_to_root(node_id: str) List[str]

Finds the path of a node to the root.

Parameters:

node_id (str) – The node from which to start the path.

Returns:

A list of all nodes on the path. The first entry is the

starting node and the last entry is the root node.

Return type:

List[str]

find_subtree_of_node(node_id: str) Dict[str, GraphNode]

Obtains the subtree from a given node towards the leaves of this tree.

This is done recursively.

Parameters:

node_id (str) – The identifier of the node from which the subtree should start.

Returns:

Contains the nodes of the subtree, keyed by the

identifier. Note that this is not a Tree class object, because the root still has a parent.

Return type:

Dict[str, Node]

find_subtree_size_of_node(node_id: str, size=0) int

Obtains the subtree size from a given node

Parameters:

node_id (str) – The identifier of the node from which the subtree should start.

Returns:

Size of subtree at node

Return type:

int

get_leaves() List[str]

Returns a list with the identifiers of all leaves.

is_child_of(pot_child: str, pot_parent: str) bool

Tests if one node is a child of the other.

Parameters:
  • pot_child (str) – Identifier of the potential child.

  • pot_parent (str) – Identifier of the potential parent.

Returns:

True if the first node is a child of the second.

Return type:

bool

is_parent_of(pot_parent: str, pot_child: str) bool

Tests if one node is a parent of the other.

Parameters:
  • pot_parent (str) – Identifier of the potential parent.

  • pot_child (str) – Identifier of the potential child.

Returns:

True if the first node is a parent of the second.

Return type:

bool

leaves_under_node(node_id: str) Dict[str, GraphNode]

Recursively finds all leaves below a given node.

Parameters:

node_id (str) – Node from which to start

Returns:

Contains all leaves that are in this tree

below the given node.

Return type:

Dict[str, GraphNode]

linearise() List[str]

Linearises the tree.

Returns:

The identifiers of the nodes in the order they are

visited. The children of a node will always appear before the node itself.

Return type:

List[str]

nearest_neighbours() List[Tuple[str, str]]

Finds all nearest neighbour pairs in this tree.

Returns:

A list containing the identifiers of all

nearest neighbour pairs. The first element of the tuple is the parent and the second the child. The order in the list is the same as the order of the nodes saved in the tree.

Return type:

nn_list (List[Tuple[str,str]])

property nodes: Dict[str, GraphNode]

Returns the nodes of this tree structure.

Can only be modified using the appropriate methods of the tree structure.

path_from_to(start_id: str, end_id: str) List[str]

Finds a path between two nodes.

Parameters:
  • start_id (str) – Identifier of start node.

  • end_id (str) – Identifier of end node.

Returns:

Identifiers of nodes that lie along the path. The first

indentifier is start_id and the last indentifier is end_id.

Return type:

List[str]

replace_node_in_neighbours(new_node_id: str, old_node_id: str)

Replaces a node in all neighbours of the old node.

Parameters:
  • new_node_id (str) – Identifier of the node to be added

  • old_node_id (atr) – Identifier of the node to be replaced

replace_node_in_some_neighbours(new_node_id: str, old_node_id: str, neighbour_ids: List[str])

Replaces a node for only some of its neighbours.

Parameters:
  • new_node_id (str) – The identifier of the new node

  • old_node_id (str) – The identifier of the node to be replaced

  • neighbour_ids (List[str]) – A list of node identifiers that are neighbours of the old node and for which the connection to the old node is to be replaced by a connection to the new node.

property root_id: None | str

Returns the root’s identifier.

pytreenet.core.ttn module

Provides the fundamental TreeTensorNetwork class.

The TreeTensorNetwork class is a subclass of the TreeStructure class and holds the structure of a tree tensor network (TTN) in the form of Nodes, as well as the tensors associated with these nodes. The TreeTensorNetwork class provides methods to manipulate the TTN, such as adding nodes, contracting nodes, or splitting nodes. It also provides methods to move the orthogonality center of the TTN.

Example:

from pytreenet import TreeTensorNetwork, Node, crandn
import numpy as np

# Create a TreeTensorNetwork
ttn = TreeTensorNetwork()

# Create a root node
root_tensor = crandn((2, 3, 4))
root_node = Node(identifier="root)
ttn.add_root(root_node, root_tensor)

# Create a child node
child_tensor = crandn((2, 2, 3))
child_node = Node(identifier="child1")
ttn.add_child_to_parent(child_node, child_tensor, 0, ttn.root_id, 0)

# Create a second child node
child_tensor2 = crandn((2, 3, 5))
child_node2 = Node(identifier="child2")
ttn.add_child_to_parent(child_node2, child_tensor2, 1, ttn.root_id, 1)

# Create a grandchild node
grandchild_tensor = crandn((2, 4))
grandchild_node = Node(identifier="grandchild")
ttn.add_child_to_parent(grandchild_node, grandchild_tensor, 0, "child2", 1)

# Contract the grandchild node with the child node
ttn.contract_nodes("child2", "grandchild")

For details and further usage refer to the example notebooks.

pytreenet.core.ttn.TTN

alias of TreeTensorNetwork

class pytreenet.core.ttn.TensorDict(nodes: Dict[str, Node], inpt: Dict[str, ndarray] | None = None)

Bases: UserDict

A custom dictionary class to store the tensors of a TreeTensorNetwork.

The class is connected to the nodes of the TreeTensorNetwork and ensures that the tensors are transposed only when they are accessed. Therefore tensor legs should be called using the nodes methods.

class pytreenet.core.ttn.TreeTensorNetwork

Bases: TreeStructure

A Tree Tensor Network (TTN)

A tree tensor network is a tensor network layed out as a tree. The data associated with each node is a tensor, stored using the same identifier as the node. A tensor associated to a node can have more legs than the node has neighbours. These legs are known as open legs. The TreeTensorNetwork class provides methods to manipulate the TTN, such as adding nodes, contracting nodes, or splitting nodes. It also provides methods to control the orthogonality center of the TTN.

orthogonality_center_id

The identifier of the node which is the orthogonality center of the TTN.

Type:

Union[str,None]

tensors

A dictionary mapping the tensor tree node identifiers to the corresponding tensor data.

Type:

TensorDict

root_id

The identifier of the root node of the TTN.

Type:

Union[str,None]

nodes

A dictionary mapping the node identifiers to the corresponding node.

Type:

Dict[str,Node]

absorb_into_open_legs(node_id: str, tensor: ndarray)

Absorb a tensor into the open legs of the tensor of a node.

This tensor will be absorbed into all open legs and it is assumed, the leg order of the tensor to be absorbed is the same as the order of the open legs of the node.

Since the tensor to be absorbed is considered to represent an operator acting on the node, it will have to have exactly twice as many legs as the node has open legs. The input legs, i.e. the ones contracted, are assumed to be the second half of the legs of the tensor.

Parameters:
  • node_id (str) – The identifier of the node which is to be contracted with the tensor

  • tensor (np.ndarray) – The tensor to be contracted.

absorb_matrix(node_id: str, absorbed_matrix: ndarray, this_tensors_leg_index: int, absorbed_matrix_leg_index: int = 1)

Absorbs a matrix into one of this TTN’s tensors at a given tensor leg.

Parameters:
  • node_id (str) – Identifier of the node/tensor into which the matrix should be absorbed.

  • absorbed_matrix (np.ndarray) – Matrix to be absorbed. Has to be a square matrix, as otherwise the tensor shape is changed. If you desire to contract a non-square matrix/ a higher-degree tensor, add a new child to this tensor and contract it with this tensor.

  • this_tensors_leg_index (int) – The leg of this TTN’s tensor that is to be contracted with the absorbed tensor.

  • absorbed_tensors_leg_index (int, Optional) – Leg that is to be contracted with this instance’s tensor. Defaults to 1, as this is usually considered to be the input leg of a matrix.

absorb_matrix_into_neighbour_leg(node_id: str, neighbour_id: str, tensor: ndarray, tensor_leg: int = 1)

Absorb a matrix into a node.

One of the legs of the matrix will be contracted into a neighbour leg of the node.

Parameters:
  • node_id (str) – The identifier of the node into which the tensor is absorbed

  • neighbour_id (str) – The identifier of the neighbour to which the leg points, which is to be contracted with the tensor

  • tensor (np.ndarray) – The tensor to be contracted

  • tensor_leg (int, optional) – The leg of the external tensor which is to be contracted. Defaults to 1, as this is usually the input leg of a matrix.

add_child_to_parent(child: Node, tensor: ndarray, child_leg: int, parent_id: str, parent_leg: int)

Adds a child node to a parent node in the TTN.

Note: Legs of the nodes might change during this operation to fit the convention (parent_leg,children_legs,open_legs)

Parameters:
  • child (Node) – The child node to be added.

  • tensor (np.ndarray) – The tensor associated with the child node.

  • child_leg (int) – The leg of the child tensor to be connected to the parent tensor.

  • parent_id (str) – The identifier of the parent node.

  • parent_leg (int) – The leg of the parent tensor to be connected to the child tensor.

Raises:

NotCompatibleException – If the dimensions of the legs of the child and parent are not the same.

add_parent_to_root(root_leg: int, parent: Node, tensor: ndarray, parent_leg: int)

Adds a parent node to the root node of the TTN.

Note: Legs of the nodes might change during this operation to fit the convention (parent_leg,children_legs,open_legs).

Parameters:
  • root_leg (int) – The leg of the root tensor to be connected to the parent tensor.

  • parent (Node) – The parent node to be added.

  • tensor (np.ndarray) – The tensor associated with the parent node.

  • parent_leg (int) – The leg of the parent tensor to be connected to the root tensor.

add_root(node: Node, tensor: ndarray)

Adds a root tensor node to the TTN.

Parameters:
  • node (Node) – The root node to be added.

  • tensor (np.ndarray) – The tensor associated with the root node.

bond_dim(node_id: str, neighbour_id: str | None = None) int

Find the bond dimension between a node and one of its neighbours.

Parameters:
  • node_id (str) – The identifier of the node.

  • neighbour_id (Union[str,None], optional) – The identifier of the neighbour node. If None, the parent is used. Defaults to None.

bond_dims() Dict[Tuple[str, str], int]

Returns the bond dimensions between all neighbouring nodes.

Returns:

The bond dimensions between

neighbouring nodes. The keys are the node identifiers of the parent and child node in that order.

Return type:

Dict[Tuple[str, str], int]

canonical_form(orthogonality_center_id: str, mode: SplitMode = SplitMode.REDUCED)
Brings the TTN in canonical form with respect to a given orthogonality

center.

Parameters:
  • orthogonality_center_id (str) – The new orthogonality center of the TTN.

  • mode – The mode to be used for the QR decomposition. For details refer to tensor_util.tensor_qr_decomposition.

completely_contract_tree(to_copy: bool = False) Tuple[ndarray, List[str]]

Completely contracts the given TTN by combining all nodes.

(WARNING: Can get very costly very fast. Only use for debugging.)

Parameters:
  • ttn (TreeTensorNetwork) – The TTN to be contracted.

  • to_copy (bool) – Wether or not the contraction should be perfomed on a deep copy. Default is False.

Returns:

The contracted TTN and the list of

the identifiers of the contracted nodes in the order they were contracted. The latter is very useful for debugging.

Return type:

Tuple[np.ndarray, List[str]]

conjugate() TreeTensorNetwork

Returns a conjugated version of this TTN.

This means for every tensor in the TTN, the complex conjugate is taken.

contract_nodes(node_id1: str, node_id2: str, new_identifier: str = '')

Contracts two nodes.

This means a new node with the contracted tensor is inserted into the ttn with the result of the tensor contraction of the other nodes as the associated tensor. Note that one of the nodes has to be the parent of the other. The resulting leg order is the following:

(parent_parent_leg, node1_children_legs, node2_children_legs, node1_open_legs, node2_open_legs)

The resulting node will have the identifier

parent_id + "contr" + child_id

unless an alternative is provided.

Note that this removes the original nodes and tensors from the TTN.

Parameters:
  • node_id1 (str) – Identifier of first tensor

  • node_id2 (str) – Identifier of second tensor

  • new_identifier (str, optional) – A potential new identifier.

  • node_id2. (Otherwise defaults to node_id1 + "contr" +)

ensure_shape_matching(new_tensor: ndarray, tensor_leg: int, old_node: Node, old_leg: int, new_node_id: str | None = None)

Ensures that the dimensions of the legs of two tensors are compatible.

Parameters:
  • new_tensor (np.ndarray) – The tensor with the new leg.

  • tensor_leg (int) – The leg of the new tensor to be compared.

  • old_node (Node) – The node with the old leg.

  • old_leg (int) – The leg of the old node to be compared.

  • new_node_id (Union[str,None], optional) – The identifier of the new node. Defaults to None.

Raises:

NotCompatibleException – If the dimensions of the legs of the two tensors are not compatible.

legs_before_combination(node1_id: str, node2_id: str) Tuple[LegSpecification, LegSpecification]

Records which leg corresponds to which node.

When combining two nodes, the information about their legs is lost. However, sometimes one wants to split the two nodes again, as they were before. This function provides the required leg specification for the splitting.

Parameters:
  • node1_id (str) – Identifier of the first node to be combined

  • node2_id (str) – Identifier of the second node to be combined

Returns:

The leg specifications

containing the information to split the two nodes again, to have the same legs as before (assuming the open legs are not transposed). Since it is not needed the LegSpecification of the parent node has the identifier of the child node not included. Same for the LegSpecification of the child node and the parent legs. The open legs are the index values that the legs would have after contracting the two nodes.

Return type:

Tuple[LegSpecification, LegSpecification]

max_bond_dim() int

Find the maximum virtual bond dimension in this TTN.

Returns:

The maximum bond dimension of this TTN.

Return type:

int

move_orthogonalization_center(new_center_id: str, mode: SplitMode = SplitMode.REDUCED)

Moves the orthogonalization center to a different node.

For this to work the TTN has to be in a canonical form already, i.e., there should already be an orthogonalisation center.

Parameters:
  • new_center (str) – The identifier of the new orthogonalisation center.

  • mode – The mode to be used for the QR decomposition. For details refer to tensor_util.tensor_qr_decomposition.

nodes_equal(node_id: str, other: TreeTensorNetwork, other_node_id: str | None = None) bool

Compares a node in this tree with a node in a different TTN.

Parameters:
  • node_id (str) – Identifier of a node in this TTN to use for comparison.

  • other (TreeTensorNetwork) – A different TTN to compare to.

  • other_node_id (Union[None, str]) – A node identifier for the node in the other tree. If it is None, the same identifier is used for both TTN. Defaults to None.

Returns:

If the two nodes are equal and the associated tensors close

to each other.

Return type:

bool

num_nodes() int

Returns the number of nodes in the TTN.

Returns:

The number of nodes in the TTN.

Return type:

int

orthogonalize(orthogonality_center_id: str, mode: SplitMode = SplitMode.REDUCED)

Wrapper of canonical form.

Parameters:
  • orthogonality_center_id (str) – The new orthogonality center of the TTN.

  • mode – The mode to be used for the QR decomposition. For details refer to tensor_util.tensor_qr_decomposition.

property root: Tuple[Node, ndarray]

Returns the root node and the associated tensor

Returns:

The root node and the associated tensor.

Return type:

Tuple[Node, np.ndarray]

Raises:

KeyError – If there is no root in the TTN.

split_node_qr(node_id: str, q_legs: LegSpecification, r_legs: LegSpecification, q_identifier: str = '', r_identifier: str = '', mode: SplitMode = SplitMode.REDUCED)

Splits a node into two nodes via QR-decomposition.

Parameters:
  • node_id (str) – Identifier of the node to be split

  • q_legs (LegSpecification) – The legs which should be part of the Q-tensor

  • r_legs (LegSpecification) – The legs which should be part of the R-tensor

  • q_identifier (str, optional) – An identifier for the Q-tensor. Defaults to “”.

  • r_identifier (str, optional) – An identifier for the R-tensor. Defaults to “”.

  • mode – The mode to be used for the QR decomposition. For details refer to tensor_util.tensor_qr_decomposition.

split_node_svd(node_id: str, u_legs: LegSpecification, v_legs: LegSpecification, u_identifier: str = '', v_identifier: str = '', svd_params: SVDParameters = SVDParameters(max_bond_dim=100, rel_tol=0.01, total_tol=1e-15, renorm=True))

Splits a node in two using singular value decomposition.

In the process the tensors are truncated as specified by truncation parameters. The singular values are absorbed into the v_legs.

Parameters:
  • node_id (str) – Identifier of the nodes to be split

  • u_legs (LegSpecification) – The legs which should be part of the U tensor

  • v_legs (LegSpecification) – The legs which should be part of the V tensor

  • u_identifier (str, optional) – An identifier for the U-tensor. Defaults to “”

  • v_identifier (str, optional) – An identifier for the V-tensor. Defaults to “”.

split_nodes(node_id: str, out_legs: LegSpecification, in_legs: LegSpecification, splitting_function: Callable, out_identifier: str = '', in_identifier: str = '', **kwargs)

Splits an node into two nodes using a specified function

Parameters:
  • node_id (str) – The identifier of the node to be split.

  • out_legs (LegSpecification) – The legs associated to the output of the matricised node tensor. (The Q legs for QR and U legs for SVD)

  • in_legs (LegSpecification) – The legs associated to the input of the matricised node tensor: (The R legs for QR and the SVh legs for SVD)

  • splitting_function (Callable) – The function to be used for the splitting

  • out_identifier (str, optional) – An identifier for the tensor with the

  • "". (output legs. Defaults to)

  • in_identifier (str, optional) – An identifier for the tensor with the input legs. Defaults to “”.

  • **kwargs – Are passed to the splitting function.

property tensors: TensorDict[str, ndarray]

Returns the tensors of the TTN.

Since during addition of nodes the tensors are not actually transposed, this has to be done here. This way whenever tensors are accessed, their leg ordering is

(parent_leg, children_legs, open_legs)

The tensors are collected in a diciotnary, where the keys are the node identifiers.