Package cc.redberry.core.transformations

Source Code of cc.redberry.core.transformations.ApplyIndexMapping

/*
* 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.indexgenerator.IndexGenerator;
import cc.redberry.core.indexmapping.IndexMapping;
import cc.redberry.core.indexmapping.IndexMappingBuffer;
import cc.redberry.core.indexmapping.IndexMappingBufferRecord;
import cc.redberry.core.indices.Indices;
import cc.redberry.core.indices.IndicesUtils;
import cc.redberry.core.indices.SimpleIndices;
import cc.redberry.core.tensor.SimpleTensor;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.tensor.TensorField;
import cc.redberry.core.tensor.Tensors;
import cc.redberry.core.tensor.iterator.TraverseGuide;
import cc.redberry.core.tensor.iterator.TraverseState;
import cc.redberry.core.tensor.iterator.TreeTraverseIterator;
import cc.redberry.core.utils.ArraysUtils;
import cc.redberry.core.utils.IntArrayList;
import cc.redberry.core.utils.TensorUtils;
import java.util.Arrays;
import java.util.Map;
import java.util.Set;

/**
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
public final class ApplyIndexMapping implements Transformation {

    private final int[] from, to, forbidden;

    public ApplyIndexMapping(int[] from, int[] to, int[] forbidden) {
        this.from = from.clone();
        this.to = to.clone();
        this.forbidden = forbidden;
    }

    @Override
    public Tensor transform(Tensor t) {
        checkConsistent(t, from);
        return applyIndexMapping(t, from, to, forbidden);
    }

    private static void checkConsistent(Tensor tensor, final int[] from) {
        int[] freeIndices = tensor.getIndices().getFree().getAllIndices().copy();
        Arrays.sort(freeIndices);
        int[] _from = from.clone();
        Arrays.sort(_from);
        if (!Arrays.equals(freeIndices, _from))
            throw new IllegalArgumentException("From indices are not equal to free indices of tensor.");
    }

    public static Tensor applyIndexMapping(Tensor tensor, int[] from, int[] to, int[] forbidden) {
        checkConsistent(tensor, from);
        return unsafeApplyIndexMappingFromClonedSource(tensor, from.clone(), to.clone(), forbidden);
    }

    public static Tensor applyIndexMapping(Tensor tensor, IndexMappingBuffer buffer) {
        return applyIndexMapping(tensor, buffer, new int[0]);
    }

    public static Tensor applyIndexMapping(Tensor tensor, IndexMappingBuffer buffer, int[] forbidden) {
        if (buffer == null)
            throw new NullPointerException("Buffer is null.");
        Map<Integer, IndexMappingBufferRecord> map = buffer.getMap();
        int[] from = new int[map.size()], to = new int[map.size()];
        int count = 0;
        IndexMappingBufferRecord record;
        for (Map.Entry<Integer, IndexMappingBufferRecord> entry : map.entrySet()) {
            from[count] = entry.getKey();
            record = entry.getValue();
            to[count++] = record.getIndexName() ^ (record.diffStatesInitialized() ? 0x80000000 : 0);
        }

        final int[] freeIndices = tensor.getIndices().getFree().getAllIndices().copy();
        for (int i = 0; i < freeIndices.length; ++i)
            freeIndices[i] = IndicesUtils.getNameWithType(freeIndices[i]);
        Arrays.sort(freeIndices);
        int[] _from = from.clone();
        Arrays.sort(_from);
        if (!Arrays.equals(freeIndices, _from))
            throw new IllegalArgumentException("From indices are not equal to free indices of tensor.");

        Tensor result = unsafeApplyIndexMappingFromSortedClonedPreparedSource(tensor, from, to, forbidden);
        if (buffer.getSignum())
            return Tensors.negate(result);
        else
            return result;
    }

    public static Tensor renameDummy(Tensor tensor, int[] forbidden) {
        return renameDummyFromClonedSource(tensor, forbidden.clone());
    }

    public static Tensor renameDummyFromClonedSource(Tensor tensor, int[] forbidden) {
        int[] from = tensor.getIndices().getFree().getAllIndices().copy();
        for (int i = from.length - 1; i >= 0; --i)
            from[i] = IndicesUtils.getNameWithType(from[i]);
        Arrays.sort(from);
        return unsafeApplyIndexMappingFromSortedClonedPreparedSource(tensor, from, from, forbidden);
    }

    private static Tensor unsafeApplyIndexMappingFromClonedSource(Tensor tensor, int[] from, int[] to, int[] forbidden) {
        int i, rawState;
        for (i = from.length - 1; i >= 0; --i) {
            rawState = IndicesUtils.getRawStateInt(from[i]);
            from[i] ^= rawState;
            to[i] ^= rawState;
        }
        ArraysUtils.quickSort(from, to);
        return unsafeApplyIndexMappingFromSortedClonedPreparedSource(tensor, from, to, forbidden);
    }

    private static Tensor unsafeApplyIndexMappingFromSortedClonedPreparedSource(
            Tensor tensor, int[] from, int[] to, int[] forbidden) {

        Set<Integer> dummyIndices = TensorUtils.getAllIndicesNames(tensor);
        //extracting contracted only
        Indices indices = tensor.getIndices().getFree();
        int i;
        for (i = indices.size() - 1; i >= 0; --i)
            dummyIndices.remove(IndicesUtils.getNameWithType(indices.get(i)));


        int[] allForbidden = new int[to.length + forbidden.length];
        System.arraycopy(to, 0, allForbidden, 0, to.length);
        System.arraycopy(forbidden, 0, allForbidden, to.length, forbidden.length);
        for (i = allForbidden.length - 1; i >= 0; --i)
            allForbidden[i] = IndicesUtils.getNameWithType(allForbidden[i]);

        IntArrayList fromL = new IntArrayList(from.length), toL = new IntArrayList(to.length);
        fromL.addAll(from);
        toL.addAll(to);

        Arrays.sort(allForbidden);
        int[] forbiddenGeneratorIndices = new int[allForbidden.length + dummyIndices.size()];
        System.arraycopy(allForbidden, 0, forbiddenGeneratorIndices, 0, allForbidden.length);
        i = allForbidden.length - 1;
        for (Integer index : dummyIndices)
            forbiddenGeneratorIndices[++i] = index;

        IndexGenerator generator = new IndexGenerator(forbiddenGeneratorIndices);//also sorts allForbidden array
        for (Integer index : dummyIndices)
            if (Arrays.binarySearch(allForbidden, index) >= 0 && Arrays.binarySearch(from, index) < 0) {
                fromL.add(index);
                toL.add(generator.generate(IndicesUtils.getType(index)));
            }

        int[] _from = fromL.toArray(), _to = toL.toArray();
        ArraysUtils.quickSort(_from, _to);

        return applyIndexMapping(tensor, new IndexMapper(_from, _to));
    }

    public static Tensor applyIndexMapping(Tensor tensor, IndexMapper mapper) {
        TreeTraverseIterator iterator = new TreeTraverseIterator(tensor, TraverseGuide.EXCEPT_FUNCTIONS_AND_FIELDS);
        TraverseState state;
        SimpleIndices oldIndices, newIndices;
        SimpleTensor simpleTensor;
        while ((state = iterator.next()) != null) {
            if (state == TraverseState.Leaving)
                continue;
            if (!(iterator.current() instanceof SimpleTensor))
                continue;
            simpleTensor = (SimpleTensor) iterator.current();
            oldIndices = simpleTensor.getIndices();
            newIndices = oldIndices.applyIndexMapping(mapper);
            if (oldIndices != newIndices)
                if (simpleTensor instanceof TensorField)
                    iterator.set(Tensors.setIndicesToField((TensorField) simpleTensor, newIndices));
                else
                    iterator.set(Tensors.setIndicesToSimpleTensor(simpleTensor, newIndices));
        }
        return iterator.result();
    }

    public final static class IndexMapper implements IndexMapping {

        private final int[] from, to;

        public IndexMapper(int[] from, int[] to) {
            this.from = from;
            this.to = to;
        }

        @Override
        public int map(int index) {
            int position = Arrays.binarySearch(from, IndicesUtils.getNameWithType(index));
            if (position < 0)
                return index;
            return IndicesUtils.getRawStateInt(index) ^ to[position];
        }
    }
}
TOP

Related Classes of cc.redberry.core.transformations.ApplyIndexMapping

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.