87 lines
3.0 KiB
Plaintext
87 lines
3.0 KiB
Plaintext
@q $Id: pyramid_prod.cweb 148 2005-04-19 15:12:26Z kamenik $ @>
|
|
@q Copyright 2004, Ondra Kamenik @>
|
|
|
|
@ Start of {\tt pyramid\_prod.cpp} file.
|
|
@c
|
|
|
|
#include "pyramid_prod.h"
|
|
#include "permutation.h"
|
|
#include "tl_exception.h"
|
|
|
|
@<|USubTensor| constructor code@>;
|
|
@<|USubTensor::addKronColumn| code@>;
|
|
|
|
|
|
@ Here we construct the |USubTensor| object. We allocate space via the
|
|
parent |URTensor|. Number of columns is a length of the list of
|
|
indices |lst|, number of variables and dimensions are of the tensor
|
|
$h$, this is given by |hdims|.
|
|
|
|
We go through all equivalences with number of classes equal to
|
|
dimension of $B$. For each equivalence we make a permutation
|
|
|per|. Then we fetch all the necessary tensors $g$ with symmetries
|
|
implied by symmetry of $B$ and the equivalence. Then we go through the
|
|
list of indices, permute them by the permutation and add the Kronecker
|
|
product of the selected columns. This is done by |addKronColumn|.
|
|
|
|
@<|USubTensor| constructor code@>=
|
|
USubTensor::USubTensor(const TensorDimens& bdims,
|
|
const TensorDimens& hdims,
|
|
const FGSContainer& cont,
|
|
const vector<IntSequence>& lst)
|
|
: URTensor(lst.size(), hdims.getNVX()[0], hdims.dimen())
|
|
{
|
|
TL_RAISE_IF(! hdims.getNVX().isConstant(),
|
|
"Tensor has not full symmetry in USubTensor()");
|
|
const EquivalenceSet& eset = cont.getEqBundle().get(bdims.dimen());
|
|
zeros();
|
|
for (EquivalenceSet::const_iterator it = eset.begin();
|
|
it != eset.end(); ++it) {
|
|
if ((*it).numClasses() == hdims.dimen()) {
|
|
Permutation per(*it);
|
|
vector<const FGSTensor*> ts =
|
|
cont.fetchTensors(bdims.getSym(), *it);
|
|
for (int i = 0; i < (int)lst.size(); i++) {
|
|
IntSequence perindex(lst[i].size());
|
|
per.apply(lst[i], perindex);
|
|
addKronColumn(i, ts, perindex);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
@ This makes a Kronecker product of appropriate columns from tensors
|
|
in |fs| and adds such data to |i|-th column of this matrix. The
|
|
appropriate columns are defined by |pindex| sequence. A column of a
|
|
tensor has index created from a corresponding part of |pindex|. The
|
|
sizes of these parts are given by dimensions of the tensors in |ts|.
|
|
|
|
Here we break the given index |pindex| according to the dimensions of
|
|
the tensors in |ts|, and for each subsequence of the |pindex| we find
|
|
an index of the folded tensor, which involves calling |getOffset| for
|
|
folded tensor, which might be costly. We gather all columns to a
|
|
vector |tmpcols| which are Kronecker multiplied in constructor of
|
|
|URSingleTensor|. Finally we add data of |URSingleTensor| to the
|
|
|i|-th column.
|
|
|
|
@<|USubTensor::addKronColumn| code@>=
|
|
void USubTensor::addKronColumn(int i, const vector<const FGSTensor*>& ts,
|
|
const IntSequence& pindex)
|
|
{
|
|
vector<ConstVector> tmpcols;
|
|
int lastdim = 0;
|
|
for (unsigned int j = 0; j < ts.size(); j++) {
|
|
IntSequence ind(pindex, lastdim, lastdim+ts[j]->dimen());
|
|
lastdim += ts[j]->dimen();
|
|
index in(ts[j], ind);
|
|
tmpcols.push_back(ConstVector(*(ts[j]), *in));
|
|
}
|
|
|
|
URSingleTensor kronmult(tmpcols);
|
|
Vector coli(*this, i);
|
|
coli.add(1.0, kronmult.getData());
|
|
}
|
|
|
|
|
|
@ End of {\tt pyramid\_prod.cpp} file.
|