Package cc.redberry.core.indexmapping

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

/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2013:
*   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 cc.redberry.concurrent.OutputPortUnsafe;
import cc.redberry.core.combinatorics.IntPermutationsGenerator;
import cc.redberry.core.tensor.Tensor;

import java.util.ArrayList;
import java.util.List;

/**
* {@link cc.redberry.core.tensor.Sum}-specific mapping provider.
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
* @since 1.0
*/
final class ProviderSum implements IndexMappingProvider {

    static final IndexMappingProviderFactory FACTORY = new IndexMappingProviderFactory() {

        @Override
        public IndexMappingProvider create(IndexMappingProvider opu, Tensor from, Tensor to) {
            if (from.size() != to.size())
                return IndexMappingProvider.Util.EMPTY_PROVIDER;
            for (int i = 0; i < from.size(); ++i)
                if (from.get(i).hashCode() != to.get(i).hashCode())
                    return IndexMappingProvider.Util.EMPTY_PROVIDER;
            return new ProviderSum(opu, from, to);
        }
    };
    private final IndexMappingProvider mainProvider;
    private final Tester[] testers;
    private final InputCache cache;

    private ProviderSum(IndexMappingProvider opu, Tensor from, Tensor to) {

        //Search for main source
        int i, begin = 0;
        final int size = from.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 || from.get(i).hashCode() != from.get(i - 1).hashCode()) {
                //if (i - 1 != begin) {
                //Here is main stretches iteration code
                testersList.add(i - begin == 1
                        ? new SinglePairTester(from.get(begin), to.get(begin))
                        : new StretchPairTester(from.getRange(begin, i), to.getRange(begin, i)));
                if (mainStretchLength > i - begin) {
                    mainStretchCoord = begin;
                    mainStretchLength = i - begin;
                    mainStretchIndex = testersList.size() - 1;
                }
                //}

                begin = i;
            }

        cache = new InputCache(opu);
        if (mainStretchLength == 1) {
            this.mainProvider = IndexMappings.createPort(cache, from.get(mainStretchCoord),
                    to.get(mainStretchCoord));
            testersList.remove(mainStretchIndex);
        } else {
            final Tensor[] preFrom = from.getRange(mainStretchCoord,
                    mainStretchCoord + mainStretchLength);
            final Tensor[] preTo = to.getRange(mainStretchCoord,
                    mainStretchCoord + mainStretchLength);

            this.mainProvider = new StretchPairSource(cache, 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;
            buffer.removeContracted();
            //buffer.addSignum(cache.lastReturned.sign);

            final IndexMappingBufferTester tester =
                    new IndexMappingBufferTester(buffer.export().mergeWith(cache.lastReturned));

            for (Tester t : testers)
                if (!t.test(tester))
                    continue OUTER;

            //buffer.addSignum(cache.lastReturned.sign);
            return buffer;
        }
    }

    private static class InputCache implements IndexMappingProvider {

        private final IndexMappingProvider provider;
        FromToHolder lastReturned;

        public InputCache(IndexMappingProvider provider) {
            this.provider = provider;
        }

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

        @Override
        public IndexMappingBuffer take() {
            IndexMappingBuffer buffer = provider.take();
            if (buffer == null)
                return null;
            lastReturned = buffer.export();
            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<IndexMappingBuffer> currentSource = null;
        private int[] currentPermutation;

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

        @Override
        public IndexMappingBuffer take() {
            if (currentBuffer == null)
                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.createPortOfBuffers(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 (!IndexMappingBufferTester.test(tester, from[i], to[currentPermutation[i]]))
                    return false;
            return true;
        }
    }

    private static class StretchPairTester implements Tester {

        private final Tensor[] from, to;
        //        private final PriorityPermutationGenerator permutationGenerator;
        private final int length;

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

            //            this.permutationGenerator = new PriorityPermutationGenerator(from.length);
        }

        @Override
        public boolean test(final IndexMappingBufferTester tester) {
            //TODO discuss algorithm with Dima
            boolean[] bijection = new boolean[length];
            int i, j;
            OUT:
            for (i = 0; i < length; ++i) {
                for (j = 0; j < length; ++j)
                    if (!bijection[j] && IndexMappingBufferTester.test(tester, from[j], to[i])) {
                        bijection[j] = true;
                        continue OUT;
                    }
                return false;
            }
            return true;
            //            int[] permutation;
            //            final PriorityPermutationGenerator generator = permutationGenerator;
            //            generator.reset();
            //            int i;
            //            OUTER:
            //            while ((permutation = generator.next()) != null)
            //                for (i = 0; i < from.length; ++i) {
            //                    if (!IndexMappingBufferTester.test(tester, from[i], to[permutation[i]]))
            //                        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 IndexMappingBufferTester.test(tester, from, to);
        }
    }
    //    private static boolean test(final Tensor from, final Tensor to, final IndexMappingBufferTester tester) {
    //        tester.reset();
    //        final IndexMappingProvider provider =
    //                IndexMappings.createPortOfBuffers(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.