Package cc.redberry.transformation.collect

Source Code of cc.redberry.transformation.collect.PatternSplit

/*
* 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.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<PatternSplit> {
    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<Tensor> 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<IndexMappingBuffer> 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<Integer, IndexMappingBufferRecord> 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<Tensor> mkCollectedList = new ArrayList<>();

        for (Map.Entry<Integer, IndexMappingBufferRecord> 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());
        }
    }
}
TOP

Related Classes of cc.redberry.transformation.collect.PatternSplit

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.