Package cc.redberry.core.tensor

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

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

import cc.redberry.core.indexmapping.IndexMappingBuffer;
import cc.redberry.core.indexmapping.IndexMappingBufferTester;
import cc.redberry.core.indexmapping.IndexMappings;
import cc.redberry.core.indices.Indices;
import cc.redberry.core.indices.IndicesFactory;
import cc.redberry.core.indices.IndicesUtils;
import cc.redberry.core.number.Complex;
import cc.redberry.core.utils.TensorHashCalculator;
import cc.redberry.core.utils.TensorUtils;
import java.util.*;

/**
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
public final class SumBuilder implements TensorBuilder {

    private final Map<Integer, List<FactorNode>> summands;
    private Complex complex = Complex.ZERO;
    private Indices indices = null;
    private int[] sortedFreeIndices;

    public SumBuilder() {
        this(7);
    }

    public SumBuilder(int initialCapacity) {
        summands = new HashMap<>(initialCapacity);
    }

    @Override
    public Tensor build() {
        if (complex.isNaN() || complex.isInfinite())
            return complex;

        List<Tensor> sum = new ArrayList<>();
        if (!complex.isZero())
            sum.add(complex);

        for (Map.Entry<Integer, List<FactorNode>> entry : summands.entrySet())
            for (FactorNode node : entry.getValue()) {
                Tensor summand = Tensors.multiply(node.build(), node.factor);
                if (!TensorUtils.isZero(summand))
                    sum.add(summand);
            }

        if (sum.isEmpty())
            return complex;
        if (sum.size() == 1)
            return sum.get(0);

        return new Sum(sum.toArray(new Tensor[sum.size()]), indices);
    }

    @Override
    public void put(Tensor tensor) {
        if (TensorUtils.isZero(tensor))
            return;
        if (indices == null) {
            indices = IndicesFactory.createSorted(tensor.getIndices().getFree());
            sortedFreeIndices = indices.getAllIndices().copy();
            Arrays.sort(sortedFreeIndices);
        } else if (!indices.equalsRegardlessOrder(tensor.getIndices().getFree()))
            throw new TensorException("Inconsinstent indices in sum.", tensor);//TODO improve message
        if (tensor instanceof Sum) {
            for (Tensor s : tensor)
                put(s);
            return;
        }
        if (tensor instanceof Complex) {
            complex = complex.add((Complex) tensor);
            return;
        }

        Split split = Split.split(tensor);

        Integer hash = TensorHashCalculator.hashWithIndices(split.factor, sortedFreeIndices);//=split.factor.hashCode();
        List<FactorNode> factorNodes = summands.get(hash);
        if (factorNodes == null) {
            List<FactorNode> fns = new ArrayList<>();
            fns.add(new FactorNode(split.factor, split.getBuilder()));
            summands.put(hash, fns);
        } else {
            Boolean b = null;
            for (FactorNode node : factorNodes)
                if ((b = compareFactors(split.factor, node.factor)) != null) {
                    if (b)
                        node.put(Tensors.negate(split.summand));
                    else
                        node.put(split.summand);
                    break;
                }
            if (b == null)
                factorNodes.add(new FactorNode(split.factor, split.getBuilder()));
        }
    }

    static Boolean compareFactors(Tensor u, Tensor v) {
        IndexMappingBuffer buffer;
        if (u.getIndices().size() == 0)
            buffer = IndexMappings.createPort(u, v).take();
        else {
            int[] fromIndices = u.getIndices().getFree().getAllIndices().copy();
            for (int i = 0; i < fromIndices.length; ++i)
                fromIndices[i] = IndicesUtils.getNameWithType(fromIndices[i]);
            buffer = IndexMappings.createPort(new IndexMappingBufferTester(fromIndices, false), u, v).take();
        }
        if (buffer == null)
            return null;
        assert buffer.isEmpty();
        return buffer.getSignum();
    }
}
TOP

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

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.