`Product`

represents a product of terms. Like any other expression, it inherits all properties of Tensor. `Product`

adopts the following convention on its indices: the indices of product are sorted concatenated indices of its multipliers:

def t = 'f_ba*t^c_c*h^a'.t println t.indice

> ^{ac}_{abc}

`Product`

sorts its arguments and collapses equal scalar terms into powers.

`Product`

is one of the most sophisticated entities in Redberry: contractions of indices brings additional structure of mathematical *graph* which is reflected in `Product`

by introducing several methods to access graph structure of product.

The data structure used to represent product contains three main blocks: numerical factor, subproduct of scalar factors (with `indices.size() == 0`

), and tensorial content (with `indices.size() != 0`

). Each block can be obtained via special additional methods introduced in product.

There are several features in addition to those defined in Tensor that are inherent only in Product:

`.select(positions)` |
returns a product of elements at specified positions |

`.remove(positions)` |
returns a product with removed elements at specified positions |

`.factor` |
returns a numerical factor of product |

`.indexlessSubProduct` |
returns a subproduct of indexless terms, i.e. product of those terms which `indices.size() == 0` |

`.dataSubProduct` |
returns a subproduct of indexed terms, i.e. product of those terms which `indices.size() != 0` |

`.content` |
returns a data structure that allows to access graph structure of product |

Consider examples:

def p = '2*a*b*f_ba*t^c_c*h^a'.t println p.select(2, 3, 5)

> a*t^{c}_{c}*h^{a}

println p.remove(2, 3, 5)

> 2*b*f_{ba}

println p.factor

> 2

println p.indexlessSubProduct

> 2*b*a

println p.dataSubProduct

> t^{c}_{c}*f_{ba}*h^{a}

The presence of indices bring a *graph structure* of Product: each multiplier represents a graph vertex, while contractions between indices are edges. One can check whether two graph isomorphic, i.e. that two tensors are equal to within free and dummy indices relabelling using Mappings of indices.

There is a special property `.content`

, which allows to access graph structure of `Product`

; the object returned by `.content`

called `ProductContent`

. It holds tensorial part of product and additional low-level data structures used in Redberry to represent tensorial graphs. Besides, `ProductContent`

provides several useful methods like `.scalars`

and `.nonScalar`

which return array of scalar sub-products and non-scalar part of tensor respectively. Consider examples:

def p = '2*a*f_a*t^ba*g_b*t^i_i*t^mn*f_nmk'.t println p.size()

> 8

def content = p.content println content.size()

> 6

println content[0..content.size()]

> [f_a, t^ba, g_b, t^i_i, t^mn, f_nmk]

println content.scalars

> [t^{i}_{i}, t^{ba}*g_{b}*f_{a}]

println content.nonScalar

> t^{mn}*f_{nmk}

In order to access low-level structure that encodes `Product`

graph there is `.structureOfContractions`

property in `ProductContent`

. This structure allows to check connected components of graph and check for each particular tensor with which tensors it is contracted. Without going into low-level details, let's illustrate this features by the examples:

def p = '3*c*f_i*g_b*t^i_i*t^pq*f_qpk*t^bie'.t def content = p.content //get graph representation def graph = content.structureOfContractions //array of connected components println graph.components

> [0, 1, 0, 1, 2, 0]The array of

`components[i] == components[j]`

, and `components[i]`

is the number of corresponding component.
//get position of tensor t^bie def i = content.findIndexOf { it.equals('t^bie'.t) } //contractions of tensor t^bie def contractions = graph.getContractedWith(i) for (def c in contractions) { if (c.tensor == -1)//free index println "Free indices:" + content[i].indices[c.indicesFrom] else { println "With tensor: " + content[c.tensor] println "This indices:" + content[i].indices[c.indicesFrom] println "With indices:" + content[c.tensor].indices[c.indicesTo] } }

> Free indices:^{e} > With tensor: g_{b} > This indices:^{b} > With indices:_{b} > With tensor: f_{i} > This indices:^{i} > With indices:_{i}

- JavaDocs: Product
- Source code: Product.java