% function contractQS()
Contract set of QSpace tensors in a pairwise fashion
as described with usage #1 and #2 below. This automatically
also takes care of the underlying Clebsch Gordan coefficient
spaces if present based on X-symbols.
Each QSpace can be used as is, or as its 'conjugate' where the
conjugate of a QSpace A, i.e. conj(A) is defined as the QSpace
1) with all `arrows' reversed
2) keeping the SAME qlabels on all legs
3) and complex conjugation of all data{} if applicable,
i.e., if the (reduced) matrix elements are complex.
Because of (1), the specification of conjugate flags (`conj-flags')
is also important for QSpaces with all-real matrix elements.
For reversing individual arrows, see getIdentitQS(..,'-0').
Usage #1: S=contractQS(A, ica, B, icb [, perm, OPTS ]);
Plain contraction of a single pair of QSpaces, A and B,
with respect to given explicitly specified sets of
contraction indices ica and icb, which can be specified
- numerically (e.g. [1 2]),
- or as strings (e.g. '1,2', or '1 2')
- or as compact strings (e.g. '1,2', or '12')
The last 'compact format' is only possible / unique,
of course, if the tensors A and B do not have more than
9 legs (which basically never occurs), such that the
contraction indices reamin in the single digits
(this can be further relaxed, though, by extending the
digital range to letter, i.e. using a-z after 0-9).
The recommended way to specify conj-flag with usage #1
is together with the contraction indices in string notation!
For example,
contractQS(A,[1 3],B,[1 3],'conjA') is equivalent to
contractQS(A,'1,3;*',B,[1 3]) is equivalent to
contractQS(A,'13*',B,'13')
(deprecated) options specific to usage #1:
'conjA' use complex conjugate of A for contraction
'conjB' use complex conjugate of B for contraction
Usage #2: S=contractQS(A,..,{B,..,{C,..}},.. [, perm, OPTS ]);
Generalized 'cell-contraction' of tensors: when encountering
a cell, the content of that cell is contracted first, before
using its result. This allows the specification of an entire
patter of pairwise contractions based on a nested cell structure
where the lowest-level contractions are performed first.
An optional fully enveloping outer cell bracket at `base' level
as in S=contractQS({A,..,{B,..,{C,..}},..} [, perm, OPTS ])
is permitted, which may be used e.g., when debugging nested
parts of cell-contractions.
Cell contractions are furthermore based on QSpace `itags'
i.e. string labels for indices with up to 8chars, and which
are specified in QSpace.info.itags. This offers automated
contraction ('auto-contraction') of pairs of tensors solely
based on matching itags! Uusage #2 therefore does not (also)
allow explicit specification of contraction indices as in
usage #1. Therefore itags (plus conj-flags) must be unique.
itags must always also contain individual conjugate flags
(this represent the bare minimum that must be specified with
each QSpacein v3): the conjugate flags on individual indices
(legs) of a tensor determine whether that index (leg) is
in- or out-going, with the convention that
all out-going indices have a trailing * in their itags!
For example, an A-tensor with L(eft), R(ight), s(=local)
indices may have itags A.info.itags={'L','R*',s'}
assuming (L,R,s) index order.
In usage #2, for every operator additional optional strings
can be specified, appearing right after the affected tensor
e.g. QSpace A:
A,'*' apply overall (complex) conjugation on given input
tensor A (see early comments above)
A,'!ij' do not contract indices specified by ij (in compact
format) despite they share common matching itags.
A,'!ij*' both of the above in a single instruction
the conjugate flag '*' always trailing.
A,'ij' [07/2023]
A,'ij*' explicitly specify indices to contract
this is intended only for the case of degenerate itags
i.e., when identical itags appear on multiple legs
including the same conjugate flag.
itags may be set or adapted on the fly (this is performed
prior to the auto-contraction together wit the above directions)
X,'--op:<tag>[:<opl=op>]'
specify itags for given (e.g. local) operator.
The last option considers X an operator, and hence assumes
operator itags '<tag>;<tag>*[;opl*]' for QSpace X;
the default operator label is `op', but may be changed
by specifying a trailing ':<opl>' as indicated above.
As a safeguard, this issues a warning, if existing itags are
overwritten. This is relevant e.g. for local operators that
are applied to a very specific site with associated itag.
[11/2018] the specified <tag> may now also represent
a regular expression (regexp), recognized by non-alphabetic
special characters, while ignoring conj-flags (without
special characters, the specified <tag> is taken as is!).
This usage then searches for a matching itag in the paired
up QSpace (cell) in the contraction.
Ex. Consider A some QSpace with a single local index
that starts with `s', e.g., like 's010' for site 10;
then contract(A,Xloc,'-op:^s') will autocontract
the local operator Xloc to the correct local index in A
(here the regex `^s' indicates `starts with s');
An alternative operator itag may still be specified
by adding a trailing ':opl' as indicated earlier.
A,'--itag:s/pat/rep/[gi] [07/2023]
replace/modify existing itags on the fly for a particular
recursive level of a cell contraction based on regular
expressions (regex; using ECMAScript grammar, cf. C++/regex).
The syntax is much analogous to perl regex.
The trailing flags enable case insensitive replacement [i]
and global replacement [g] of all possible matches
(by default, only the first match is replaced).
An adaptation of usage #2 can also be used
for plain sequential contractions
S=contractQS(A [,flagsA],B [,flagsB],C,... [, perm, OPTS ])
which is equivalent to
S=contractQS({A [,flagsA],{B [,flagsB], {C,...}}}, [,perm,OPTS ]).
That is, by grouping A*(B*(C*...)), sequential contractions start
from the right end onwards to the beginning of the specified set.
This structure is also permitted at any lower level inside cell
contractions. Non-contracted indices are always collected in the
order they appear in the input.
The remaining trailing OPTS are
perm optional permutation (non-string) on the final object;
this permutation can be shorter than the actual rank
of the resulting QSpace, which then is completed as
an identity permutation on the remainder of indices.
By permitting the specification of indices to contract
also in contractions based on itags (cell-contractions)
there is a potential ambiguity of whether perm should
be interpreted as indices on the last specified tensor
(the latter may also be represented in compact string
format for better differentiation).
Hence the rules for perm to be interpreted as permutation
requires that (i) it is a valid permutation of length
r>=2 to start with, and (ii) that it is in numeric format,
i.e., not written as compact string. Valid examples are
[2 1], [2 3 1], but not, e.g., 1, [2 3], or '21'.
The ambiguity above is fully circumvented when also
wrapping the last contraction at base level into a cell,
such as contractQS({A,...},perm [,'-v']) [see above],
in which case perm is always interpreted as permutation
on the overall result, irrespective of rank or whether
specified as numeric or compact string index. In case
of a string, this then also permits to specify an optional
conjugate flag to be applied on the overall result.
'-v' debug mode that shows all levels of a cell contraction
together with the actual contractions performed
based on shown itags. Internally, degenerate itags are
frequently flagged by making use of signed characters,
which makes them unique and thus differentiate them.
When printed, flagged itags are formatted as "<itag>|b"
where the character `|' separates the actual itag string
from number b (int8 decimal) which in its binary form
reflects the internal flags.
Mixed usage of #2 and #1 is not possible.
Usage #2 is typically recommended because auto-contraction
makes it far easier to contract entire networks in a single go
without having to manually track and specify index locations.
AW (C) May 2010-2023
% --------------------------------------------------------------------
% CHANGE LOG
% --------------------------------------------------------------------
% [07/2023] cell-contraction now also permits
explicit specification of index to contract for particular
QSpace on compact notation such as '12' equivalent to [1 2]
rather than just excluding indices that could be contracted
based on matching itags.
% [07/2023] introduced '--itag:s/pat/rep/[gi]
% [07/2023] replaced '-op: by '--op:'
yet with '-op:' still permitted for backward compatibility
% --------------------------------------------------------------------