7.5. Tagged UniTensor

In this section we introduce tagged UniTensor, which is a UniTensor with directional bonds. Mathematically, a bond directing towards a tensor represents a vectorspace, while a bond directing away from a tensor represents the corresponding dual space. In physics, this is often represented as a “Ket” or “Bra” vector. We use the convention that “Ket” is represented by a bond directing towards the tensor, while “Bra” points away from the tensor.

If symmetric tensors are considered, the bonds carry quantum numbers and are always tagged. Therefore, tagged UniTensors can further be categorized into non-symmetric and symmetric (block form) tensors. The latter are covered in UniTensor with Symmetries.

7.5.1. Non-symmetric Tagged UniTensor

To create the non-symmetric, tagged UniTensor, we initialize it with directional bonds (BD_IN/BD_KET or BD_OUT/BD_BRA). Let’s create UniTensors Ta, Tb and Tc in this way and investigate their properties:

  • In Python:

 1bond_a = cytnx.Bond(3, cytnx.BD_KET)
 2bond_b = cytnx.Bond(3, cytnx.BD_BRA)
 3Ta = cytnx.UniTensor([bond_a, bond_a, bond_b],
 4                     labels=["a", "b", "c"],
 5                     rowrank = 2)
 6Ta.set_name("Ta")
 7Ta.print_diagram()
 8Tb = cytnx.UniTensor([bond_a, bond_b, bond_b],
 9                     labels=["c", "d", "e"],
10                     rowrank = 1)
11Tb.set_name("Tb")
12Tb.print_diagram()
13Tc = cytnx.UniTensor([bond_b, bond_b, bond_b],
14                     labels=["c", "d", "e"],
15                     rowrank = 1)
16Tc.set_name("Tc")
17Tc.print_diagram()

Output >>

-----------------------
tensor Name : Ta
tensor Rank : 3
block_form  : False
is_diag     : False
on device   : cytnx device: CPU
braket_form : True
      row           col
         -----------
         |         |
   a  -->| 3     3 |-->  c
         |         |
   b  -->| 3       |
         |         |
         -----------
-----------------------
tensor Name : Tb
tensor Rank : 3
block_form  : False
is_diag     : False
on device   : cytnx device: CPU
braket_form : True
      row           col
         -----------
         |         |
   c  -->| 3     3 |-->  d
         |         |
         |       3 |-->  e
         |         |
         -----------
-----------------------
tensor Name : Tc
tensor Rank : 3
block_form  : False
is_diag     : False
on device   : cytnx device: CPU
braket_form : False
      row           col
         -----------
         |         |
   c *<--| 3     3 |-->  d
         |         |
         |       3 |-->  e
         |         |
         -----------

In this example, the UniTensors Ta and Tb are created to be in the braket form (braket_form : True). This means that all bonds in the rowspace are Kets (inward) and all the bonds in the colspace are Bras(outward), which can be seen in the diagram as well. The property rowrank of a UniTensor defines these spaces: the first bonds are part of rowspace, and rowspace contains rowrank bonds.

Two bonds can only be contracted when one of them corresponds to a Ket state (living in a vector space) and the other is Bra state (living in the dual space). Therefore, two bonds with conflicting directions cannot be contract with each other. While this is certainly a constraint, this condition makes the implementation of tensor network algorithms less error-prone since incompatible bond directions will not be contracted.

To demonstrate this, we use Contract and try:

1cytnx.Contract(Ta, Tb)
2cytnx.Contract(Ta, Tc)

While the first contraction works well, the second one throws a RuntimeError stating “BRA-KET mismatch”:

Output >>

# Cytnx error occur at virtual boost::intrusive_ptr<cytnx::UniTensor_base> cytnx::DenseUniTensor::contract(const boost::intrusive_ptr<cytnx::UniTensor_base>&, const bool&, const bool&)
# error: [ERROR][DenseUniTensor][contract] cannot contract common label: <c> @ self bond#2 & rhs bond#0, BRA-KET mismatch!