209 lines
6.6 KiB
Plaintext
209 lines
6.6 KiB
Plaintext
|
@q $Id: symmetry.hweb 841 2006-07-27 14:41:11Z tamas $ @>
|
||
|
@q Copyright 2004, Ondra Kamenik @>
|
||
|
|
||
|
@*2 Symmetry. This is {\tt symmetry.h} file
|
||
|
|
||
|
Symmetry is an abstraction for a term of the form $y^3u^2$. It manages
|
||
|
only indices, not the variable names. So if one uses this
|
||
|
abstraction, he must keep in mind that $y$ is the first, and $u$ is
|
||
|
the second.
|
||
|
|
||
|
In fact, the symmetry is a special case of equivalence, but its
|
||
|
implementation is much simpler. We do not need an abstraction for the
|
||
|
term $yyuyu$ but due to Green theorem we can have term $y^3u^2$. That
|
||
|
is why the equivalence is too general for our purposes.
|
||
|
|
||
|
One of a main purposes of the tensor library is to calculate something like:
|
||
|
$$\left[B_{y^2u^3}\right]_{\alpha_1\alpha_2\beta_1\beta_2\beta_3}
|
||
|
=\left[g_{y^l}\right]_{\gamma_1\ldots\gamma_l}
|
||
|
\left(\sum_{c\in M_{l,5}}
|
||
|
\prod_{m=1}^l\left[g_{c_m}\right]^{\gamma_m}_{c_m(\alpha,\beta)}\right)$$
|
||
|
If, for instance, $l=3$, and $c=\{\{0,4\},\{1,2\},\{3\}\}$, then we
|
||
|
have to calculate
|
||
|
$$\left[g_{y^3}\right]_{\gamma_1\gamma_2\gamma_3}
|
||
|
\left[g_{yu}\right]^{\gamma_1}_{\alpha_1\beta_3}
|
||
|
\left[g_{yu}\right]^{\gamma_2}_{\alpha_2\beta_1}
|
||
|
\left[g_u\right]^{\gamma_3}_{\beta_2}
|
||
|
$$
|
||
|
|
||
|
We must be able to calculate a symmetry induced by symmetry $y^2u^3$
|
||
|
and by an equivalence class from equivalence $c$. For equivalence
|
||
|
class $\{0,4\}$ the induced symmetry is $yu$, since we pick first and
|
||
|
fifth variable from $y^2u^3$. For a given outer symmetry, the class
|
||
|
|InducedSymmetries| does this for all classes of a given equivalence.
|
||
|
|
||
|
We need also to cycle through all possible symmetries yielding the
|
||
|
given dimension. For this purpose we define classes |SymmetrySet| and
|
||
|
|symiterator|.
|
||
|
|
||
|
The symmetry is implemented as |IntSequence|, in fact, it inherits
|
||
|
from it.
|
||
|
|
||
|
@s Symmetry int
|
||
|
@s IntSequence int
|
||
|
@s SymmetrySet int
|
||
|
@s symiterator int
|
||
|
@s OrdSequence int
|
||
|
@s InducedSymmetries int
|
||
|
|
||
|
@c
|
||
|
#ifndef SYMMETRY_H
|
||
|
#define SYMMETRY_H
|
||
|
|
||
|
#include "equivalence.h"
|
||
|
#include "int_sequence.h"
|
||
|
|
||
|
#include <list>
|
||
|
#include <vector>
|
||
|
|
||
|
@<|Symmetry| class declaration@>;
|
||
|
@<|SymmetrySet| class declaration@>;
|
||
|
@<|symiterator| class declaration@>;
|
||
|
@<|InducedSymmetries| class declaration@>;
|
||
|
|
||
|
#endif
|
||
|
|
||
|
@ Clear. The method |isFull| returns true if and only if the symmetry
|
||
|
allows for any permutation of indices.
|
||
|
|
||
|
@<|Symmetry| class declaration@>=
|
||
|
class Symmetry : public IntSequence {
|
||
|
public:@/
|
||
|
@<|Symmetry| constructors@>;
|
||
|
int num() const
|
||
|
{@+return size();@+}
|
||
|
int dimen() const
|
||
|
{@+return sum();@+}
|
||
|
int findClass(int i) const;
|
||
|
bool isFull() const;
|
||
|
};
|
||
|
|
||
|
@ We provide three constructors for symmetries of the form $y^n$,
|
||
|
$y^nu^m$, $y^nu^m\sigma^k$. Also a copy constructor, and finally a
|
||
|
constructor of implied symmetry for a symmetry and an equivalence
|
||
|
class. It is already implemented in |IntSequence| so we only call
|
||
|
appropriate constructor of |IntSequence|. We also provide the
|
||
|
subsymmetry, which takes the given length of symmetry from the end.
|
||
|
|
||
|
The last constructor constructs a symmetry from an integer sequence
|
||
|
(supposed to be ordered) as a symmetry counting successively equal
|
||
|
items. For instance the sequence $(a,a,a,b,c,c,d,d,d,d)$ produces
|
||
|
symmetry $(3,1,2,4)$.
|
||
|
|
||
|
@<|Symmetry| constructors@>=
|
||
|
Symmetry(int len, const char* dummy)
|
||
|
: IntSequence(len, 0)@+ {}
|
||
|
Symmetry(int i1)
|
||
|
: IntSequence(1, i1)@+ {}
|
||
|
Symmetry(int i1, int i2)
|
||
|
: IntSequence(2) {@+operator[](0) = i1;@+ operator[](1) = i2;@+}
|
||
|
Symmetry(int i1, int i2 ,int i3)
|
||
|
: IntSequence(3)
|
||
|
{@+
|
||
|
operator[](0) = i1;@+
|
||
|
operator[](1) = i2;@+
|
||
|
operator[](2) = i3;@+
|
||
|
}
|
||
|
Symmetry(int i1, int i2 ,int i3, int i4)
|
||
|
: IntSequence(4)
|
||
|
{@+
|
||
|
operator[](0) = i1;@+
|
||
|
operator[](1) = i2;@+
|
||
|
operator[](2) = i3;@+
|
||
|
operator[](3) = i4;@+
|
||
|
}
|
||
|
Symmetry(const Symmetry& s)
|
||
|
: IntSequence(s)@+ {}
|
||
|
Symmetry(const Symmetry& s, const OrdSequence& cl)
|
||
|
: IntSequence(s, cl.getData())@+ {}
|
||
|
Symmetry(Symmetry& s, int len)
|
||
|
: IntSequence(s, s.size()-len, s.size())@+ {}
|
||
|
Symmetry(const IntSequence& s);
|
||
|
|
||
|
@ The class |SymmetrySet| defines a set of symmetries of the given
|
||
|
length having given dimension. It does not store all the symmetries,
|
||
|
rather it provides a storage for one symmetry, which is changed as an
|
||
|
adjoint iterator moves.
|
||
|
|
||
|
The iterator class is |symiterator|. It is implemented
|
||
|
recursively. The iterator object, when created, creates subordinal
|
||
|
iterator, which iterates over a symmetry set whose length is one less,
|
||
|
and dimension is the former dimension. When the subordinal iterator
|
||
|
goes to its end, the superordinal iterator increases left most index in
|
||
|
the symmetry, resets the subordinal symmetry set with different
|
||
|
dimension, and iterates through the subordinal symmetry set until its
|
||
|
end, and so on. That's why we provide also |SymmetrySet| constructor
|
||
|
for construction of a subordinal symmetry set.
|
||
|
|
||
|
The typical usage of the abstractions for |SymmetrySet| and
|
||
|
|symiterator| is as follows:
|
||
|
|
||
|
\kern0.3cm
|
||
|
\centerline{|for (symiterator si(SymmetrySet(6, 4)); !si.isEnd(); ++si) {body}|}
|
||
|
\kern0.3cm
|
||
|
|
||
|
\noindent It goes through all symmetries of size 4 having dimension
|
||
|
6. One can use |*si| as the symmetry in the body.
|
||
|
|
||
|
@<|SymmetrySet| class declaration@>=
|
||
|
class SymmetrySet {
|
||
|
Symmetry run;
|
||
|
int dim;
|
||
|
public:@;
|
||
|
SymmetrySet(int d, int length)
|
||
|
: run(length, ""), dim(d)@+ {}
|
||
|
SymmetrySet(SymmetrySet& s, int d)
|
||
|
: run(s.run, s.size()-1), dim(d)@+ {}
|
||
|
int dimen() const
|
||
|
{@+ return dim;@+}
|
||
|
const Symmetry& sym() const
|
||
|
{@+ return run;@+}
|
||
|
Symmetry& sym()
|
||
|
{@+ return run;@+}
|
||
|
int size() const
|
||
|
{@+ return run.size();@+}
|
||
|
};
|
||
|
|
||
|
@ The logic of |symiterator| was described in |@<|SymmetrySet| class
|
||
|
declaration@>|. Here we only comment that: the class has a reference
|
||
|
to the |SymmetrySet| only to know dimension and for access of its
|
||
|
symmetry storage. Further we have pointers to subordinal |symiterator|
|
||
|
and its |SymmetrySet|. These are pointers, since the recursion ends at
|
||
|
length equal to 2, in which case these pointers are |NULL|.
|
||
|
|
||
|
The constructor creates the iterator which initializes to the first
|
||
|
symmetry (beginning).
|
||
|
|
||
|
@<|symiterator| class declaration@>=
|
||
|
class symiterator {
|
||
|
SymmetrySet& s;
|
||
|
symiterator* subit;
|
||
|
SymmetrySet* subs;
|
||
|
bool end_flag;
|
||
|
public:@;
|
||
|
symiterator(SymmetrySet& ss);
|
||
|
~symiterator();
|
||
|
symiterator& operator++();
|
||
|
bool isEnd() const
|
||
|
{@+ return end_flag;@+}
|
||
|
const Symmetry& operator*() const
|
||
|
{@+ return s.sym();@+}
|
||
|
};
|
||
|
|
||
|
|
||
|
@ This simple abstraction just constructs a vector of induced
|
||
|
symmetries from the given equivalence and outer symmetry. A
|
||
|
permutation might optionally permute the classes of the equivalence.
|
||
|
|
||
|
@<|InducedSymmetries| class declaration@>=
|
||
|
class InducedSymmetries : public vector<Symmetry> {
|
||
|
public:@;
|
||
|
InducedSymmetries(const Equivalence& e, const Symmetry& s);
|
||
|
InducedSymmetries(const Equivalence& e, const Permutation& p, const Symmetry& s);
|
||
|
void print() const;
|
||
|
};
|
||
|
|
||
|
|
||
|
|
||
|
@ End of {\tt symmetry.h} file.
|