Contraction

The contraction of tensors can be done by contract (which is the wrap-up of MEX function contractQS). By exploiting symmetries, the contraction of QSpace objects is done for every symmetry sectors. Only the sectors of two tensors, whose quantum numbers are identical, are to be contracted. And the QSpace library automatically and seamlessly treats the contraction of the Clebsch-Gordan coefficients; we users need to only care about reduced matrix elements.

For example, the particle number operator \(\hat{n} =\sum_{\sigma } {\hat{f} }_{\sigma }^{\dagger } {\hat{f} }_{\sigma }\) can be obtained by:

NF = contract(F, '1,3;*',F, '1,3') 
NF =
    Q: 2x [2 2] having 'A,SU2',     { , * }   
 data: 2-D double (224 bytes)       2 x 2 => 3 x 3

    1. 1x1      | 2x2         [ 0 1 ; 0 1 ]           1.  {1.414}
    2. 1x1      | 1x1         [ 1 0 ; 1 0 ]           2.

We see that the sector of quantum number [0 1]has one particle (see .data{1} is 1) and the sector of [1 0] has two (see .data{2} is 2).

In the usage of contract, * at the end of the second input '1,3;*'means that the first input F is complex conjugated before contraction. And '1,3' in the second and fourth inputs mean that the first legs ('1' and '1' each) and the third legs ('3' and '3'each) are contracted, respectively. The tensor network diagram for this is:

Alt Text

Here F* means the complex conjugate to F.

By using itags, the contraction can be made simpler. For example, the number operator can be obtained by:

F1 = F;
F1.info.itags = { 's00', 's00*', 'op*'};
NF = contract(F1,'!2*',F1) 

NF =
    Q: 2x [2 2] having 'A,SU2',     { s00, s00* }   
 data: 2-D double (224 bytes)       2 x 2 => 3 x 3

    1. 1x1      | 2x2         [ 0 1 ; 0 1 ]           1.  {1.414}
    2. 1x1      | 1x1         [ 1 0 ; 1 0 ]           2.

In the usage of contract here, '*' at the end of the second input '!2*' means that the first input F is complex conjugated, and '!2' in the second input means that all the legs of the first input except the second leg are contracted to the legs of the third input, as long as their itags match. Only the pair of outward leg (e.g., with itag 's00*') and inward leg (e.g., with itag 's00') of the same name can be contracted.** Here, the first legs and the third legs have compatible itags, so they are contracted.

Also, the contract function supports multiple contractions in a single line syntax. For example, the squared number operator \(\sum_{\sigma \sigma^{\prime } } {\hat{f} }_{\sigma }^{\dagger } {\hat{f} }_{\sigma } {\hat{f} }_{\sigma^{\prime } }^{\dagger } {\hat{f} }_{\sigma^{\prime } }\) can be obtained by:

N2 = contract(F1, '!2*',{F1, '!1',{F1,  '!2*',F1}});
N2 =
    Q: 2x [2 2] having 'A,SU2',     { s00, s00* }   
 data: 2-D double (224 bytes)       2 x 2 => 3 x 3

    1. 1x1      | 2x2         [ 0 1 ; 0 1 ]           1.  {1.414}
    2. 1x1      | 1x1         [ 1 0 ; 1 0 ]           4.

In such syntax, the contraction inside the inner-most parenthesis { } is performed first, and then the contraction for the next inner-most parenthesis is done, and so on. In the above example, the parenthesis are given so that the contraction is performed over two right-most tensors, and contract the left ones iteratively. For details, type:

>> contractQS -?