
cc.redberry.groovy.Redberry.groovy Maven / Gradle / Ivy
/*
* Redberry: symbolic tensor computations.
*
* Copyright (c) 2010-2013:
* 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.groovy
import cc.redberry.core.combinatorics.IntPermutationsGenerator
import cc.redberry.core.indexmapping.IndexMappings
import cc.redberry.core.indexmapping.Mapping
import cc.redberry.core.indexmapping.MappingsPort
import cc.redberry.core.indices.*
import cc.redberry.core.number.Complex
import cc.redberry.core.number.Numeric
import cc.redberry.core.number.Rational
import cc.redberry.core.number.Real
import cc.redberry.core.parser.ParserIndices
import cc.redberry.core.tensor.Expression
import cc.redberry.core.tensor.Tensor
import cc.redberry.core.tensor.TensorBuilder
import cc.redberry.core.tensor.Tensors
import cc.redberry.core.tensor.iterator.FromChildToParentIterator
import cc.redberry.core.tensor.iterator.FromParentToChildIterator
import cc.redberry.core.tensor.iterator.TraverseGuide
import cc.redberry.core.transformations.Transformation
import cc.redberry.core.transformations.TransformationCollection
import cc.redberry.core.transformations.substitutions.SubstitutionIterator
import cc.redberry.core.transformations.substitutions.SubstitutionTransformation
import cc.redberry.core.utils.IntArray
import cc.redberry.core.utils.IntArrayList
import cc.redberry.core.utils.TensorUtils
import org.codehaus.groovy.runtime.DefaultGroovyMethods
import static cc.redberry.core.tensor.Tensors.*
/**
* Redberry category.
*
* @author Dmitry Bolotin
* @author Stanislav Poslavsky
*/
class Redberry {
static Real number2Real(Number num) {
if (num instanceof Double || num instanceof BigDecimal)
return new Numeric(num.doubleValue());
else
return new Rational(num.toBigInteger());
}
private static Complex number2Complex(Number num) {
return new Complex(number2Real(num));
}
/*
* Math operations
*/
/**
* Returns the result of summation of several tensors.
*
* @param a summand
* @param b summand
* @return result of summation
* @throws cc.redberry.core.tensor.TensorException if tensors have different free indices
* @see Tensors#sum(cc.redberry.core.tensor.Tensor ...)
*/
static Tensor plus(Tensor a, Tensor b) { Tensors.sum(a, b); }
/**
* Adds {@code b} to {@code a}
*
* @param a tensor
* @param b number
* @return {@code a} - {@code b}
* @throws cc.redberry.core.tensor.TensorException if a is not scalar
* @see Tensors#sum(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static Tensor plus(Tensor a, Number b) { Tensors.sum(a, number2Complex(b)); }
/**
* Subtracts {@code b} from {@code a}
*
* @param a tensor
* @param b tensor
* @return {@code a} - {@code b}
* @throws cc.redberry.core.tensor.TensorException if tensors have different free indices
* @see Tensors#subtract(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static Tensor minus(Tensor a, Tensor b) { Tensors.subtract(a, b); }
/**
* Subtracts {@code b} from {@code a}
*
* @param a tensor
* @param b number
* @return {@code a} - {@code b}
* @throws cc.redberry.core.tensor.TensorException if a is not scalar
* @see Tensors#subtract(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static Tensor minus(Tensor a, Number b) { Tensors.subtract(a, number2Complex(b)); }
/**
* Returns {@code a} divided by {@code b}.
*
* @param a tensor
* @param b scalar tensor
* @return {@code a} divided by {@code b}.
* @throws IllegalArgumentException if b is not scalar
* @see Tensors#divide(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static Tensor div(Tensor a, Tensor b) { Tensors.divide(a, b); }
/**
* Divides tensor on specified number
* @param a tensor
* @param b number
* @return the result
* @see Tensors#divide(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static Tensor div(Tensor a, Number b) { Tensors.divide(a, number2Complex(b)); }
/**
* Returns result of multiplication of specified tensors taking care about
* all conflicting dummy indices in factors. Einstein notation assumed.
*
* @param a factor
* @param b factor
* @return result of multiplication
* @throws InconsistentIndicesException if there is indices clash
* @see Tensors#multiplyAndRenameConflictingDummies(cc.redberry.core.tensor.Tensor ...)
*/
static Tensor multiply(Tensor a, Tensor b) { multiplyAndRenameConflictingDummies(a, b); }
/**
* Multiplies tensor on number
* @param a tensor
* @param b number
* @return the result
* @see Tensors#multiply(cc.redberry.core.tensor.Tensor ...)
*/
static Tensor multiply(Tensor a, Number b) { Tensors.multiply(a, number2Complex(b)); }
/**
* Power function. Returns tensor raised to specified power.
*
* @param a base
* @param b power
* @return result of argument exponentiation
* @throws IllegalArgumentException if argument or power is not scalar
* @see Tensors#pow(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static Tensor power(Tensor a, Tensor b) { Tensors.pow(a, b); }
/**
* Power function. Returns tensor raised to specified power.
*
* @param a base
* @param b power
* @return result of argument exponentiation
* @throws IllegalArgumentException if argument or power is not scalar
* @see Tensors#pow(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static Tensor power(Tensor a, Number b) { Tensors.pow(a, number2Complex(b)); }
/**
* Multiplies specified tensor by minus one.
*
* @param a tensor to be negotiated
* @return tensor negate to specified one
* @see Tensors#negate(cc.redberry.core.tensor.Tensor)
*/
static Tensor negative(Tensor a) { negate(a); }
/**
* Returns tensor
* @param a tensor
* @return tensor
*/
static Tensor positive(Tensor a) { a; }
/**
* Returns element at i-th position.
*
* @param a tensor
* @param i position
* @return element at i-th position
* @throws IndexOutOfBoundsException if {@code i < 0} or {@code i >= size()}
* @see Tensor#get(int)
*/
static Tensor getAt(Tensor a, int i) { a.get(i); }
/**
* Returns element at specified positions in expression-tree
* @param a tensor
* @param positions positions in tree
* @return element at specified positions in expression-tree
* @see Tensor#get(int)
*/
static Tensor getAt(Tensor a, Collection positions) {
for (int i : positions)
a = a.get(i)
return a;
}
/**
* Retrieves several sub-tensors from current tensor. This function is
* faster than sequential invocations of {@link Tensor#get(int)} method.
*
* @param a tensor
* @param range integer range
* @return array with retrieved tensors
* @see Tensor#getRange(int, int)
*/
static Tensor[] getAt(Tensor a, IntRange range) {
int from = range.fromInt, to = range.toInt;
if (from == 0 && to == a.size())
return a.toArray();
return a.getRange(from, to);
}
/**
* Overloads the left shift operator to provide an easy way to put tensors to a TensorBuilder.
* @param builder tensor builder
* @param tensor a tensor to be putted to the tensor builder.
* @return same builder, after the value was putted to it.
*/
static TensorBuilder leftShift(TensorBuilder builder, Tensor tensor) {
builder.put(tensor);
return builder;
}
/**
* Overloads the left shift operator to provide an easy way to put a collections of tensors to a TensorBuilder.
* @param builder tensor builder
* @param tensors a collection of tensors to be sequentially putted to the tensor builder.
* @return same builder, after the value was putted to it.
*/
static TensorBuilder leftShift(TensorBuilder builder, Collection tensors) {
for (Tensor t : tensors)
builder.put(t)
return builder;
}
/**
* Overloads the left shift operator to provide an easy way to put an array of tensors to a TensorBuilder.
* @param builder tensor builder
* @param tensors an array of tensors to be sequentially putted to the tensor builder.
* @return same builder, after the value was putted to it.
*/
static TensorBuilder leftShift(TensorBuilder builder, Tensor[] tensors) {
for (Tensor t : tensors)
builder.put(t)
return builder;
}
/**
* Returns a list of tensor content
* @param tensor tensor
* @return a list of tensor content
*/
static List toList(Tensor tensor) {
return tensor.toArray() as List
}
/**
* Tensor as array, list etc.
* @param tensor
* @param clazz
* @return
*/
static Object asType(Tensor tensor, Class clazz) {
if (clazz == List)
return tensor.toArray() as List
else if (clazz == Tensor[])
return tensor.toArray()
else
return DefaultGroovyMethods.asType(tensor, clazz)
}
/*
* Indices
*/
/**
* Returns the index at the specified position in indices
*
* @param indices indices
* @param position position of the index
* @return the index at the specified position in this
* Indices
* @throws IndexOutOfBoundsException - if the index is out of range (index <
* 0 || index >= size())
* @see Indices#get(int)
*/
static int getAt(Indices indices, int position) { indices.get(position) }
/**
* Returns sub indices of specified range
*
* @param indices indices
* @param range range
* @return sub indices of specified range
* @throws IndexOutOfBoundsException
*/
static Indices getAt(Indices indices, IntRange range) {
int[] sub = new int[range.size()]
for (int i = 0; i < range.size(); ++i)
sub[i] = indices.get(i + range.from);
return IndicesFactory.create(sub)
}
/**
* Returns sub indices of specified range
*
* @param indices indices
* @param range range
* @return sub indices of specified range
* @throws IndexOutOfBoundsException
*/
static SimpleIndices getAt(SimpleIndices indices, IntRange range) {
int[] sub = new int[range.size()]
for (int i = 0; i < range.size(); ++i)
sub[i] = indices.get(i + range.from);
return IndicesFactory.createSimple(null, sub)
}
/**
* Returns the index of the specified type at the
* specified position in indices
*
* @param indices indices
* @param type IndexType
* @param position position of the index to return
* @return the index of the specified type at the
* specified position in this Indices
* @throws IndexOutOfBoundsException - if the index is out of range
* @see Indices#get(cc.redberry.core.indices.IndexType, int)
*/
static int getAt(Indices indices, IndexType type, int position) { indices.get(type, position) }
static Object asType(Indices indices, Class clazz) {
if (clazz == int[])
return indices.getAllIndices().copy()
else
return DefaultGroovyMethods.asType(indices, clazz)
}
static Indices asType(int[] indices, Class clazz) {
if (clazz == SimpleIndices)
return IndicesFactory.createSimple(null, indices)
else if (clazz == Indices)
return IndicesFactory.create(indices)
else
return DefaultGroovyMethods.asType(indices, clazz)
}
static Indices asType(IntArray indices, Class clazz) {
if (clazz == SimpleIndices)
return IndicesFactory.createSimple(null, indices.copy())
else if (clazz == Indices)
return IndicesFactory.create(indices.copy())
else
return DefaultGroovyMethods.asType(indices, clazz)
}
/**
* Iterator over single indices integers in {@code indices} object
* @param indices indices
* @return iterator over integers
*/
static Iterator iterator(final Indices indices) {
def position = 0;
new Iterator() {
@Override
boolean hasNext() {
return position < indices.size()
}
@Override
Integer next() {
return indices.get(position++)
}
@Override
void remove() {
throw new UnsupportedOperationException()
}
}
}
/**
* Returns true if specified index is contained in indices
* @param indices indices
* @param index single index
* @return true if specified index is contained in indices
*/
static boolean contains(Indices indices, int index) {
//todo move to Indices
for (int i = indices.size() - 1; i >= 0; --i)
if (indices.get(i) == index)
return true
return false
}
/**
* Returns true if specified index is contained in indices
* @param indices indices
* @param index single index
* @return true if specified index is contained in indices
*/
static boolean containsIgnoringState(Indices indices, int index) {
//todo move to Indices
index = IndicesUtils.getNameWithType(index)
for (int i = indices.size() - 1; i >= 0; --i)
if (IndicesUtils.getNameWithType(indices.get(i)) == index)
return true
return false
}
/**
* SimpleIndices concatenation
* @param indices simple indices
* @param toAdd to add
* @return new indices
* @see SimpleIndicesBuilder
* @throws InconsistentIndicesException if there was more then one same index (with same names, types and states)
*/
static SimpleIndices plus(SimpleIndices indices, toAdd) {
if (toAdd instanceof String)
toAdd = ParserIndices.parseSimple(toAdd);
if (toAdd instanceof Indices || toAdd instanceof Integer || toAdd instanceof int[])
return new SimpleIndicesBuilder().append(indices).append(toAdd).indices;
if (toAdd instanceof Collection)
return new SimpleIndicesBuilder().append(indices).append(toAdd as int[]).indices;
else
throw new IllegalArgumentException()
}
/**
* Indices concatenation
* @param indices indices
* @param toAdd to add
* @return new indices
* @see IndicesBuilder
* @throws InconsistentIndicesException if there was more then one same index (with same names, types and states)
*/
static Indices plus(Indices indices, toAdd) {
if (toAdd instanceof String)
toAdd = ParserIndices.parseSimple(toAdd);
if (toAdd instanceof Indices || toAdd instanceof Integer || toAdd instanceof int[])
return new SimpleIndicesBuilder().append(indices).append(toAdd).indices;
if (toAdd instanceof Collection)
return new IndicesBuilder().append(indices).append(toAdd as int[]).indices;
else
throw new IllegalArgumentException()
}
static boolean equals(SimpleIndices a, SimpleIndices b) {
return Arrays.equals(a.allIndices.copy(), b.allIndices.copy())
}
/*
* Tensor traversing
*/
/**
* Expression-tree traversal parent-after-child
* @param t expression
* @param closure do stuff
* @param guide traverse guide
* @see FromChildToParentIterator
*/
static void parentAfterChild(Tensor t, Object guide, Closure closure) {
FromChildToParentIterator iterator = new FromChildToParentIterator(t, guide);
Tensor c;
while ((c = iterator.next()) != null)
closure.call(c);
}
/**
* Expression-tree traversal parent-before-child
* @param t expression
* @param closure do stuff
* @param guide traverse guide
* @see FromParentToChildIterator
* @see TraverseGuide
*/
static void parentBeforeChild(Tensor t, TraverseGuide guide, Closure closure) {
FromParentToChildIterator iterator = new FromParentToChildIterator(t, guide);
Tensor c;
while ((c = iterator.next()) != null)
closure.call(c);
}
/**
* Expression-tree traversal parent-after-child
* @param t expression
* @param closure do stuff
* @see FromChildToParentIterator
*/
static void parentAfterChild(Tensor t, Closure closure) {
parentAfterChild(t, TraverseGuide.ALL, closure)
}
/**
* Expression-tree traversal parent-before-child
* @param t expression
* @param closure do stuff
* @see FromParentToChildIterator
*/
static void parentBeforeChild(Tensor t, Closure closure) {
parentBeforeChild(t, TraverseGuide.ALL, closure)
}
/*
* Tree modification
*/
/**
* Expression-tree traversal and modification
* @param t expression
* @param closure do stuff
* @param guide traverse guide
* @return the result
* @see SubstitutionIterator
* @see TraverseGuide
*/
static Tensor transformParentAfterChild(Tensor t, TraverseGuide guide, Closure closure) {
SubstitutionIterator iterator = new SubstitutionIterator(t, guide);
Tensor c;
while ((c = iterator.next()) != null)
iterator.safeSet(closure.call(c));
return iterator.result();
}
/**
* Expression-tree traversal and modification
* @param t expression
* @param closure do stuff
* @return the result
* @see SubstitutionIterator
*/
static Tensor transformParentAfterChild(Tensor t, Closure closure) {
return transformParentAfterChild(t, TraverseGuide.ALL, closure);
}
//todo implement
// static Tensor transformParentBeforeChild(Tensor t, TraverseGuide guide, Closure closure) {
// }
//
// static Tensor transformParentBeforeChild(Tensor t, Closure closure) {
// return transformParentBeforeChild(t, TraverseGuide.ALL, closure);
// }
/*
* Transformations
*/
/**
* Joins two transformations in a single one, which will apply both transformations sequentially
* @param tr1 transformation
* @param tr2 transformation
* @return joined transformation, which will apply both transformations sequentially
*/
static Transformation and(Transformation tr1, Transformation tr2) {
def transformations = [];
if (tr1 instanceof TransformationCollection)
transformations.addAll(tr1.transformations)
else
transformations << tr1
if (tr2 instanceof TransformationCollection)
transformations.addAll(tr2.transformations)
else
transformations << tr2
new TransformationCollection(transformations)
}
/**
* Joins two substitutions in a single one, which will apply both substitutions "simultaneously"
* @param tr1 substitution
* @param tr2 substitution
* @return joined substitution, which will apply both substitutions "simultaneously"
* @see SubstitutionTransformation
*/
static Transformation or(Transformation tr1, Transformation tr2) {
def expressions = [];
if (tr1 instanceof SubstitutionContainer)
expressions.addAll(tr1.expressions)
else if (tr1 instanceof Expression)
expressions << tr1
else throw new IllegalArgumentException()
if (tr2 instanceof SubstitutionContainer)
expressions.addAll(tr2.expressions)
else if (tr2 instanceof Expression)
expressions << tr2
else throw new IllegalArgumentException()
new SubstitutionContainer(expressions)
}
private static final class SubstitutionContainer implements Transformation {
final List expressions;
SubstitutionContainer(expressions) {
this.expressions = expressions
}
@Override
Tensor transform(Tensor t) {
return new SubstitutionTransformation(expressions.toArray(new Expression[expressions.size()]), false).transform(t)
}
@Override
public String toString() {
return expressions
}
}
private static boolean isCollectionOfType(collection, Class type) {
for (t in collection)
if (!type.isAssignableFrom(t.class))
return false;
return true;
}
/**
* Applies transformation to tensor
* @param tensor tensor
* @param transformation transformation
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
*/
static Tensor rightShift(Transformation transformation, Tensor tensor) {
return transformation.transform(tensor);
}
/**
* Applies transformation to a collection of tensors
* @param tensors tensors
* @param transformation transformation
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
*/
static Collection rightShift(Transformation transformation, Collection tensors) {
return tensors.collect { rightShift(transformation, it) }
}
/**
* Applies substitution to tensor
* @param tensor tensor
* @param transformation string representation of substitution
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
*/
static Tensor rightShift(String transformation, Tensor tensor) {
return parseExpression(transformation).transform(tensor);
}
/**
* Applies collection of transformations to tensor
* @param tensor tensor
* @param transformations collection of transformations
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
*/
static Tensor rightShift(Collection transformations, Tensor tensor) {
transformations = transformations.collect { if (it instanceof String) parse(it); else it; }
if (isCollectionOfType(transformations, Expression))
return new SubstitutionTransformation(transformations as Expression[]).transform(tensor);
def t = tensor
for (Transformation tr in transformations)
t = tr.transform(t);
return t;
}
/**
* Applies collection of transformations to a collection of tensors
* @param tensors tensors
* @param transformations collection of transformations
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
*/
static Collection rightShift(Collection transformations, Collection tensors) {
return tensors.collect { rightShift(transformations, it) }
}
/**
* Applies collection of transformations to collection of expressions represented by
* {@link TransformationCollection}
*
* @param tensor tensor
* @param transformations collection of transformations
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
* @throws RuntimeException if {@code collection} is not a collection of expressions
*/
static TransformationCollection rightShift(Transformation transformation, TransformationCollection collection) {
return new TransformationCollection(collection.transformations.collect { transformation.transform(it) })
}
/**
* Applies collection of transformations to collection of expressions represented by
* {@link TransformationCollection}
*
* @param tensor tensor
* @param transformations collection of transformations
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
* @throws RuntimeException if {@code collection} is not a collection of expressions
*/
static TransformationCollection leftShift(TransformationCollection collection, Transformation transformation) {
return rightShift(transformation, collection)
}
/**
* Applies transformation to tensor
* @param tensor tensor
* @param transformation transformation
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
*/
static Tensor leftShift(Tensor tensor, Transformation transformation) {
return transformation.transform(tensor);
}
/**
* Applies collection of transformations to tensor
* @param tensor tensor
* @param transformations collection of transformations
* @return the result
* @see Transformation#transform(cc.redberry.core.tensor.Tensor)
*/
static Tensor leftShift(Tensor tensor, Collection transformations) {
if (isCollectionOfType(transformations, Expression))
return new SubstitutionTransformation(transformations as Expression[]).transform(tensor);
def t = tensor
for (Transformation tr in transformations)
t = tr.transform(t);
return t;
}
/*
* Type conversions
*/
static Object asType(Collection collection, Class clazz) {
if (clazz == Indices)
return IndicesFactory.create(* collection)
if (clazz == Transformation)
return new TransformationCollection(collection)
return DefaultGroovyMethods.asType(collection, clazz);
}
static Tensor asType(Number num, Class clazz) {
if (clazz == Tensor)
return number2Complex(num)
return DefaultGroovyMethods.asType(num, clazz)
}
static Object asType(String string, Class clazz) {
if (clazz == Tensor)
return parse(string);
return DefaultGroovyMethods.asType(string, clazz);
}
/*
* Tensor comparison and Mapping
*/
/**
* Returns {@code true} if tensors are mathematically (not programmatically) equal
* @param a tensor
* @param b tensor
* @return {@code true} if tensors are mathematically (not programmatically) equal, {@code false} otherwise
* @see TensorUtils#equals(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
*/
static boolean equals(Tensor a, Tensor b) {
return TensorUtils.equals(a, b);
}
/**
* Returns the container of mappings from tensor {@code from} onto tensor {@code to}. This structure is iterable
* and also can be manipulated as single transformation which simply applies first possible mapping.
*
* @param from {@code from} tensor
* @param to {@code to} tensor
* @return container of mappings
*/
static MappingsContainer mod(Tensor from, Tensor to) {
return new MappingsContainer(from, to);
}
/**
* This class describes the container of mappings from one tensor onto another. This structure is iterable
* and also can be manipulated as single transformation which simply applies first possible mapping.
*/
public static final class MappingsContainer implements Transformation, Iterable {
private final Tensor from, to
private boolean firstCalculated = false
private Mapping first = null
MappingsContainer(Tensor from, Tensor to) {
this.from = from
this.to = to
}
@Override
Tensor transform(Tensor t) {
return getFirst().transform(t)
}
/**
* Returns the first possible mapping
* @return first possible mapping
*/
public Mapping getFirst() {
if (!firstCalculated) {
first = IndexMappings.getFirst(from, to)
firstCalculated = true
}
return first
}
/**
* Returns the output port of possible mappings
* @return port of possible mappings
*/
public MappingsPort getPort() {
return IndexMappings.createPort(from, to)
}
@Override
Iterator iterator() {
return new MappingsIterator(getPort())
}
@Override
public String toString() {
return getFirst().toString()
}
private static class MappingsIterator implements Iterator {
private final MappingsPort port
private Mapping previous, next
MappingsIterator(MappingsPort port) {
this.port = port
next = port.take()
}
@Override
boolean hasNext() {
return next != null
}
@Override
Mapping next() {
previous = next
next = port.take()
return previous
}
@Override
void remove() {
throw new UnsupportedOperationException()
}
}
}
/*
* Matrix descriptors
*/
/**
* Covector with respect to specified type
* @param type index type
* @return matrix descriptor of covector with specified type
* @see IndexType
* @see cc.redberry.groovy.RedberryStatic#defineMatrices(java.lang.Object [])
*/
static MatrixDescriptor getCovector(IndexType type) {
return new MatrixDescriptor(type, 0, 1);
}
/**
* Vector with respect to specified type
* @param type index type
* @return matrix descriptor of vector with specified type
* @see IndexType
* @see cc.redberry.groovy.RedberryStatic#defineMatrices(java.lang.Object [])
*/
static MatrixDescriptor getVector(IndexType type) {
return new MatrixDescriptor(type, 1, 0);
}
/**
* Matrix with respect to specified type
* @param type index type
* @return matrix descriptor of matrix with specified type
* @see IndexType
* @see cc.redberry.groovy.RedberryStatic#defineMatrices(java.lang.Object [])
*/
static MatrixDescriptor getMatrix(IndexType type) {
return new MatrixDescriptor(type, 1, 1);
}
/**
* Generalized matrix with respect to specified type with specified number of upper and lower indices
* @param type index type
* @param upper number of upper indices
* @param lower number of lower indices
* @return matrix descriptor of generalized matrix with specified type
* @see IndexType
* @see cc.redberry.groovy.RedberryStatic#defineMatrices(java.lang.Object [])
*/
static MatrixDescriptor tensor(IndexType type, int upper, int lower) {
return new MatrixDescriptor(type, upper, lower);
}
/*
* Parse
*/
/**
* Parse string to tensor
* @param string string representation of tensor
* @return tensor
* @see Tensor
* @see Tensors#parse(java.lang.String)
* @throws cc.redberry.core.parser.ParserException
* if expression does not satisfy correct Redberry
* input notation for tensors
*
*/
static Tensor getT(String string) {
return parse(string)
}
/**
* Parse collection of strings to colection of tensors
* @param strings string representations of tensors
* @return collection of tensors
* @see Tensor
* @see Tensors#parse(java.lang.String)
*
* @throws cc.redberry.core.parser.ParserException
* if expression does not satisfy correct Redberry
* input notation for tensors
*
*/
static Collection getT(Collection strings) {
return strings.collect {
if (it instanceof String || it instanceof GString)
return parse(it)
else return it
}
}
/**
* Parse string to tensor
* @param string string representation of tensor
* @return tensor
* @see Tensor
* @see Tensors#parse(java.lang.String)
* @throws cc.redberry.core.parser.ParserException
* if expression does not satisfy correct Redberry
* input notation for tensors
*/
static Tensor getT(GString string) {
return parse(string.toString())
}
static Tensor getT(Tensor tensor) {
return tensor
}
/**
* Gives Redberry representation of number
* @param number number
* @return Redberry representation of number
* @see Complex
*/
static Tensor getT(Number number) {
return number2Complex(number)
}
/**
* Parse string to indices
* @param string string representation of indices
* @return indices
* @see Indices
* @see ParserIndices#parseSimple(java.lang.String)
* @see IndicesFactory#create(cc.redberry.core.indices.Indices)
* @throws IllegalArgumentException if string does not represent correct indices object.
*/
static Indices getI(String string) {
return IndicesFactory.create(ParserIndices.parseSimple(string))
}
/**
* Parse string to simple indices
* @param string string representation of simple indices
* @return simple indices
* @see SimpleIndices
* @see ParserIndices#parseSimple(java.lang.String)
* @throws IllegalArgumentException if string does not represent correct indices object.
*/
static SimpleIndices getSi(String string) {
return ParserIndices.parseSimple(string)
}
/*
* Tensor creation
*/
/**
* Creates {@link Expression} from given l.h.s. and r.h.s.
* @param lhs l.h.s. of the expression
* @param rhs r.h.s. of the expression
* @return expression
* @see Tensors#parse(java.lang.String)
* @see Tensors#expression(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
* @throws cc.redberry.core.parser.ParserException
* if expression does not satisfy correct Redberry
* input notation for tensors
* @throws IllegalArgumentException if l.h.s. free indices are not matches r.h.s. free indices
*/
static Tensor eq(String lhs, Tensor rhs) {
return expression(parse(lhs), rhs)
}
/**
* Creates {@link Expression} from given l.h.s. and r.h.s.
* @param lhs l.h.s. of the expression
* @param rhs r.h.s. of the expression
* @return expression
* @see Tensors#expression(cc.redberry.core.tensor.Tensor, cc.redberry.core.tensor.Tensor)
* @throws IllegalArgumentException if l.h.s. free indices are not matches r.h.s. free indices
*/
static Expression eq(Tensor lhs, Tensor rhs) {
return expression(lhs, rhs)
}
/**
* Creates the mapping of indices from a given string representation.
*
* @param string string representation of a mapping
* @return mapping of indices
*/
static Mapping getMapping(String string) {
string = string.trim().substring(1, string.length() - 1).trim()
IntArrayList from = new IntArrayList(), to = new IntArrayList()
int fromIndex
string.split(',').each {
def split = it.split('->')
if (split.length == 2) {
fromIndex = IndicesUtils.parseIndex(split[0].trim())
from.add(IndicesUtils.getNameWithType(fromIndex))
to.add(IndicesUtils.getRawStateInt(fromIndex) ^ IndicesUtils.parseIndex(split[1].trim()))
}
}
return new Mapping(from.toArray(), to.toArray())
}
/*
* Combinatorics
*/
static void permutations(List list, Closure> closure) {
IntPermutationsGenerator generator = new IntPermutationsGenerator(list.size());
for (int[] permutation : generator) {
def temp = []
for (int i : permutation)
temp << list[i]
closure.call(temp)
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy