All Downloads are FREE. Search and download functionalities are using the official Maven repository.

cc.redberry.core.context.Context Maven / Gradle / Ivy

Go to download

Redberry is an open source computer algebra system designed for tensor manipulation. It implements basic computer algebra system routines as well as complex tools for real computations in physics. This is Redberry core, which contains the implementation of the basic computer algebra routines and general-purpose transformations.

The newest version!
/*
 * Redberry: symbolic tensor computations.
 *
 * Copyright (c) 2010-2015:
 *   Stanislav Poslavsky   
 *   Bolotin Dmitriy       
 *
 * 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 .
 */
package cc.redberry.core.context;

import cc.redberry.core.indices.*;
import cc.redberry.core.parser.ParseManager;
import cc.redberry.core.tensor.SimpleTensor;
import cc.redberry.core.tensor.Tensor;
import cc.redberry.core.tensor.TensorField;
import cc.redberry.core.tensor.Tensors;
import cc.redberry.core.utils.BitArray;
import cc.redberry.core.utils.OutputPort;
import org.apache.commons.math3.random.RandomGenerator;

import java.util.Collections;
import java.util.EnumSet;
import java.util.Set;

/**
 * This class represents Redberry context. It stores all Redberry session data (in some sense it stores static data).
 * 

*

Management of current Redberry context is made through {@link ContextManager} class. * Context of Redberry is attached to the current thread, so that any thread created from the outside of Redebrry * will hold a unique instance of {@link Context} object. In such a way tensors created in one thread can not * be used in the other thread because they are in some sense "attached" to the initial thread. However, if thread is * created through the executor service which is obtained from {@link ContextManager#getExecutorService()}, it will * share the same context as initial thread (such threads could hold concurrent computations regarding single context, * the appropriate synchronization is assumed). In order to create a new session of Redberry with a particular context, * an instance of this class should be set as a current context via {@link ContextManager#setCurrentContext(Context)}.

* * @author Dmitry Bolotin * @author Stanislav Poslavsky * @see NameManager * @see IndexConverterManager * @see ParseManager * @see OutputFormat * @see ContextManager * @see ContextSettings * @since 1.0 */ public final class Context { /** * NameManager has a sense of namespace */ private final NameManager nameManager; /** * Defaults output format can be changed during the session */ private OutputFormat defaultOutputFormat; private final IndexConverterManager converterManager; private final ParseManager parseManager; /** * Holds information about metric types. * This is a "map" from (byte) type to (bit) isMetric */ private final BitArray metricTypesBits = new BitArray(128); /** * Metric types. */ private final Set metricTypes; /** * Matrix types. */ private final Set matrixTypes; /** * Creates context from the settings * * @param contextSettings settings * @see ContextSettings */ public Context(ContextSettings contextSettings) { this.parseManager = new ParseManager(contextSettings.getParser()); this.converterManager = contextSettings.getConverterManager(); this.nameManager = new NameManager(contextSettings.getNameManagerSeed(), contextSettings.getKronecker(), contextSettings.getMetricName()); this.defaultOutputFormat = contextSettings.getDefaultOutputFormat(); EnumSet metricTypes = EnumSet.noneOf(IndexType.class); EnumSet matrixTypes = EnumSet.allOf(IndexType.class); for (IndexType type : contextSettings.getMetricTypes()) { matrixTypes.remove(type); metricTypes.add(type); this.metricTypesBits.set(type.getType()); } this.metricTypes = Collections.unmodifiableSet(metricTypes); this.matrixTypes = Collections.unmodifiableSet(matrixTypes); } /** * Returns all metric types. * * @return all metric types */ public Set getMetricTypes() { return metricTypes; } /** * Returns all matrix types. * * @return all matrix types */ public Set getMatrixTypes() { return matrixTypes; } /** * This method resets all tensor names in the namespace. *

*

Any tensor created before this method call becomes invalid, and * must not be used! This method is mainly used in unit tests, so * avoid invocations of this method in general computations.

*/ public synchronized void resetTensorNames() { nameManager.reset(); } /** * Resets all definitions. */ public synchronized void reset() { resetTensorNames(); parseManager.reset(); } /** * This method resets all tensor names in the namespace and sets a * specified seed to the {@link NameManager}. If this method is invoked * with constant seed before any interactions with Redberry, further * behaviour of Redberry will be fully deterministic from run to run * (order of summands and multipliers will be fixed, computation time * will be pretty constant, hash codes will be the same). *

*

Any tensor created before this method call becomes invalid, and * must not be used! This method is mainly used in unit tests, so * avoid invocations of this method in general computations.

*/ public synchronized void resetTensorNames(long seed) { nameManager.reset(seed); } /** * Sets the default output format. After this step, all expressions * will be printed according to the specified output format. * * @param defaultOutputFormat output format */ public void setDefaultOutputFormat(OutputFormat defaultOutputFormat) { this.defaultOutputFormat = defaultOutputFormat; } /** * Returns current default output format. * * @return current default output format */ public OutputFormat getDefaultOutputFormat() { return defaultOutputFormat; } /** * Returns index converter manager of current session. * * @return index converter manager of current session */ public IndexConverterManager getIndexConverterManager() { return converterManager; } /** * Returns the name manager (namespace) of current session. * * @return the name manager (namespace) of current session. */ public NameManager getNameManager() { return nameManager; } /** * Returns {@code NameDescriptor} corresponding to the specified {@code int} nameId. * * @param nameId integer name of tensor * @return corresponding {@code NameDescriptor} */ public NameDescriptor getNameDescriptor(int nameId) { return nameManager.getNameDescriptor(nameId); } /** * Returns string representation of Kronecker delta name * * @return string representation of Kronecker delta name */ public String getKroneckerName() { return nameManager.getKroneckerName(); } /** * Returns string representation of metric tensor name * * @return string representation of metric tensor name */ public String getMetricName() { return nameManager.getMetricName(); } /** * Sets the default metric tensor name. After this step, metric tensor * will be printed with the specified string name. * * @param name string representation of metric tensor name */ public void setMetricName(String name) { nameManager.setMetricName(name); } /** * Sets the default Kronecker tensor name. After this step, Kronecker tensor * will be printed with the specified string name. * * @param name string representation of Kronecker tensor name */ public void setKroneckerName(String name) { nameManager.setKroneckerName(name); } /** * Returns {@code true} if specified tensor is a Kronecker tensor * * @param t tensor * @return {@code true} if specified tensor is a Kronecker tensor */ public boolean isKronecker(SimpleTensor t) { return nameManager.isKroneckerOrMetric(t.getName()) && !IndicesUtils.haveEqualStates(t.getIndices().get(0), t.getIndices().get(1)); } /** * Returns {@code true} if specified tensor is a metric tensor * * @param t tensor * @return {@code true} if specified tensor is a metric tensor */ public boolean isMetric(SimpleTensor t) { return nameManager.isKroneckerOrMetric(t.getName()) && IndicesUtils.haveEqualStates(t.getIndices().get(0), t.getIndices().get(1)); } /** * Returns {@code true} if specified tensor is a metric or a Kronecker tensor * * @param t tensor * @return {@code true} if specified tensor is a metric or a Kronecker tensor */ public boolean isKroneckerOrMetric(SimpleTensor t) { return nameManager.isKroneckerOrMetric(t.getName()); } /** * Returns parse manager of current session * * @return parse manager of current session */ public ParseManager getParseManager() { return parseManager; } /** * Allows to parse expressions with repeated indices of the same variance (like T_aa or T_a*T^a which results in T^a_a * and T^a*T_a respactively) * * @param b allow or not to parse repeated indices with same variance */ public void setParserAllowsSameVariance(boolean b) { parseManager.getParser().setAllowSameVariance(b); } /** * Returns whether repeated indices of the same variance are allowed to be parsed * * @return whether repeated indices of the same variance are allowed to be parsed */ public boolean getParserAllowsSameVariance() { return parseManager.getParser().isAllowSameVariance(); } /** * Returns true if metric is defined for the specified index type. * * @param type index type * @return true if metric is defined for the specified index type */ public boolean isMetric(byte type) { return metricTypesBits.get(type); } /** * Returns Kronecker tensor with specified upper and lower indices. * * @param index1 first index * @param index2 second index * @return Kronecker tensor with specified upper and lower indices * @throws IllegalArgumentException if indices have same states * @throws IllegalArgumentException if indices have different types */ public SimpleTensor createKronecker(int index1, int index2) { byte type; if ((type = IndicesUtils.getType(index1)) != IndicesUtils.getType(index2) || IndicesUtils.getRawStateInt(index1) == IndicesUtils.getRawStateInt(index2)) throw new IllegalArgumentException("This is not kronecker indices!"); if (!isMetric(type) && IndicesUtils.getState(index2)) { int t = index1; index1 = index2; index2 = t; } SimpleIndices indices = IndicesFactory.createSimple(null, index1, index2); NameDescriptor nd = nameManager.mapNameDescriptor(nameManager.getKroneckerName(), StructureOfIndices.create(indices)); int name = nd.getId(); return Tensors.simpleTensor(name, indices); } /** * Returns metric tensor with specified indices. * * @param index1 first index * @param index2 second index * @return metric tensor with specified indices * @throws IllegalArgumentException if indices have different states * @throws IllegalArgumentException if indices have different types * @throws IllegalArgumentException if indices have non metric types */ public SimpleTensor createMetric(int index1, int index2) { byte type; if ((type = IndicesUtils.getType(index1)) != IndicesUtils.getType(index2) || !IndicesUtils.haveEqualStates(index1, index2) || !metricTypesBits.get(type)) throw new IllegalArgumentException("Not metric indices."); SimpleIndices indices = IndicesFactory.createSimple(null, index1, index2); NameDescriptor nd = nameManager.mapNameDescriptor(nameManager.getMetricName(), StructureOfIndices.create(indices)); int name = nd.getId(); return Tensors.simpleTensor(name, indices); } /** * Returns metric tensor if specified indices have same states and * Kronecker tensor if specified indices have different states. * * @param index1 first index * @param index2 second index * @return metric tensor if specified indices have same states and * Kronecker tensor if specified indices have different states * @throws IllegalArgumentException if indices have different types * @throws IllegalArgumentException if indices have same states and non metric types */ public SimpleTensor createMetricOrKronecker(int index1, int index2) { if (IndicesUtils.getRawStateInt(index1) == IndicesUtils.getRawStateInt(index2)) return createMetric(index1, index2); return createKronecker(index1, index2); } /** * Generates a new symbol which never used before during current session. * * @return new symbol which never used before during current session */ public SimpleTensor generateNewSymbol() { NameDescriptor nameDescriptor = nameManager.generateNewSymbolDescriptor(); return Tensors.simpleTensor(nameDescriptor.getId(), IndicesFactory.EMPTY_SIMPLE_INDICES); } /** * Returns a delta function with specified arguments * * @param a tensor * @param b tensor * @return DiracDelta[a, b] */ public TensorField createDeltaFunction(Tensor a, Tensor b) { return Tensors.field(nameManager.getDiracDeltaName(), IndicesFactory.EMPTY_SIMPLE_INDICES, new Tensor[]{a, b}); } /** * Return output port which generates new symbol via {@link #generateNewSymbol()} at each {@code take()} invocation. * * @return output port which generates new symbol via {@link #generateNewSymbol()} at each {@code take()} invocation. */ public OutputPort getDefaultParametersGenerator() { return defaultGeneratedParameters; } private final GeneratedParameters defaultGeneratedParameters = new GeneratedParameters(); private final class GeneratedParameters implements OutputPort { @Override public SimpleTensor take() { return generateNewSymbol(); } } /** * Returns random generator used by Redberry in current session. * * @return random generator used by Redberry in current session */ public RandomGenerator getRandomGenerator() { return nameManager.getRandomGenerator(); } /** * Returns the current context of Redberry session. * * @return the current context of Redberry session. */ public static Context get() { return ContextManager.getCurrentContext(); } }




© 2015 - 2024 Weber Informatics LLC | Privacy Policy