Package cc.redberry.core.transformations.expand

Source Code of cc.redberry.core.transformations.expand.ExpandPort$SumPort

/*
* 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.transformations.expand;

import cc.redberry.concurrent.OutputPortUnsafe;
import cc.redberry.core.combinatorics.IntTuplesPort;
import cc.redberry.core.number.Complex;
import cc.redberry.core.number.NumberUtils;
import cc.redberry.core.tensor.*;
import cc.redberry.core.utils.TensorUtils;
import gnu.trove.set.hash.TIntHashSet;

import java.math.BigInteger;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
* Output port, which iteratively gives expand tensor.
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
* @since 1.0
*/
public final class ExpandPort {

    public static Tensor expandUsingPort(Tensor t) {
        SumBuilder sb = new SumBuilder();
        OutputPortUnsafe<Tensor> port = createPort(t);
        Tensor n;
        while ((n = port.take()) != null)
            sb.put(n);
        return sb.build();
    }

    public static OutputPortUnsafe<Tensor> createPort(Tensor tensor) {
        if (tensor instanceof Product)
            return new ProductPort(tensor);
        if (tensor instanceof Sum)
            return new SumPort(tensor);
        if (ExpandUtils.isExpandablePower(tensor) && !TensorUtils.isNegativeNaturalNumber(tensor.get(1)))
            return new PowerPort(tensor);
        else
            return new OutputPortUnsafe.Singleton<>(tensor);
    }

    private static interface ResettablePort extends OutputPortUnsafe<Tensor> {
        void reset();
    }

    private static final class PowerPort implements ResettablePort {

        private final Tensor base;
        private final int power;
        private IntTuplesPort tuplesPort;
        private final int[] initialForbidden;
        private OutputPortUnsafe<Tensor> currentPort;

        public PowerPort(Tensor tensor, int[] initialForbidden) {
            base = tensor.get(0);
            power = ((Complex) tensor.get(1)).getReal().intValue();
            int[] upperBounds = new int[power];
            Arrays.fill(upperBounds, base.size());
            tuplesPort = new IntTuplesPort(upperBounds);
            this.initialForbidden = initialForbidden;
            currentPort = nextPort();
        }

        public PowerPort(Tensor tensor) {
            this(tensor, TensorUtils.getAllIndicesNamesT(tensor.get(0)).toArray());
        }

        OutputPortUnsafe<Tensor> nextPort() {
            final int[] tuple = tuplesPort.take();
            if (tuple == null)
                return null;
            TIntHashSet added = new TIntHashSet(initialForbidden);
            ProductBuilder builder = new ProductBuilder();
            builder.put(base.get(tuple[0]));
            for (int i = 1; i < tuple.length; ++i)
                builder.put(ApplyIndexMapping.renameDummy(base.get(tuple[i]), added.toArray(), added));

            return createPort(builder.build());
        }

        @Override
        public Tensor take() {
            if (currentPort == null)
                return null;
            Tensor t = currentPort.take();
            if (t == null) {
                currentPort = nextPort();
                return take();
            }
            return t;
        }

        @Override
        public void reset() {
            tuplesPort.reset();
            currentPort = nextPort();
        }
    }

    private static final class ProductPort implements OutputPortUnsafe<Tensor> {

        private final ProductBuilder base;
        private ProductBuilder currentBuilder;
        private final ResettablePort[] sumsAndPowers;
        private final Tensor[] currentMultipliers;
        private final Tensor tensor;

        public ProductPort(Tensor tensor) {
            this.tensor = tensor;
            this.base = new ProductBuilder();
            List<ResettablePort> sumOrPowerPorts = new ArrayList<>();
            int theLargestSumPosition = 0, theLargestSumSize = 0, productSize = tensor.size();
            Tensor m;
            for (int i = 0; i < productSize; ++i) {
                m = tensor.get(i);
                if (m instanceof Sum) {
                    if (m.size() > theLargestSumSize) {
                        theLargestSumPosition = sumOrPowerPorts.size();
                        theLargestSumSize = m.size();
                    }
                    sumOrPowerPorts.add(new SumPort(m));
                } else if (ExpandUtils.isExpandablePower(m)) {
                    if (TensorUtils.isNegativeNaturalNumber(m.get(1))) {
//                        base.put(Tensors.reciprocal(ExpandUtils.expandPower(
//                                (Sum) m.get(0), ((Complex) m.get(1)).getReal().intValue(),
//                                TensorUtils.getAllIndicesNamesT(tensor).toArray(), new Transformation[0])));
                        base.put(m);
                        continue;
                    }
                    if (NumberUtils.pow(BigInteger.valueOf(m.get(0).size()),
                            (((Complex) m.get(1)).getReal().bigIntValue())).compareTo(BigInteger.valueOf(theLargestSumSize)) > 0) {
                        theLargestSumPosition = sumOrPowerPorts.size();
                        theLargestSumSize = m.size();
                    }
                    sumOrPowerPorts.add(new PowerPort(m, TensorUtils.getAllIndicesNamesT(tensor).toArray()));
                } else
                    base.put(m);
            }
            sumsAndPowers = sumOrPowerPorts.toArray(new ResettablePort[sumOrPowerPorts.size()]);

            if (sumsAndPowers.length <= 1) {
                currentMultipliers = new Tensor[0];
                currentBuilder = base;
            } else {
                ResettablePort temp = sumsAndPowers[theLargestSumPosition];
                sumsAndPowers[theLargestSumPosition] = sumsAndPowers[sumsAndPowers.length - 1];
                sumsAndPowers[sumsAndPowers.length - 1] = temp;
                currentMultipliers = new Tensor[sumsAndPowers.length - 2];
                for (productSize = 0; productSize < sumsAndPowers.length - 2; ++productSize)
                    currentMultipliers[productSize] = sumsAndPowers[productSize].take();
                currentBuilder = nextCombination();
            }
        }

        private ProductBuilder nextCombination() {
            if (sumsAndPowers.length == 1)
                return null;
            int pointer = sumsAndPowers.length - 2;
            ProductBuilder temp = base.clone();
            boolean next = false;
            Tensor c;
            c = sumsAndPowers[pointer].take();
            if (c == null) {
                sumsAndPowers[pointer].reset();
                c = sumsAndPowers[pointer].take();
                next = true;
            }
            temp.put(c);
            while (--pointer >= 0) {
                if (next) {
                    next = false;
                    c = sumsAndPowers[pointer].take();
                    if (c == null) {
                        sumsAndPowers[pointer].reset();
                        c = sumsAndPowers[pointer].take();
                        next = true;
                    }
                    currentMultipliers[pointer] = c;
                }
                temp.put(currentMultipliers[pointer]);
            }
            if (next)
                return null;
            return temp;
        }

        @Override
        public Tensor take() {
            if (currentBuilder == null)
                return null;
            if (sumsAndPowers.length == 0) {
                currentBuilder = null;
                return tensor;
            }
            Tensor t = sumsAndPowers[sumsAndPowers.length - 1].take();
            if (t == null) {
                currentBuilder = nextCombination();
                sumsAndPowers[sumsAndPowers.length - 1].reset();
                return take();
            }
            ProductBuilder temp = currentBuilder.clone();
            temp.put(t);
            return temp.build();
        }
    }

    private static final class SumPort implements ResettablePort {

        private final OutputPortUnsafe<Tensor>[] ports;
        private final Tensor tensor;
        private int pointer;

        public SumPort(Tensor tensor) {
            this.tensor = tensor;
            this.ports = new OutputPortUnsafe[tensor.size()];
            reset();
        }

        @Override
        public void reset() {
            pointer = 0;
            for (int i = tensor.size() - 1; i >= 0; --i)
                ports[i] = createPort(tensor.get(i));
        }

        @Override
        public Tensor take() {
            Tensor t = null;
            while (pointer < tensor.size()) {
                t = ports[pointer].take();
                if (t == null)
                    ++pointer;
                else
                    return t;
            }
            return t;
        }
    }
}
TOP

Related Classes of cc.redberry.core.transformations.expand.ExpandPort$SumPort

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.