Package cc.redberry.core.tensor

Source Code of cc.redberry.core.tensor.ProductBuilder

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

import cc.redberry.core.indices.IndicesBuilder;
import cc.redberry.core.number.Complex;
import cc.redberry.core.utils.TensorUtils;

import java.util.ArrayList;
import java.util.Arrays;

import static cc.redberry.core.number.NumberUtils.isZeroOrIndeterminate;
import static cc.redberry.core.transformations.ToNumericTransformation.toNumeric;

/**
* Implementation of product builder. It performs basic simplifications and reduces the
* resulting product to the standard form.
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
* @since 1.0
*/
public final class ProductBuilder implements TensorBuilder {

    private Complex factor = Complex.ONE;
    private final ArrayList<Tensor> elements, indexLess;
    /* hash -> list of power nodes */
    private final PowersContainer symbolicPowers;

    /**
     * Creates builder with initial capacities of indexless and indexed parts.
     *
     * @param initialCapacityIndexless initial capacity of indexless data
     * @param initialCapacityData      initial capacity of indexed data
     */
    public ProductBuilder(int initialCapacityIndexless, int initialCapacityData) {
        elements = new ArrayList<>(initialCapacityData);
        symbolicPowers = new PowersContainer(initialCapacityIndexless);
        indexLess = new ArrayList<>();
    }

    /**
     * Creates builder with default initial capacity.
     */
    public ProductBuilder() {
        this(4, 3);
    }

    private ProductBuilder(Complex factor, ArrayList<Tensor> elements, ArrayList<Tensor> indexLess, PowersContainer powers) {
        this.factor = factor;
        this.elements = elements;
        this.indexLess = indexLess;
        this.symbolicPowers = powers;
    }


    private void initializeData(Complex complex, Tensor[] indexlessData, Tensor[] data) {
        this.factor = complex.multiply(this.factor);
        if (isZeroOrIndeterminate(this.factor))
            return;
        elements.addAll(Arrays.asList(data));
        Tensor base, exponent;
        for (Tensor t : indexlessData) {
            if (TensorUtils.isSymbolic(t)) {
                if (t instanceof Power) {
                    //case x^y
                    base = t.get(0);
                    exponent = t.get(1);
                } else {
                    //case x^1 (= x)
                    base = t;
                    exponent = Complex.ONE;
                }
                symbolicPowers.putNew(base, exponent);
            } else
                indexLess.add(t);
        }
    }

    private boolean isEmpty() {
        return symbolicPowers.isEmpty() && elements.isEmpty();
    }

    @Override
    public Tensor build() {
        if (isZeroOrIndeterminate(factor))
            return factor;
        final boolean isNumeric = factor.isNumeric();
        for (Tensor t : symbolicPowers) {
            assert !(t instanceof Product);

            if (isNumeric)
                t = toNumeric(t);

            if (t instanceof Complex) {
                factor = factor.multiply((Complex) t);
                if (isZeroOrIndeterminate(factor))
                    return factor;
            } else
                indexLess.add(t);
        }
        if (symbolicPowers.isSign())
            factor = factor.negate();

        //Only factor
        if (indexLess.isEmpty() && elements.isEmpty())
            return factor;

        if (isNumeric) {
            ArrayList<Tensor> nonNumbers = new ArrayList<>();
            for (Tensor t : elements) {
                t = toNumeric(t);
                if (t instanceof Complex)
                    factor = factor.multiply((Complex) t);
                else
                    nonNumbers.add(t);
            }
            //Only factor
            if (indexLess.isEmpty() && nonNumbers.isEmpty())
                return factor;
            elements.clear();
            elements.addAll(nonNumbers);
        }

        // 1 * (something)
        if (factor.isOne()) {
            if (indexLess.size() == 1 && elements.isEmpty())
                return indexLess.get(0);
            if (indexLess.isEmpty() && elements.size() == 1)
                return elements.get(0);
        }

        if (factor.isMinusOne()) {
            Sum s = null;
            if (indexLess.size() == 1 && elements.isEmpty() && indexLess.get(0) instanceof Sum)
                //case (-1)*(a+b) -> -a-b
                s = ((Sum) indexLess.get(0));
            if (indexLess.isEmpty() && elements.size() == 1 && elements.get(0) instanceof Sum)
                //case (-1)*(a_i+b_i) -> -a_i-b_i
                s = ((Sum) elements.get(0));
            if (s != null) {
                Tensor sumData[] = s.data.clone();
                for (int i = sumData.length - 1; i >= 0; --i)
                    sumData[i] = Tensors.negate(sumData[i]);
                return new Sum(s.indices, sumData, s.hashCode());
            }
        }

        //Calculating product indices
        IndicesBuilder ibs = new IndicesBuilder();
        for (Tensor m : elements)
            ibs.append(m);
        return new Product(ibs.getIndices(), factor,
                indexLess.toArray(new Tensor[indexLess.size()]),
                elements.toArray(new Tensor[elements.size()]));
    }

    @Override
    public void put(Tensor tensor) {
        if (factor.isNumeric())
            tensor = toNumeric(tensor);
        if (tensor instanceof Complex) {
            factor = factor.multiply((Complex) tensor);
            return;
        }

        if (tensor instanceof Product) {
            Product p = (Product) tensor;
            //if no any elements were added yet
            if (isEmpty()) {
                initializeData(p.factor, p.indexlessData, p.data);
            } else {
                factor = factor.multiply(p.factor);
                if (isZeroOrIndeterminate(factor))
                    return;
                for (Tensor t : p.indexlessData)
                    put(t);
                elements.addAll(Arrays.asList(p.data));
            }
            return;
        }
        if (isZeroOrIndeterminate(factor))
            return;

        if (TensorUtils.isSymbolic(tensor)) {
            symbolicPowers.put(tensor);
        } else if (tensor.getIndices().size() == 0)
            indexLess.add(tensor);
        else
            elements.add(tensor);
    }


    @Override
    public ProductBuilder clone() {
        return new ProductBuilder(factor, new ArrayList<>(elements), new ArrayList<>(indexLess), symbolicPowers.clone());
    }
}
TOP

Related Classes of cc.redberry.core.tensor.ProductBuilder

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.