Package cc.redberry.core.solver

Source Code of cc.redberry.core.solver.ReduceEngine

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

import cc.redberry.core.context.CC;
import cc.redberry.core.indices.IndexType;
import cc.redberry.core.indices.IndicesFactory;
import cc.redberry.core.indices.SimpleIndices;
import cc.redberry.core.number.Complex;
import cc.redberry.core.tensor.*;
import cc.redberry.core.tensorgenerator.GeneratedTensor;
import cc.redberry.core.tensorgenerator.TensorGenerator;
import cc.redberry.core.tensorgenerator.TensorGeneratorUtils;
import cc.redberry.core.transformations.CollectNonScalarsTransformation;
import cc.redberry.core.transformations.EliminateMetricsTransformation;
import cc.redberry.core.transformations.Transformation;
import cc.redberry.core.transformations.TransformationCollection;
import cc.redberry.core.transformations.expand.ExpandTransformation;
import cc.redberry.core.utils.TensorUtils;
import gnu.trove.set.hash.TIntHashSet;

import java.util.*;

import static cc.redberry.core.indices.IndicesUtils.*;

/**
* This class implements an algorithm for reducing a system of tensorial equations into system of symbolic equations.
* The underlying algorithm simply generates tensor of the most general form for each unknown tensorial variable and
* then tries to build a system of equations fot its coefficients.
* <p/>
* <b>Note:</b> the implementation does not guaranties that solution (or proof of its absence) will be found.
* <p/>
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
* @since 1.1.5
*/
public final class ReduceEngine {
    /**
     * Maximum number of tries to reduce the system.
     */
    private static final int ITERATION_LIMIT = 10000;

    private ReduceEngine() {
    }

    /**
     * Tries to reduces a system of tensorial equations into a system of symbolic equations or return {@code null} if
     * it fails to reduce.
     *
     * @param equations equations
     * @param vars      unknown variables
     * @param rules     additional transformations/rules to be applied or taken into account
     * @return reduced system of symbolic equations and solutions general form
     */
    public static ReducedSystem reduceToSymbolicSystem(Expression[] equations, SimpleTensor[] vars,
                                                       Transformation[] rules) {
        return reduceToSymbolicSystem(equations, vars, rules, new boolean[vars.length]);
    }

    /**
     * Tries to reduces a system of tensorial equations into a system of symbolic equations or return {@code null} if
     * it fails to reduce.
     *
     * @param equations     equations
     * @param vars          unknown variables
     * @param rules         additional transformations/rules to be applied or taken into account
     * @param symmetricForm specifies whether solutions should be putted into symmetric form (with respect to upper and
     *                      lower indices separately)
     * @return reduced system of symbolic equations and solutions general form
     */
    public static ReducedSystem reduceToSymbolicSystem(Expression[] equations, SimpleTensor[] vars,
                                                       Transformation[] rules, boolean[] symmetricForm) {

        Tensor[] zeroReduced = new Tensor[equations.length];
        for (int i = equations.length - 1; i >= 0; --i) {
            zeroReduced[i] = Tensors.subtract(equations[i].get(0), equations[i].get(1));
            zeroReduced[i] = ExpandTransformation.expand(zeroReduced[i],
                    EliminateMetricsTransformation.ELIMINATE_METRICS);
            zeroReduced[i] = EliminateMetricsTransformation.eliminate(zeroReduced[i]);
        }

        TIntHashSet varsNames = new TIntHashSet(vars.length);
        for (SimpleTensor var : vars)
            varsNames.add(var.getName());
        Tensor[] samples = getSamples(zeroReduced, varsNames);
        if (samples.length == 0)
            for (int i = 0; i < vars.length; ++i)
                if (vars[i].getIndices().size() != 0)
                    return null;

        final Expression[] generalSolutions = new Expression[vars.length];
        GeneratedTensor generatedTensor;
        ArrayList<SimpleTensor> unknownCoefficients = new ArrayList<>();

        for (int i = 0; i < generalSolutions.length; ++i) {
            if (vars[i].getIndices().size() == 0) {
                SimpleTensor nVar = CC.generateNewSymbol();
                unknownCoefficients.add(nVar);
                generalSolutions[i] = Tensors.expression(vars[i], nVar);
            } else {
                generatedTensor = TensorGenerator.generateStructure(vars[i].getIndices(), samples, vars[i].getIndices().getSymmetries().getInnerSymmetries(), symmetricForm[i], true, true
                );

                unknownCoefficients.ensureCapacity(generatedTensor.coefficients.length);
                for (SimpleTensor st : generatedTensor.coefficients)
                    unknownCoefficients.add(st);
                generalSolutions[i] = Tensors.expression(vars[i], generatedTensor.generatedTensor);
            }
        }


        ArrayList<Transformation> allRules = new ArrayList<>(Arrays.asList(rules));
        allRules.add(0, EliminateMetricsTransformation.ELIMINATE_METRICS);
        Transformation simplification = new TransformationCollection(allRules);

        ArrayList<Expression> reducedSystem = new ArrayList<>();
        for (Tensor equation : zeroReduced) {
            int count = ITERATION_LIMIT;
            do {
                for (Expression solution : generalSolutions)
                    equation = solution.transform(equation);

                equation = ExpandTransformation.expand(equation, simplification);
                equation = simplification.transform(equation);
                equation = CollectNonScalarsTransformation.collectNonScalars(equation);
                if (!TensorUtils.containsSimpleTensors(equation, varsNames))
                    break;

            } while (count-- > 0);
            if (count <= 0)
                throw new RuntimeException("Maximum number of iterations exceeded: the system cannot be reduced after 10 000 iterations.");


            if (equation.getIndices().size() == 0) {
                reducedSystem.add(Tensors.expression(equation, Complex.ZERO));
            } else {
                if (equation instanceof Sum)
                    for (Tensor t : equation)
                        reducedSystem.add(Tensors.expression(Split.splitScalars(t).summand, Complex.ZERO));
                else
                    reducedSystem.add(Tensors.expression(Split.splitScalars(equation).summand, Complex.ZERO));
            }
        }
        return new ReducedSystem(
                reducedSystem.toArray(new Expression[reducedSystem.size()]),
                unknownCoefficients.toArray(new SimpleTensor[unknownCoefficients.size()]),
                generalSolutions);
    }

    private static Tensor[] getSamples(Tensor[] zeroReduced, TIntHashSet vars) {
        Collection<SimpleTensor> content = TensorUtils.getAllDiffSimpleTensors(zeroReduced);
        ArrayList<Tensor> samples = new ArrayList<>(content.size() + 1);
        Set<IndexType> usedTypes = new HashSet<>();

        for (SimpleTensor st : content) {
            if (vars.contains(st.getName()))
                continue;
            if (st.getIndices().size() == 0)
                continue;
            if (Tensors.isKroneckerOrMetric(st)) {
                usedTypes.add(getTypeEnum(st.getIndices().get(0)));
                continue;
            }

            SimpleIndices si = st.getIndices();
            int[] free = new int[si.size()];
            for (int i = si.size() - 1; i >= 0; --i) {
                usedTypes.add(getTypeEnum(si.get(i)));
                free[i] = createIndex(i, getType(si.get(i)), getState(si.get(i)));
            }
            st = Tensors.setIndices(st, IndicesFactory.createSimple(null, si));
            samples.addAll(Arrays.asList(TensorGeneratorUtils.allStatesCombinations(st)));
        }

        for (IndexType type : usedTypes) {
            byte btype = type.getType();
            //adding Kronecker
            samples.add(Tensors.createKronecker(setType(btype, 0), 0x80000000 | setType(btype, 1)));
            if (CC.isMetric(btype)) {
                samples.add(Tensors.createMetric(setType(btype, 0), setType(btype, 1)));
                samples.add(Tensors.createMetric(0x80000000 | setType(btype, 0), 0x80000000 | setType(btype, 1)));
            }
        }
        return samples.toArray(new Tensor[samples.size()]);
    }
}
TOP

Related Classes of cc.redberry.core.solver.ReduceEngine

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.