
cc.redberry.transformation.collect.PatternSplit Maven / Gradle / Ivy
/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2012:
* Stanislav Poslavsky
* Bolotin Dmitriy
*
* This file is part of Redberry.
*
* Redberry is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Redberry is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Redberry. If not, see .
*/
package cc.redberry.transformation.collect;
import static cc.redberry.core.indices.IndicesUtils.*;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import cc.redberry.core.context.CC;
import cc.redberry.core.indexgenerator.IndexGenerator;
import cc.redberry.core.tensor.Product;
import cc.redberry.core.tensor.SimpleTensor;
import cc.redberry.core.tensor.Sum;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.tensor.TensorIterator;
import cc.redberry.core.tensor.TensorNumber;
import cc.redberry.core.indexmapping.IndexMappingBufferRecord;
import cc.redberry.core.indexmapping.IndexMappingDirectAllowingUnmapped;
import cc.redberry.core.indexmapping.IndexMappingUtils;
import cc.redberry.core.indexmapping.IndexMappingBuffer;
import cc.redberry.core.indexmapping.IndexMappings;
import cc.redberry.core.tensor.testing.TTest;
import cc.redberry.core.transformations.ApplyIndexMappingDirectTransformation;
import cc.redberry.transformation.Transformations;
import cc.redberry.transformation.contractions.UncontractIndices;
import cc.redberry.transformation.contractions.UncontractIndicesAndRename;
import cc.redberry.core.utils.IntArrayList;
import cc.redberry.core.utils.TensorUtils;
/**
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
public class PatternSplit extends Split {
private Product factoredOut;
private final Sum factors = new Sum();
private IntArrayList termIndicesNames;
private IntArrayBuffer factorsIndicesNames;
private boolean initialized = false;
final boolean allowDiffStates;
public PatternSplit(Product factoredOut, boolean allowDiffStates) {
this.factoredOut = factoredOut;
this.term = TensorNumber.createONE();
this.allowDiffStates = allowDiffStates;
}
public PatternSplit(Product factoredOut) {
this(factoredOut, false);
}
public PatternSplit(Product factoredOut, Tensor term, boolean allowDiffStates) {
this.factoredOut = factoredOut;
this.term = term;
this.allowDiffStates = allowDiffStates;
}
private void initialize() {
UncontractIndices uncontractIndicesTransformation =
new UncontractIndices(TensorUtils.getAllIndicesNames(factoredOut));
term = uncontractIndicesTransformation.renameIndicesAndBuidKroneckers(term);
factoredOut.add(uncontractIndicesTransformation.getKroneckers());
factorsIndicesNames = new IntArrayBuffer(TensorUtils.getAllIndicesNames(factoredOut));
termIndicesNames = new IntArrayList(TensorUtils.getAllIndicesNames(term));
//TODO investigate cloning
//factors.addAll(factoredOut.clone());
factors.add(factoredOut);
initialized = true;
}
@Override
public boolean canMerge(PatternSplit split) {
return TTest.testEqualstensorStructure(term, split.term);
}
@Override
public void mergeFrom(PatternSplit split) {
if (!initialized)
initialize();
//main rountine
UncontractIndicesAndRename uncontractIndicesTransformation =
new UncontractIndicesAndRename(TensorUtils.getAllIndicesNames(split.factoredOut),
termIndicesNames.toArray());
split.term = uncontractIndicesTransformation.renameIndicesAndBuidKroneckers(split.term);
List generatedKroneckers = uncontractIndicesTransformation.getKroneckers();
split.factoredOut.add(generatedKroneckers);
//renaming indices of toCollect tensor
new RenameContractedIndices(factorsIndicesNames.toArray()).transform(split.term, split.factoredOut);
Tensor toCollect = split.term;
Tensor collectedTensor = term;
IntArrayList uncontractedIndicesToCollect = TensorUtils.getContractedIndicesNames(split.term, split.factoredOut);
IntArrayList uncontractedIndicesCollected = TensorUtils.getContractedIndicesNames(term, factors.getElements().get(0));
IndexMappingBuffer concurentBuffer = null;
if (factors.size() > 30){//TODO refacor in future
concurentBuffer = IndexMappings.getFirst(toCollect, collectedTensor, allowDiffStates);}
else {
List buffers = IndexMappingUtils.createAllMappings(toCollect, collectedTensor, allowDiffStates);
//finding best mapping
//botleneck for very huge sums
int concurrence = 0, currentConcurrence;
boolean sign = false;
for (IndexMappingBuffer buffer : buffers) {
currentConcurrence = 0;
for (Map.Entry entry : buffer.getMap().entrySet()) {
int indexToCollect = entry.getKey();
int indexCollected = entry.getValue().getIndexName();
if (indexToCollect == indexCollected || (uncontractedIndicesToCollect.contains(indexToCollect) && uncontractedIndicesCollected.contains(indexCollected)))
currentConcurrence++;
if (entry.getValue().diffStatesInitialized())
currentConcurrence--;
}
if (concurentBuffer == null
|| currentConcurrence > concurrence
|| (sign && !buffer.getSignum()
&& (currentConcurrence >= concurrence))) {
concurentBuffer = buffer;
concurrence = currentConcurrence;
}
}
}
IndexMappingDirectAllowingUnmapped mappingToCollect = new IndexMappingDirectAllowingUnmapped();
IndexMappingDirectAllowingUnmapped mappingCollectedTensor = new IndexMappingDirectAllowingUnmapped();
//building index generator
IntArrayList usedIndices = new IntArrayList(TensorUtils.getAllIndicesNames(split.factoredOut));
usedIndices.addAll(factorsIndicesNames);
usedIndices.addAll(termIndicesNames);
IndexGenerator ig = new IndexGenerator(usedIndices.toArray());
List mkCollectedList = new ArrayList<>();
for (Map.Entry entry : concurentBuffer.getMap().entrySet()) {
int indexCollected, indexToCollect, rawState = ((entry.getValue().getStates() & 1) ^ 1) << 31;
boolean diffStatesInit = entry.getValue().diffStatesInitialized();
indexCollected = rawState | entry.getValue().getIndexName();
indexToCollect = (diffStatesInit ? 0x80000000 : 0) ^ (rawState | entry.getKey());
SimpleTensor mkCollected;
SimpleTensor mkToCollect;
if (indexToCollect == indexCollected)
continue;
else if (uncontractedIndicesToCollect.contains(getNameWithType(indexToCollect))
&& uncontractedIndicesCollected.contains(getNameWithType(indexCollected)))
mappingToCollect.add(inverseIndexState(indexToCollect),
inverseIndexState(indexCollected));
else if (uncontractedIndicesToCollect.contains(getNameWithType(indexToCollect))) {
mkCollected = CC.createMetricOrKronecker(inverseIndexState(indexToCollect), indexCollected);
factorsIndicesNames.add(getNameWithType(indexCollected));
factorsIndicesNames.add(getNameWithType(indexToCollect));
termIndicesNames.replaceFirst(getNameWithType(indexCollected), getNameWithType(indexToCollect));
mappingCollectedTensor.add(indexCollected, indexToCollect);
mkCollectedList.add(mkCollected);
} else if (uncontractedIndicesCollected.contains(getNameWithType(indexCollected))) {
mkToCollect = CC.createMetricOrKronecker(indexToCollect, inverseIndexState(indexCollected));
split.factoredOut.add(mkToCollect);
} else {
int newIndex = ig.generate(getType(indexToCollect));
factorsIndicesNames.add(getNameWithType(indexCollected));
factorsIndicesNames.add(newIndex);
termIndicesNames.replaceFirst(getNameWithType(indexCollected), newIndex);
newIndex = getRawStateInt(indexCollected) | newIndex;
mkCollected = CC.createKronecker(indexCollected, inverseIndexState(newIndex));
mkToCollect = CC.createMetricOrKronecker(indexToCollect, inverseIndexState(newIndex));
mappingCollectedTensor.add(indexCollected, newIndex);
mkCollectedList.add(mkCollected);
split.factoredOut.add(mkToCollect);
}
}
if (!mkCollectedList.isEmpty())
for (Tensor p : factors)
((Product) p).add(mkCollectedList);
if (concurentBuffer.getSignum())
split.factoredOut.addFirst(TensorNumber.createMINUSONE());
if (!mappingToCollect.isEmpty())
ApplyIndexMappingDirectTransformation.INSTANCE.perform(split.factoredOut, mappingToCollect);
factors.add(split.factoredOut);
factorsIndicesNames.addAll(TensorUtils.getAllIndicesNames(split.factoredOut));
if (!mappingCollectedTensor.isEmpty())
ApplyIndexMappingDirectTransformation.INSTANCE.perform(collectedTensor, mappingCollectedTensor);
}
@Override
public Tensor tensorEquvivalent() {
if (!initialized)
return pairProduct(factoredOut, term);
TensorIterator it = factors.iterator();
Tensor equivalent;
Tensor current;
while (it.hasNext()) {
current = it.next();
equivalent = current.equivalent();
if (current != equivalent)
it.set(equivalent);
}
return pairProduct(Transformations.calculateNumbers(factors), term.equivalent());
}
private static class IntArrayBuffer extends IntArrayList {
public IntArrayBuffer(int[] data) {
super(data);
}
@Override
public void add(int num) {
if (contains(num))
return;
super.add(num);
}
@Override
public void addAll(int[] arr) {
IntArrayList temp = new IntArrayList();
for (int i : arr)
if (contains(i))
continue;
else
temp.add(i);
super.addAll(temp.toArray());
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy