/*
* 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.indexmapping;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import cc.redberry.concurrent.OutputPortUnsafe;
import cc.redberry.core.context.CC;
import cc.redberry.core.indices.Indices;
import cc.redberry.core.indices.IndicesUtils;
import cc.redberry.core.tensor.Product;
import cc.redberry.core.tensor.SimpleTensor;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.combinatorics.Symmetries;
import cc.redberry.core.combinatorics.Symmetry;
/**
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
public class IndexMappingUtils {
private IndexMappingUtils() {
}
public static boolean isIdentity(IndexMappingBuffer indexMappingBuffer) {
return indexMappingBuffer.getSignum() == false && isIdentityUnsigned(indexMappingBuffer);
}
public static boolean isOpposite(IndexMappingBuffer indexMappingBuffer) {
return indexMappingBuffer.getSignum() == true && isIdentityUnsigned(indexMappingBuffer);
}
public static boolean isIdentityUnsigned(IndexMappingBuffer indexMappingBuffer) {
for (Map.Entry<Integer, IndexMappingBufferRecord> entry : indexMappingBuffer.getMap().entrySet())
if (entry.getKey().intValue() != (entry.getValue().getIndexName()))
return false;
return true;
}
public static Symmetry getSymmetryFromMapping(Indices indices, IndexMappingBuffer indexMappingBuffer) {
boolean sign = indexMappingBuffer.getSignum();
int dimension = indices.size();
int[] indicesArray = new int[dimension];
int i = 0;
for (; i < dimension; ++i)
indicesArray[i] = IndicesUtils.getNameWithType(indices.get(i));
// Permutation sortPermuatation = new Permutation(MathUtils.sort(indicesArray));
int[] permutation = new int[dimension];
for (i = 0; i < indices.size(); ++i) {
int fromIndex = indicesArray[i];
IndexMappingBufferRecord record = indexMappingBuffer.getMap().get(fromIndex);
if (record == null)
return new Symmetry(dimension);
int newPosition = -1;
//TODO refactor with sort and binary search
for (int j = 0; j < dimension; ++j)
if (indicesArray[j] == record.getIndexName())
newPosition = j;
if (newPosition < 0)
return new Symmetry(dimension);
permutation[i] = newPosition;
}
return new Symmetry(permutation, sign);
}
// public static Symmetries getSymmetriesFromMappings(Indices indices, Collection<? extends IndexMappingBufferImpl> buffers) {
// Symmetries symmetries = new Symmetries(indices.size());
// for (IndexMappingBufferImpl buffer : buffers)
// symmetries.add(getSymmetryFromMapping(indices, buffer));
// return symmetries;
// }
public static Symmetries getSymmetriesFromMappings(Indices indices, OutputPortUnsafe<IndexMappingBuffer> buffers) {
Symmetries symmetries = new Symmetries(indices.size());
IndexMappingBuffer buffer;
while ((buffer = buffers.take()) != null)
symmetries.add(getSymmetryFromMapping(indices, buffer));
return symmetries;
}
public static Symmetries getSymmetriesFromMappings(Indices indices, Tensor tensor, boolean allowDiffStates) {
return getSymmetriesFromMappings(indices, IndexMappings.createPort(tensor, tensor, allowDiffStates));
}
public static Tensor createMetrics(IndexMappingBuffer indexMappingBuffer) {
List<SimpleTensor> metrics = new ArrayList<>();
Iterator<Map.Entry<Integer, IndexMappingBufferRecord>> it = indexMappingBuffer.getMap().entrySet().iterator();
Map.Entry<Integer, IndexMappingBufferRecord> entry;
while (it.hasNext()) {
entry = it.next();
IndexMappingBufferRecord record = entry.getValue();
if (record.diffStatesInitialized() && !record.isContracted()) {
int rawState = ((record.states & 1) ^ 1) << 31;
metrics.add(CC.createMetric(rawState | record.getIndexName(), rawState | entry.getKey().intValue()));
}
}
if (metrics.isEmpty())
return null;
if (metrics.size() == 1)
return metrics.get(0);
return new Product(metrics);
}
public static IndexMappingBuffer tryGetPositiveWithoutDiffStates(List<IndexMappingBuffer> buffers) {
boolean sign = false, hasDiffStates = false;
boolean currentHasDiffStates;
IndexMappingBuffer buffer = null;
for (IndexMappingBuffer current : buffers) {
currentHasDiffStates = containsDiffStates(current);
if (buffer == null
|| (hasDiffStates && !currentHasDiffStates)
|| (sign && !current.getSignum()
&& !(currentHasDiffStates && !hasDiffStates))) {
buffer = current;
sign = buffer.getSignum();
hasDiffStates = currentHasDiffStates;
if (!sign && !hasDiffStates)
break;
}
}
return buffer;
}
//returns null if no mappings at all
public static IndexMappingBuffer tryGetPositiveWithoutDiffStates(OutputPortUnsafe<IndexMappingBuffer> opu) {
boolean sign = false, hasDiffStates = false;
boolean currentHasDiffStates;
IndexMappingBuffer buffer = null, current;
while ((current = opu.take()) != null) {
currentHasDiffStates = containsDiffStates(current);
if (!currentHasDiffStates && current.getSignum() == false)
return current;
if (buffer == null
|| (hasDiffStates && !currentHasDiffStates)
|| (sign && !current.getSignum()
&& !(currentHasDiffStates && !hasDiffStates))) {
buffer = current;
sign = buffer.getSignum();
hasDiffStates = currentHasDiffStates;
if (!sign && !hasDiffStates)
break;
}
}
return buffer;
}
// public static IndexMappingBuffer tryGetPositive(List<IndexMappingBuffer> buffers) {
// for (IndexMappingBuffer current : buffers)
// if (!current.getSignum())
// return current;
// return buffers.get(0);
// }
public static IndexMappingBuffer tryGetPositive(OutputPortUnsafe<IndexMappingBuffer> opu) {
IndexMappingBuffer current;
while ((current = opu.take()) != null)
if (!current.getSignum())
return current;
return current;
}
public static boolean containsDiffStates(IndexMappingBuffer indexMappingBuffer) {
for (Map.Entry<Integer, IndexMappingBufferRecord> entry : indexMappingBuffer.getMap().entrySet())
if (entry.getValue().diffStatesInitialized())
return true;
return false;
}
public static List<IndexMappingBuffer> createAllMappings(OutputPortUnsafe<IndexMappingBuffer> opu) {
List<IndexMappingBuffer> res = new ArrayList<>();
IndexMappingBuffer c;
while ((c = opu.take()) != null)
res.add(c);
return res;
}
public static List<IndexMappingBuffer> createAllMappings(Tensor from, Tensor to, boolean allowDiffStates) {
return createAllMappings(IndexMappings.createPort(from, to, allowDiffStates));
}
}