/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2012:
* Stanislav Poslavsky <stvlpos@mail.ru>
* Bolotin Dmitriy <bolotin.dmitriy@gmail.com>
*
* 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 <http://www.gnu.org/licenses/>.
*/
package cc.redberry.core.transformations;
import cc.redberry.core.indices.IndicesUtils;
import cc.redberry.core.math.MathUtils;
import cc.redberry.core.tensor.Derivative;
import cc.redberry.core.tensor.Fraction;
import cc.redberry.core.tensor.Product;
import cc.redberry.core.tensor.Sum;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.tensor.TensorIterator;
import cc.redberry.core.indexmapping.IndexMappingImpl;
import cc.redberry.core.utils.IntArrayList;
import cc.redberry.core.utils.TensorUtils;
import cc.redberry.transformation.Transformation;
/**
* This transformation renames indices... TODO write<br/><br/>
*
* <b>Application Note:</b> must be applied using {@link cc.redberry.transformation.Transformer} in <i>tensor last</i> mode.
*
* @author Bolotin Dmitriy
* @author Poslavsky Stanislav
* @author Konstantin Kiselev
*/
public class RenameConflictingIndices implements Transformation {
public static final RenameConflictingIndices INSTANCE = new RenameConflictingIndices();
private RenameConflictingIndices() {
}
@Override
public Tensor transform(Tensor tensor) {
if (tensor instanceof Product) {
//Creating int set from indices
int[] usedIndices = IndicesUtils.getSortedDistinctIndicesNames(tensor.getIndices());
for (Tensor multiplyer : tensor)
if ((multiplyer instanceof Sum) || (multiplyer instanceof Fraction)) { //TODO: Add more tensor typess?
//Sum & Fraction returns only free indices
int[] mIndices = IndicesUtils.getSortedDistinctIndicesNames(multiplyer.getIndices());
//Used indices ecept sum free indices
int[] currentUsedIndices = MathUtils.intSetDifference(mIndices, usedIndices);
//ApplyIndexMappingTransformation (AIM) never produce conflicting indices if
//there are no such indices in tensor,
//so while transforming in tensor last mode AIM transformation applies only on tensors
//without any conflicts, just giving new names for indices from this product
IndexMappingImpl indexMapping = new IndexMappingImpl(currentUsedIndices);
ApplyIndexMappingTransformation.INSTANCE.perform(multiplyer, indexMapping);
//Adding new illegal indices
usedIndices =
MathUtils.intSetUnion(usedIndices,
TensorUtils.getAllIndicesNames(multiplyer));
}
}
if (tensor instanceof Derivative) {
//Very similar to Product case
Derivative derivative = (Derivative) tensor;
//Collecting all indices from derivative vars
TensorIterator it = derivative.iterator();
IntArrayList usedIndices = new IntArrayList();
Tensor current;
while (it.hasNext()) {
current = it.next();
if (Derivative.onVarsIndicator.is(it))
usedIndices.addAll(TensorUtils.getAllIndicesNames(current));
}
//Creating int set from collected indices
int[] usedIndicesArray = MathUtils.getSortedDistinct(usedIndices.toArray());
Tensor target = derivative.getTarget();
//Calculating used indices for AIM transformation
int[] targetIndices = IndicesUtils.getSortedDistinctIndicesNames(target.getIndices().getFreeIndices());
int[] currentUsedIndices = MathUtils.intSetDifference(targetIndices, usedIndices.toArray());
//Applying AIM transformation
IndexMappingImpl indexMapping = new IndexMappingImpl(currentUsedIndices);
ApplyIndexMappingTransformation.INSTANCE.perform(target, indexMapping);
}
return tensor;
}
}