Package cc.redberry.core.indexmapping

Source Code of cc.redberry.core.indexmapping.ProviderSum$StretchPairTester

/*
* 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.List;
import cc.redberry.concurrent.OutputPortUnsafe;
import cc.redberry.core.tensor.Sum;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.tensor.TensorSortedContent;
import cc.redberry.core.combinatorics.IntPermutationsGenerator;
import cc.redberry.core.combinatorics.PriorityPermutationGenerator;
import cc.redberry.core.utils.TensorUtils;

/**
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
final class ProviderSum implements IndexMappingProvider {
    public static final IndexMappingProviderFactory FACTORY = new IndexMappingProviderFactory() {
        @Override
        public IndexMappingProvider create(IndexMappingProvider opu, Tensor from, Tensor to, boolean allowDiffStates) {
            TensorSortedContent fromC = ((Sum) from).getContent(),
                    toC = ((Sum) to).getContent();
            if (fromC.size() != toC.size())
                return IndexMappingProvider.Util.EMPTY_PROVIDER;
            for (int i = 0; i < fromC.size(); ++i)
                if (fromC.get(i).hashCode() != toC.get(i).hashCode())
                    return IndexMappingProvider.Util.EMPTY_PROVIDER;
            return new ProviderSum(opu, fromC, toC, allowDiffStates);
        }
    };
    private final IndexMappingProvider mainProvider;
    private final Tester[] testers;

    public ProviderSum(IndexMappingProvider opu, TensorSortedContent fromContent, TensorSortedContent toContent, boolean allowDiffStates) {
        int begin = 0;

        //Search for main source
        int i;
        final int size = fromContent.size();
        int mainStretchCoord = -1;
        int mainStretchIndex = -1;
        int mainStretchLength = Integer.MAX_VALUE;
        List<Tester> testersList = new ArrayList<>();
        for (i = 1; i <= size; ++i)
            if (i == size || fromContent.get(i).hashCode() != fromContent.get(i - 1).hashCode()) {
                //if (i - 1 != begin) {
                //Here is main stretches iteration code
                testersList.add(i - begin == 1
                        ? new SinglePairTester(fromContent.get(begin), toContent.get(begin))
                        : new StretchPairTester(fromContent.getRange(begin, i), toContent.getRange(begin, i)));
                if (mainStretchLength > i - begin) {
                    mainStretchCoord = begin;
                    mainStretchLength = i - begin;
                    mainStretchIndex = testersList.size() - 1;
                }
                //}

                begin = i;
            }
        if (mainStretchLength == 1) {
            this.mainProvider = IndexMappings.createPort(opu, fromContent.get(mainStretchCoord),
                    toContent.get(mainStretchCoord), allowDiffStates);
            testersList.remove(mainStretchIndex);
        } else {

            final Tensor[] preFrom = TensorUtils.getDistinct(
                    fromContent.getRange(mainStretchCoord, mainStretchCoord + mainStretchLength));
            final Tensor[] preTo = TensorUtils.getDistinct(
                    toContent.getRange(mainStretchCoord, mainStretchCoord + mainStretchLength));

            if (preFrom.length != preTo.length) {
                this.mainProvider = IndexMappingProvider.Util.EMPTY_PROVIDER;
                testersList.clear();
            } else if (preFrom.length == 1) {
                this.mainProvider = IndexMappings.createPort(opu, preFrom[0], preTo[0], allowDiffStates);
                testersList.remove(mainStretchIndex);
            } else {
                this.mainProvider = new StretchPairSource(opu, preFrom, preTo);
                testersList.set(mainStretchIndex, (StretchPairSource) this.mainProvider);
            }
        }
        this.testers = testersList.toArray(new Tester[testersList.size()]);
    }

    @Override
    public boolean tick() {
        return mainProvider.tick();
    }

    @Override
    public IndexMappingBuffer take() {
        OUTER:
        while (true) {
            final IndexMappingBuffer buffer = mainProvider.take();
            if (buffer == null)
                return null;
            final IndexMappingBufferTester tester = IndexMappingBufferTester.create(buffer);
            for (Tester t : testers)
                if (!t.test(tester))
                    continue OUTER;
            return buffer;
        }
    }

    private interface Tester {
        boolean test(IndexMappingBufferTester tester);
    }

    private static class StretchPairSource extends IndexMappingProviderAbstract implements Tester {
        private final Tensor[] from, to;
        private final IntPermutationsGenerator permutationGenerator;
        private OutputPortUnsafe<? extends IndexMappingBuffer> currentSource = null;
        private int[] currentPermutation;

        public StretchPairSource(final OutputPortUnsafe<? extends IndexMappingBuffer> opu,
                final Tensor[] from, final Tensor[] to) {
            super(opu);
            this.from = from;
            this.to = to;
            this.permutationGenerator = new IntPermutationsGenerator(this.from.length);
        }

        @Override
        public IndexMappingBuffer take() {
            if (currentBuffer == null)
                return null;
            if (!permutationGenerator.hasNext())
                return null;
            IndexMappingBuffer buf;
            while (true) {
                if (currentSource != null && (buf = currentSource.take()) != null)
                    return buf;
                if (!permutationGenerator.hasNext()) {
                    currentBuffer = null;
                    return null;
                }
                currentPermutation = permutationGenerator.next();
                currentSource = IndexMappings.createPort(currentBuffer.clone(), from[0], to[currentPermutation[0]]);
            }
        }

        @Override
        protected void _tick() {
            permutationGenerator.reset();
        }

        @Override
        public boolean test(IndexMappingBufferTester tester) {
            for (int i = 1; i < from.length; ++i)
                if (!ProviderSum.test(from[i], to[currentPermutation[i]], tester))
                    return false;
            return true;
        }
    }

    private static class StretchPairTester implements Tester {
        private final Tensor[] from, to;
        private final PriorityPermutationGenerator permutationGenerator;

        public StretchPairTester(final Tensor[] from, final Tensor[] to) {
            this.from = from;
            this.to = to;
            this.permutationGenerator = new PriorityPermutationGenerator(from.length);
        }

        @Override
        public boolean test(final IndexMappingBufferTester tester) {
            int[] permutation;
            final PriorityPermutationGenerator generator = permutationGenerator;
            generator.reset();
            int i;
            OUTER:
            while ((permutation = generator.next()) != null)
                for (i = 0; i < from.length; ++i) {
                    if (!ProviderSum.test(from[i], to[permutation[i]], tester))
                        continue OUTER;
                    generator.nice();
                    return true;
                }
            return false;
        }
    }

    private static class SinglePairTester implements Tester {
        private final Tensor from, to;

        public SinglePairTester(final Tensor from, final Tensor to) {
            this.from = from;
            this.to = to;
        }

        @Override
        public boolean test(final IndexMappingBufferTester tester) {
            return ProviderSum.test(from, to, tester);
        }
    }

    private static boolean test(final Tensor from, final Tensor to, final IndexMappingBufferTester tester) {
        tester.reset();
        final IndexMappingProvider provider =
                IndexMappings.createPort(IndexMappingProvider.Util.singleton(tester), from, to, tester.allowDiffStates());
        provider.tick();
        return provider.take() != null;
    }
}
TOP

Related Classes of cc.redberry.core.indexmapping.ProviderSum$StretchPairTester

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.