//selecting unitary matrices from product
//extracting trace combinations from product
Product product = (Product) current;
//positions of matrices
IntArrayList positionsOfMatrices = new IntArrayList();
int sizeOfIndexless = product.sizeOfIndexlessPart();
ProductContent pc = product.getContent();
PrimitiveSubgraph[] partition
= PrimitiveSubgraphPartition.calculatePartition(pc, matrixType);
//calculated traces
ProductBuilder traces = new ProductBuilder();
traces:
for (PrimitiveSubgraph subgraph : partition) {
if (subgraph.getGraphType() != GraphType.Cycle)
continue;
int numberOfGammas = 0, numberOfGamma5s = 0;
Tensor gamma;
//actual positions in current
int[] positions = subgraph.getPartition();
assert positions.length > 1;
for (int i = positions.length - 1; i >= 0; --i) {
positions[i] = positions[i] + sizeOfIndexless;
gamma = product.get(positions[i]);
if (gamma instanceof SimpleTensor) {
if (((SimpleTensor) gamma).getName() == gammaName)
++numberOfGammas;
else if (((SimpleTensor) gamma).getName() == gamma5Name)
++numberOfGamma5s;
else
//not a gamma matrix
continue traces;
} else {
//not a gamma matrix
continue traces;
}
}
//early terminations
if (numberOfGammas % 2 == 1
|| (numberOfGammas == 2 && numberOfGamma5s % 2 == 1)) {
iterator.set(Complex.ZERO);
continue out;
}
if (numberOfGammas == 0 && numberOfGamma5s % 2 == 1) {
iterator.set(Complex.ZERO);
continue out;
}
positionsOfMatrices.addAll(positions);
if (numberOfGamma5s == 0)
traces.put(traceWithout5(product.select(positions), numberOfGammas));
else {
//early check
if (numberOfGammas == 0) {
//numberOfGamma5s % 2 == 0
traces.put(Complex.FOUR);
continue traces;
}
//eliminating excess products of gamma5s
if (numberOfGamma5s > 1) {
//take into account odd number of swaps
boolean sign = false;
//product of gammas as ordered array (will be filled without excess gamma5s)
final SimpleTensor[] orderedProduct = new SimpleTensor[numberOfGammas + (numberOfGamma5s % 2 == 0 ? 0 : 1)];
int counter = -1;
//index of tensor in product content, which is contracted with current gamma5
int positionOfPreviousGamma = -2;
SimpleTensor currentGamma;
for (int positionOfGamma = 0; positionOfGamma < positions.length; ++positionOfGamma) {
currentGamma = (SimpleTensor) product.get(positions[positionOfGamma]);
if (currentGamma.getName() == gamma5Name) {
//adding one gamma5 if they are odd number
if (positionOfPreviousGamma == -2) {
if (numberOfGamma5s % 2 == 1) {
orderedProduct[++counter] = currentGamma;
positionOfPreviousGamma = -1;
} else {
positionOfPreviousGamma = positionOfGamma;
}
continue;
}
if (positionOfPreviousGamma == -1)
positionOfPreviousGamma = positionOfGamma;
else {
//odd number of swaps
if ((positionOfGamma - positionOfPreviousGamma) % 2 == 0)
sign ^= true;
positionOfPreviousGamma = -1;
}
} else
orderedProduct[++counter] = currentGamma;
}
//fixing new indices contractions
int u = 0, l = 0;
for (int i = 0; ; ++i) {
if (i == orderedProduct.length - 1) {
orderedProduct[i] = setMatrixIndices(orderedProduct[i], u, 0);
break;
}
orderedProduct[i] = setMatrixIndices(orderedProduct[i], u, ++l);
u = l;
}
Tensor withoutExcessGamma5s = multiply(orderedProduct);
if (numberOfGamma5s % 2 == 0)
withoutExcessGamma5s = traceWithout5(withoutExcessGamma5s, numberOfGammas);
else {
withoutExcessGamma5s = traceWith5(withoutExcessGamma5s, numberOfGammas);
withoutExcessGamma5s = simplifyLeviCivita.transform(withoutExcessGamma5s);
}
if (sign)
withoutExcessGamma5s = negate(withoutExcessGamma5s);
traces.put(withoutExcessGamma5s);
} else
traces.put(traceWith5(product.select(positions), numberOfGammas));
}
}
if (positionsOfMatrices.isEmpty())
continue out;
//final simplifications
traces.put(product.remove(positionsOfMatrices.toArray()));
current = traces.build();
current = ExpandAndEliminateTransformation.expandAndEliminate(current);
current = deltaTrace.transform(current);
if (simplifyLeviCivita != null)
current = simplifyLeviCivita.transform(current);