<s> """<STR_LIT>""" <EOL> from __future__ import print_function , division <EOL> from collections import defaultdict <EOL> from sympy import Matrix , Rational <EOL> from sympy . combinatorics . tensor_can import get_symmetric_group_sgs , bsgs_direct_product , canonicalize , riemann_bsgs <EOL> from sympy . core import Basic , sympify , Add , S <EOL> from sympy . core . compatibility import string_types , reduce , range <EOL> from sympy . core . containers import Tuple <EOL> from sympy . core . decorators import deprecated <EOL> from sympy . core . symbol import Symbol , symbols <EOL> from sympy . core . sympify import CantSympify <EOL> from sympy . external import import_module <EOL> from sympy . utilities . decorator import doctest_depends_on <EOL> from sympy . matrices import eye <EOL> class TIDS ( CantSympify ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self , components , free , dum ) : <EOL> self . components = components <EOL> self . free = free <EOL> self . dum = dum <EOL> self . _ext_rank = len ( self . free ) + <NUM_LIT:2> * len ( self . dum ) <EOL> self . dum . sort ( key = lambda x : ( x [ <NUM_LIT:2> ] , x [ <NUM_LIT:0> ] ) ) <EOL> def get_tensors ( self ) : <EOL> """<STR_LIT>""" <EOL> indices = self . get_indices ( ) <EOL> components = self . components <EOL> tensors = [ None for i in components ] <EOL> ind_pos = <NUM_LIT:0> <EOL> for i , component in enumerate ( components ) : <EOL> prev_pos = ind_pos <EOL> ind_pos += component . rank <EOL> tensors [ i ] = Tensor ( component , indices [ prev_pos : ind_pos ] ) <EOL> return tensors <EOL> def get_components_with_free_indices ( self ) : <EOL> """<STR_LIT>""" <EOL> components = self . components <EOL> ret_comp = [ ] <EOL> free_counter = <NUM_LIT:0> <EOL> if len ( self . free ) == <NUM_LIT:0> : <EOL> return [ ( comp , [ ] ) for comp in components ] <EOL> for i , comp in enumerate ( components ) : <EOL> c_free = [ ] <EOL> while free_counter < len ( self . free ) : <EOL> if not self . free [ free_counter ] [ <NUM_LIT:2> ] == i : <EOL> break <EOL> c_free . append ( self . free [ free_counter ] ) <EOL> free_counter += <NUM_LIT:1> <EOL> if free_counter >= len ( self . free ) : <EOL> break <EOL> ret_comp . append ( ( comp , c_free ) ) <EOL> return ret_comp <EOL> @ staticmethod <EOL> def from_components_and_indices ( components , indices ) : <EOL> """<STR_LIT>""" <EOL> tids = None <EOL> cur_pos = <NUM_LIT:0> <EOL> for i in components : <EOL> tids_sing = TIDS ( [ i ] , * TIDS . free_dum_from_indices ( * indices [ cur_pos : cur_pos + i . rank ] ) ) <EOL> if tids is None : <EOL> tids = tids_sing <EOL> else : <EOL> tids *= tids_sing <EOL> cur_pos += i . rank <EOL> if tids is None : <EOL> tids = TIDS ( [ ] , [ ] , [ ] ) <EOL> tids . free . sort ( key = lambda x : x [ <NUM_LIT:0> ] . name ) <EOL> tids . dum . sort ( ) <EOL> return tids <EOL> @ deprecated ( useinstead = "<STR_LIT>" ) <EOL> def to_indices ( self ) : <EOL> return self . get_indices ( ) <EOL> @ staticmethod <EOL> def free_dum_from_indices ( * indices ) : <EOL> """<STR_LIT>""" <EOL> n = len ( indices ) <EOL> if n == <NUM_LIT:1> : <EOL> return [ ( indices [ <NUM_LIT:0> ] , <NUM_LIT:0> , <NUM_LIT:0> ) ] , [ ] <EOL> free = [ True ] * len ( indices ) <EOL> index_dict = { } <EOL> dum = [ ] <EOL> for i , index in enumerate ( indices ) : <EOL> name = index . _name <EOL> typ = index . _tensortype <EOL> contr = index . _is_up <EOL> if ( name , typ ) in index_dict : <EOL> is_contr , pos = index_dict [ ( name , typ ) ] <EOL> if is_contr : <EOL> if contr : <EOL> raise ValueError ( '<STR_LIT>' % ( pos , i ) ) <EOL> else : <EOL> free [ pos ] = False <EOL> free [ i ] = False <EOL> else : <EOL> if contr : <EOL> free [ pos ] = False <EOL> free [ i ] = False <EOL> else : <EOL> raise ValueError ( '<STR_LIT>' % ( pos , i ) ) <EOL> if contr : <EOL> dum . append ( ( i , pos , <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> else : <EOL> dum . append ( ( pos , i , <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> else : <EOL> index_dict [ ( name , typ ) ] = index . _is_up , i <EOL> free = [ ( index , i , <NUM_LIT:0> ) for i , index in enumerate ( indices ) if free [ i ] ] <EOL> free . sort ( ) <EOL> return free , dum <EOL> @ staticmethod <EOL> def _check_matrix_indices ( f_free , g_free , nc1 ) : <EOL> dum = [ ] <EOL> f_free . sort ( key = lambda x : ( x [ <NUM_LIT:2> ] , x [ <NUM_LIT:1> ] ) ) <EOL> g_free . sort ( key = lambda x : ( x [ <NUM_LIT:2> ] , x [ <NUM_LIT:1> ] ) ) <EOL> matrix_indices_storage = { } <EOL> transform_right_to_left = { } <EOL> f_pop_pos = [ ] <EOL> g_pop_pos = [ ] <EOL> for free_pos , ( ind , i , c ) in enumerate ( f_free ) : <EOL> index_type = ind . _tensortype <EOL> if ind not in ( index_type . auto_left , - index_type . auto_right ) : <EOL> continue <EOL> matrix_indices_storage [ ind ] = ( free_pos , i , c ) <EOL> for free_pos , ( ind , i , c ) in enumerate ( g_free ) : <EOL> index_type = ind . _tensortype <EOL> if ind not in ( index_type . auto_left , - index_type . auto_right ) : <EOL> continue <EOL> if ind == index_type . auto_left : <EOL> if - index_type . auto_right in matrix_indices_storage : <EOL> other_pos , other_i , other_c = matrix_indices_storage . pop ( - index_type . auto_right ) <EOL> dum . append ( ( other_i , i , other_c , c + nc1 ) ) <EOL> g_pop_pos . append ( free_pos ) <EOL> f_pop_pos . append ( other_pos ) <EOL> continue <EOL> if ind in matrix_indices_storage : <EOL> other_pos , other_i , other_c = matrix_indices_storage . pop ( ind ) <EOL> dum . append ( ( other_i , i , other_c , c + nc1 ) ) <EOL> g_pop_pos . append ( free_pos ) <EOL> f_pop_pos . append ( other_pos ) <EOL> transform_right_to_left [ - index_type . auto_right ] = c <EOL> continue <EOL> if ind in transform_right_to_left : <EOL> other_c = transform_right_to_left . pop ( ind ) <EOL> if c == other_c : <EOL> g_free [ free_pos ] = ( index_type . auto_left , i , c ) <EOL> for i in reversed ( sorted ( f_pop_pos ) ) : <EOL> f_free . pop ( i ) <EOL> for i in reversed ( sorted ( g_pop_pos ) ) : <EOL> g_free . pop ( i ) <EOL> return dum <EOL> @ staticmethod <EOL> def mul ( f , g ) : <EOL> """<STR_LIT>""" <EOL> index_up = lambda u : u if u . is_up else - u <EOL> notmat = lambda i : i not in ( i . _tensortype . auto_left , - i . _tensortype . auto_right ) <EOL> f_free = f . free [ : ] <EOL> g_free = g . free [ : ] <EOL> nc1 = len ( f . components ) <EOL> dum = TIDS . _check_matrix_indices ( f_free , g_free , nc1 ) <EOL> free_dict1 = { i if i . is_up else - i : ( pos , cpos , i ) for i , pos , cpos in f_free } <EOL> free_dict2 = { i if i . is_up else - i : ( pos , cpos , i ) for i , pos , cpos in g_free } <EOL> free_names = set ( free_dict1 . keys ( ) ) & set ( free_dict2 . keys ( ) ) <EOL> dum2 = [ ( i1 , i2 , c1 + nc1 , c2 + nc1 ) for i1 , i2 , c1 , c2 in g . dum ] <EOL> free1 = [ ( ind , i , c ) for ind , i , c in f_free if index_up ( ind ) not in free_names ] <EOL> free2 = [ ( ind , i , c + nc1 ) for ind , i , c in g_free if index_up ( ind ) not in free_names ] <EOL> free = free1 + free2 <EOL> dum . extend ( f . dum + dum2 ) <EOL> for name in free_names : <EOL> ipos1 , cpos1 , ind1 = free_dict1 [ name ] <EOL> ipos2 , cpos2 , ind2 = free_dict2 [ name ] <EOL> cpos2 += nc1 <EOL> if ind1 . _is_up == ind2 . _is_up : <EOL> raise ValueError ( '<STR_LIT>' . format ( ind1 ) ) <EOL> if ind1 . _is_up : <EOL> new_dummy = ( ipos1 , ipos2 , cpos1 , cpos2 ) <EOL> else : <EOL> new_dummy = ( ipos2 , ipos1 , cpos2 , cpos1 ) <EOL> dum . append ( new_dummy ) <EOL> return ( f . components + g . components , free , dum ) <EOL> def __mul__ ( self , other ) : <EOL> return TIDS ( * self . mul ( self , other ) ) <EOL> def __str__ ( self ) : <EOL> return "<STR_LIT>" . format ( self . components , self . free , self . dum ) <EOL> def __repr__ ( self ) : <EOL> return self . __str__ ( ) <EOL> def sorted_components ( self ) : <EOL> """<STR_LIT>""" <EOL> from sympy . combinatorics . permutations import _af_invert <EOL> cv = list ( zip ( self . components , range ( len ( self . components ) ) ) ) <EOL> sign = <NUM_LIT:1> <EOL> n = len ( cv ) - <NUM_LIT:1> <EOL> for i in range ( n ) : <EOL> for j in range ( n , i , - <NUM_LIT:1> ) : <EOL> c = cv [ j - <NUM_LIT:1> ] [ <NUM_LIT:0> ] . commutes_with ( cv [ j ] [ <NUM_LIT:0> ] ) <EOL> if c not in [ <NUM_LIT:0> , <NUM_LIT:1> ] : <EOL> continue <EOL> if ( cv [ j - <NUM_LIT:1> ] [ <NUM_LIT:0> ] . _types , cv [ j - <NUM_LIT:1> ] [ <NUM_LIT:0> ] . _name ) > ( cv [ j ] [ <NUM_LIT:0> ] . _types , cv [ j ] [ <NUM_LIT:0> ] . _name ) : <EOL> cv [ j - <NUM_LIT:1> ] , cv [ j ] = cv [ j ] , cv [ j - <NUM_LIT:1> ] <EOL> if c : <EOL> sign = - sign <EOL> components = [ x [ <NUM_LIT:0> ] for x in cv ] <EOL> perm_inv = [ x [ <NUM_LIT:1> ] for x in cv ] <EOL> perm = _af_invert ( perm_inv ) <EOL> free = [ ( ind , i , perm [ c ] ) for ind , i , c in self . free ] <EOL> free . sort ( ) <EOL> dum = [ ( i1 , i2 , perm [ c1 ] , perm [ c2 ] ) for i1 , i2 , c1 , c2 in self . dum ] <EOL> dum . sort ( key = lambda x : components [ x [ <NUM_LIT:2> ] ] . index_types [ x [ <NUM_LIT:0> ] ] ) <EOL> return TIDS ( components , free , dum ) , sign <EOL> def _get_sorted_free_indices_for_canon ( self ) : <EOL> sorted_free = self . free [ : ] <EOL> sorted_free . sort ( key = lambda x : x [ <NUM_LIT:0> ] ) <EOL> return sorted_free <EOL> def _get_sorted_dum_indices_for_canon ( self ) : <EOL> return sorted ( self . dum , key = lambda x : ( x [ <NUM_LIT:2> ] , x [ <NUM_LIT:0> ] ) ) <EOL> def canon_args ( self ) : <EOL> """<STR_LIT>""" <EOL> from sympy . combinatorics . permutations import _af_new <EOL> n = self . _ext_rank <EOL> g = [ None ] * n + [ n , n + <NUM_LIT:1> ] <EOL> pos = <NUM_LIT:0> <EOL> vpos = [ ] <EOL> components = self . components <EOL> for t in components : <EOL> vpos . append ( pos ) <EOL> pos += t . _rank <EOL> for i , ( indx , ipos , cpos ) in enumerate ( self . _get_sorted_free_indices_for_canon ( ) ) : <EOL> pos = vpos [ cpos ] + ipos <EOL> g [ pos ] = i <EOL> pos = len ( self . free ) <EOL> j = len ( self . free ) <EOL> dummies = [ ] <EOL> prev = None <EOL> a = [ ] <EOL> msym = [ ] <EOL> for ipos1 , ipos2 , cpos1 , cpos2 in self . _get_sorted_dum_indices_for_canon ( ) : <EOL> pos1 = vpos [ cpos1 ] + ipos1 <EOL> pos2 = vpos [ cpos2 ] + ipos2 <EOL> g [ pos1 ] = j <EOL> g [ pos2 ] = j + <NUM_LIT:1> <EOL> j += <NUM_LIT:2> <EOL> typ = components [ cpos1 ] . index_types [ ipos1 ] <EOL> if typ != prev : <EOL> if a : <EOL> dummies . append ( a ) <EOL> a = [ pos , pos + <NUM_LIT:1> ] <EOL> prev = typ <EOL> msym . append ( typ . metric_antisym ) <EOL> else : <EOL> a . extend ( [ pos , pos + <NUM_LIT:1> ] ) <EOL> pos += <NUM_LIT:2> <EOL> if a : <EOL> dummies . append ( a ) <EOL> numtyp = [ ] <EOL> prev = None <EOL> for t in components : <EOL> if t == prev : <EOL> numtyp [ - <NUM_LIT:1> ] [ <NUM_LIT:1> ] += <NUM_LIT:1> <EOL> else : <EOL> prev = t <EOL> numtyp . append ( [ prev , <NUM_LIT:1> ] ) <EOL> v = [ ] <EOL> for h , n in numtyp : <EOL> if h . _comm == <NUM_LIT:0> or h . _comm == <NUM_LIT:1> : <EOL> comm = h . _comm <EOL> else : <EOL> comm = TensorManager . get_comm ( h . _comm , h . _comm ) <EOL> v . append ( ( h . _symmetry . base , h . _symmetry . generators , n , comm ) ) <EOL> return _af_new ( g ) , dummies , msym , v <EOL> def perm2tensor ( self , g , canon_bp = False ) : <EOL> """<STR_LIT>""" <EOL> vpos = [ ] <EOL> components = self . components <EOL> pos = <NUM_LIT:0> <EOL> for t in components : <EOL> vpos . append ( pos ) <EOL> pos += t . _rank <EOL> sorted_free = [ i [ <NUM_LIT:0> ] for i in self . _get_sorted_free_indices_for_canon ( ) ] <EOL> nfree = len ( sorted_free ) <EOL> rank = self . _ext_rank <EOL> dum = [ [ None ] * <NUM_LIT:4> for i in range ( ( rank - nfree ) // <NUM_LIT:2> ) ] <EOL> free = [ ] <EOL> icomp = - <NUM_LIT:1> <EOL> for i in range ( rank ) : <EOL> if i in vpos : <EOL> icomp += vpos . count ( i ) <EOL> pos0 = i <EOL> ipos = i - pos0 <EOL> gi = g [ i ] <EOL> if gi < nfree : <EOL> ind = sorted_free [ gi ] <EOL> free . append ( ( ind , ipos , icomp ) ) <EOL> else : <EOL> j = gi - nfree <EOL> idum , cov = divmod ( j , <NUM_LIT:2> ) <EOL> if cov : <EOL> dum [ idum ] [ <NUM_LIT:1> ] = ipos <EOL> dum [ idum ] [ <NUM_LIT:3> ] = icomp <EOL> else : <EOL> dum [ idum ] [ <NUM_LIT:0> ] = ipos <EOL> dum [ idum ] [ <NUM_LIT:2> ] = icomp <EOL> dum = [ tuple ( x ) for x in dum ] <EOL> return TIDS ( components , free , dum ) <EOL> def get_indices ( self ) : <EOL> """<STR_LIT>""" <EOL> components = self . components <EOL> free = self . free <EOL> dum = self . dum <EOL> indices = [ None ] * self . _ext_rank <EOL> start = <NUM_LIT:0> <EOL> pos = <NUM_LIT:0> <EOL> vpos = [ ] <EOL> for t in components : <EOL> vpos . append ( pos ) <EOL> pos += t . rank <EOL> cdt = defaultdict ( int ) <EOL> for indx , ipos , cpos in free : <EOL> if indx . _name . split ( '<STR_LIT:_>' ) [ <NUM_LIT:0> ] == indx . _tensortype . _dummy_fmt [ : - <NUM_LIT:3> ] : <EOL> cdt [ indx . _tensortype ] = max ( cdt [ indx . _tensortype ] , int ( indx . _name . split ( '<STR_LIT:_>' ) [ <NUM_LIT:1> ] ) + <NUM_LIT:1> ) <EOL> start = vpos [ cpos ] <EOL> indices [ start + ipos ] = indx <EOL> for ipos1 , ipos2 , cpos1 , cpos2 in dum : <EOL> start1 = vpos [ cpos1 ] <EOL> start2 = vpos [ cpos2 ] <EOL> typ1 = components [ cpos1 ] . index_types [ ipos1 ] <EOL> assert typ1 == components [ cpos2 ] . index_types [ ipos2 ] <EOL> fmt = typ1 . _dummy_fmt <EOL> nd = cdt [ typ1 ] <EOL> indices [ start1 + ipos1 ] = TensorIndex ( fmt % nd , typ1 ) <EOL> indices [ start2 + ipos2 ] = TensorIndex ( fmt % nd , typ1 , False ) <EOL> cdt [ typ1 ] += <NUM_LIT:1> <EOL> return indices <EOL> def contract_metric ( self , g ) : <EOL> """<STR_LIT>""" <EOL> components = self . components <EOL> antisym = g . index_types [ <NUM_LIT:0> ] . metric_antisym <EOL> gpos = [ i for i , x in enumerate ( components ) if x == g ] <EOL> if not gpos : <EOL> return self , <NUM_LIT:1> <EOL> sign = <NUM_LIT:1> <EOL> dum = self . dum [ : ] <EOL> free = self . free [ : ] <EOL> elim = set ( ) <EOL> for gposx in gpos : <EOL> if gposx in elim : <EOL> continue <EOL> free1 = [ x for x in free if x [ - <NUM_LIT:1> ] == gposx ] <EOL> dum1 = [ x for x in dum if x [ - <NUM_LIT:2> ] == gposx or x [ - <NUM_LIT:1> ] == gposx ] <EOL> if not dum1 : <EOL> continue <EOL> elim . add ( gposx ) <EOL> if len ( dum1 ) == <NUM_LIT:2> : <EOL> if not antisym : <EOL> dum10 , dum11 = dum1 <EOL> if dum10 [ <NUM_LIT:3> ] == gposx : <EOL> c0 = dum10 [ <NUM_LIT:2> ] <EOL> p0 = dum10 [ <NUM_LIT:0> ] <EOL> else : <EOL> c0 = dum10 [ <NUM_LIT:3> ] <EOL> p0 = dum10 [ <NUM_LIT:1> ] <EOL> if dum11 [ <NUM_LIT:3> ] == gposx : <EOL> c1 = dum11 [ <NUM_LIT:2> ] <EOL> p1 = dum11 [ <NUM_LIT:0> ] <EOL> else : <EOL> c1 = dum11 [ <NUM_LIT:3> ] <EOL> p1 = dum11 [ <NUM_LIT:1> ] <EOL> dum . append ( ( p0 , p1 , c0 , c1 ) ) <EOL> else : <EOL> dum10 , dum11 = dum1 <EOL> if dum10 [ <NUM_LIT:3> ] == gposx : <EOL> c0 = dum10 [ <NUM_LIT:2> ] <EOL> p0 = dum10 [ <NUM_LIT:0> ] <EOL> if dum10 [ <NUM_LIT:1> ] == <NUM_LIT:1> : <EOL> sign = - sign <EOL> else : <EOL> c0 = dum10 [ <NUM_LIT:3> ] <EOL> p0 = dum10 [ <NUM_LIT:1> ] <EOL> if dum10 [ <NUM_LIT:0> ] == <NUM_LIT:0> : <EOL> sign = - sign <EOL> if dum11 [ <NUM_LIT:3> ] == gposx : <EOL> c1 = dum11 [ <NUM_LIT:2> ] <EOL> p1 = dum11 [ <NUM_LIT:0> ] <EOL> sign = - sign <EOL> else : <EOL> c1 = dum11 [ <NUM_LIT:3> ] <EOL> p1 = dum11 [ <NUM_LIT:1> ] <EOL> dum . append ( ( p0 , p1 , c0 , c1 ) ) <EOL> elif len ( dum1 ) == <NUM_LIT:1> : <EOL> if not antisym : <EOL> dp0 , dp1 , dc0 , dc1 = dum1 [ <NUM_LIT:0> ] <EOL> if dc0 == dc1 : <EOL> typ = g . index_types [ <NUM_LIT:0> ] <EOL> if typ . _dim is None : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> sign = sign * typ . _dim <EOL> else : <EOL> if dc0 == gposx : <EOL> p1 = dp1 <EOL> c1 = dc1 <EOL> else : <EOL> p1 = dp0 <EOL> c1 = dc0 <EOL> ind , p , c = free1 [ <NUM_LIT:0> ] <EOL> free . append ( ( ind , p1 , c1 ) ) <EOL> else : <EOL> dp0 , dp1 , dc0 , dc1 = dum1 [ <NUM_LIT:0> ] <EOL> if dc0 == dc1 : <EOL> typ = g . index_types [ <NUM_LIT:0> ] <EOL> if typ . _dim is None : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> sign = sign * typ . _dim <EOL> if dp0 < dp1 : <EOL> sign = - sign <EOL> else : <EOL> if dc0 == gposx : <EOL> p1 = dp1 <EOL> c1 = dc1 <EOL> if dp0 == <NUM_LIT:0> : <EOL> sign = - sign <EOL> else : <EOL> p1 = dp0 <EOL> c1 = dc0 <EOL> ind , p , c = free1 [ <NUM_LIT:0> ] <EOL> free . append ( ( ind , p1 , c1 ) ) <EOL> dum = [ x for x in dum if x not in dum1 ] <EOL> free = [ x for x in free if x not in free1 ] <EOL> shift = <NUM_LIT:0> <EOL> shifts = [ <NUM_LIT:0> ] * len ( components ) <EOL> for i in range ( len ( components ) ) : <EOL> if i in elim : <EOL> shift += <NUM_LIT:1> <EOL> continue <EOL> shifts [ i ] = shift <EOL> free = [ ( ind , p , c - shifts [ c ] ) for ( ind , p , c ) in free if c not in elim ] <EOL> dum = [ ( p0 , p1 , c0 - shifts [ c0 ] , c1 - shifts [ c1 ] ) for i , ( p0 , p1 , c0 , c1 ) in enumerate ( dum ) if c0 not in elim and c1 not in elim ] <EOL> components = [ c for i , c in enumerate ( components ) if i not in elim ] <EOL> tids = TIDS ( components , free , dum ) <EOL> return tids , sign <EOL> class _TensorDataLazyEvaluator ( CantSympify ) : <EOL> """<STR_LIT>""" <EOL> _substitutions_dict = dict ( ) <EOL> _substitutions_dict_tensmul = dict ( ) <EOL> def __getitem__ ( self , key ) : <EOL> dat = self . _get ( key ) <EOL> if dat is None : <EOL> return None <EOL> numpy = import_module ( "<STR_LIT>" ) <EOL> if not isinstance ( dat , numpy . ndarray ) : <EOL> return dat <EOL> if dat . ndim == <NUM_LIT:0> : <EOL> return dat [ ( ) ] <EOL> elif dat . ndim == <NUM_LIT:1> and dat . size == <NUM_LIT:1> : <EOL> return dat [ <NUM_LIT:0> ] <EOL> return dat <EOL> def _get ( self , key ) : <EOL> """<STR_LIT>""" <EOL> if key in self . _substitutions_dict : <EOL> return self . _substitutions_dict [ key ] <EOL> if isinstance ( key , TensorHead ) : <EOL> return None <EOL> if isinstance ( key , Tensor ) : <EOL> signature = tuple ( [ i . is_up for i in key . get_indices ( ) ] ) <EOL> srch = ( key . component , ) + signature <EOL> if srch in self . _substitutions_dict_tensmul : <EOL> return self . _substitutions_dict_tensmul [ srch ] <EOL> return self . data_tensmul_from_tensorhead ( key , key . component ) <EOL> if isinstance ( key , TensMul ) : <EOL> tensmul_list = key . split ( ) <EOL> if len ( tensmul_list ) == <NUM_LIT:1> and len ( tensmul_list [ <NUM_LIT:0> ] . components ) == <NUM_LIT:1> : <EOL> signature = tuple ( [ i . is_up for i in tensmul_list [ <NUM_LIT:0> ] . get_indices ( ) ] ) <EOL> srch = ( tensmul_list [ <NUM_LIT:0> ] . components [ <NUM_LIT:0> ] , ) + signature <EOL> if srch in self . _substitutions_dict_tensmul : <EOL> return self . _substitutions_dict_tensmul [ srch ] <EOL> data_list = [ self . data_tensmul_from_tensorhead ( i , i . components [ <NUM_LIT:0> ] ) for i in tensmul_list ] <EOL> if all ( [ i is None for i in data_list ] ) : <EOL> return None <EOL> if any ( [ i is None for i in data_list ] ) : <EOL> raise ValueError ( "<STR_LIT>" "<STR_LIT>" ) <EOL> data_result , tensmul_result = self . data_product_tensors ( data_list , tensmul_list ) <EOL> return data_result <EOL> if isinstance ( key , TensAdd ) : <EOL> sumvar = S . Zero <EOL> data_list = [ i . data for i in key . args ] <EOL> if all ( [ i is None for i in data_list ] ) : <EOL> return None <EOL> if any ( [ i is None for i in data_list ] ) : <EOL> raise ValueError ( "<STR_LIT>" "<STR_LIT>" ) <EOL> for i in data_list : <EOL> sumvar += i <EOL> return sumvar <EOL> return None <EOL> def data_tensorhead_from_tensmul ( self , data , tensmul , tensorhead ) : <EOL> """<STR_LIT>""" <EOL> if data is None : <EOL> return None <EOL> return self . _correct_signature_from_indices ( <EOL> data , <EOL> tensmul . get_indices ( ) , <EOL> tensmul . free , <EOL> tensmul . dum , <EOL> True ) <EOL> def data_tensmul_from_tensorhead ( self , tensmul , tensorhead ) : <EOL> """<STR_LIT>""" <EOL> if tensorhead . data is None : <EOL> return None <EOL> return self . _correct_signature_from_indices ( <EOL> tensorhead . data , <EOL> tensmul . get_indices ( ) , <EOL> tensmul . free , <EOL> tensmul . dum ) <EOL> def data_product_tensors ( self , data_list , tensmul_list ) : <EOL> """<STR_LIT>""" <EOL> def data_mul ( f , g ) : <EOL> """<STR_LIT>""" <EOL> data1 , tensmul1 = f <EOL> data2 , tensmul2 = g <EOL> components , free , dum = TIDS . mul ( tensmul1 , tensmul2 ) <EOL> data = _TensorDataLazyEvaluator . _contract_ndarray ( tensmul1 . free , tensmul2 . free , data1 , data2 ) <EOL> return data , TensMul . from_TIDS ( S . One , TIDS ( components , free , dum ) ) <EOL> return reduce ( data_mul , zip ( data_list , tensmul_list ) ) <EOL> def _assign_data_to_tensor_expr ( self , key , data ) : <EOL> if isinstance ( key , TensAdd ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if len ( key . components ) != <NUM_LIT:1> : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> tensorhead = key . components [ <NUM_LIT:0> ] <EOL> newdata = self . data_tensorhead_from_tensmul ( data , key , tensorhead ) <EOL> return tensorhead , newdata <EOL> def _check_permutations_on_data ( self , tens , data ) : <EOL> import numpy <EOL> if isinstance ( tens , TensorHead ) : <EOL> rank = tens . rank <EOL> generators = tens . symmetry . generators <EOL> elif isinstance ( tens , Tensor ) : <EOL> rank = tens . rank <EOL> generators = tens . components [ <NUM_LIT:0> ] . symmetry . generators <EOL> elif isinstance ( tens , TensorIndexType ) : <EOL> rank = tens . metric . rank <EOL> generators = tens . metric . symmetry . generators <EOL> for gener in generators : <EOL> sign_change = + <NUM_LIT:1> if ( gener ( rank ) == rank ) else - <NUM_LIT:1> <EOL> data_swapped = data <EOL> last_data = data <EOL> permute_axes = list ( map ( gener , list ( range ( rank ) ) ) ) <EOL> for i in range ( gener . order ( ) - <NUM_LIT:1> ) : <EOL> data_swapped = numpy . transpose ( data_swapped , permute_axes ) <EOL> if ( last_data - sign_change * data_swapped ) . any ( ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> last_data = data_swapped <EOL> def __setitem__ ( self , key , value ) : <EOL> """<STR_LIT>""" <EOL> data = _TensorDataLazyEvaluator . parse_data ( value ) <EOL> self . _check_permutations_on_data ( key , data ) <EOL> if not isinstance ( key , ( TensorHead , TensorIndexType ) ) : <EOL> key , data = self . _assign_data_to_tensor_expr ( key , data ) <EOL> if isinstance ( key , TensorHead ) : <EOL> for dim , indextype in zip ( data . shape , key . index_types ) : <EOL> if indextype . data is None : <EOL> raise ValueError ( "<STR_LIT>" "<STR_LIT>" . format ( indextype ) ) <EOL> if indextype . dim is None : <EOL> continue <EOL> if dim != indextype . dim : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> self . _substitutions_dict [ key ] = data <EOL> def __delitem__ ( self , key ) : <EOL> del self . _substitutions_dict [ key ] <EOL> def __contains__ ( self , key ) : <EOL> return key in self . _substitutions_dict <EOL> @ staticmethod <EOL> def _contract_ndarray ( free1 , free2 , ndarray1 , ndarray2 ) : <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> def ikey ( x ) : <EOL> return x [ <NUM_LIT:2> ] , x [ <NUM_LIT:1> ] <EOL> free1 = free1 [ : ] <EOL> free2 = free2 [ : ] <EOL> free1 . sort ( key = ikey ) <EOL> free2 . sort ( key = ikey ) <EOL> self_free = [ _ [ <NUM_LIT:0> ] for _ in free1 ] <EOL> axes1 = [ ] <EOL> axes2 = [ ] <EOL> for jpos , jindex in enumerate ( free2 ) : <EOL> if - jindex [ <NUM_LIT:0> ] in self_free : <EOL> nidx = self_free . index ( - jindex [ <NUM_LIT:0> ] ) <EOL> else : <EOL> continue <EOL> axes1 . append ( nidx ) <EOL> axes2 . append ( jpos ) <EOL> contracted_ndarray = numpy . tensordot ( <EOL> ndarray1 , <EOL> ndarray2 , <EOL> ( axes1 , axes2 ) <EOL> ) <EOL> return contracted_ndarray <EOL> @ staticmethod <EOL> def add_tensor_mul ( prod , f , g ) : <EOL> def mul_function ( ) : <EOL> return _TensorDataLazyEvaluator . _contract_ndarray ( f . free , g . free , f . data , g . data ) <EOL> _TensorDataLazyEvaluator . _substitutions_dict [ prod ] = mul_function ( ) <EOL> @ staticmethod <EOL> def add_tensor_add ( addition , f , g ) : <EOL> def add_function ( ) : <EOL> return f . data + g . data <EOL> _TensorDataLazyEvaluator . _substitutions_dict [ addition ] = add_function ( ) <EOL> def add_metric_data ( self , metric , data ) : <EOL> """<STR_LIT>""" <EOL> self . _substitutions_dict_tensmul [ metric , True , True ] = data <EOL> inverse_transpose = self . inverse_transpose_matrix ( data ) <EOL> self . _substitutions_dict_tensmul [ metric , False , False ] = inverse_transpose <EOL> m = Matrix ( data ) <EOL> invt = Matrix ( inverse_transpose ) <EOL> self . _substitutions_dict_tensmul [ metric , True , False ] = m * invt <EOL> self . _substitutions_dict_tensmul [ metric , False , True ] = invt * m <EOL> @ staticmethod <EOL> def _flip_index_by_metric ( data , metric , pos ) : <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> data = numpy . tensordot ( <EOL> metric , <EOL> data , <EOL> ( <NUM_LIT:1> , pos ) ) <EOL> return numpy . rollaxis ( data , <NUM_LIT:0> , pos + <NUM_LIT:1> ) <EOL> @ staticmethod <EOL> def inverse_matrix ( ndarray ) : <EOL> m = Matrix ( ndarray ) . inv ( ) <EOL> return _TensorDataLazyEvaluator . parse_data ( m ) <EOL> @ staticmethod <EOL> def inverse_transpose_matrix ( ndarray ) : <EOL> m = Matrix ( ndarray ) . inv ( ) . T <EOL> return _TensorDataLazyEvaluator . parse_data ( m ) <EOL> @ staticmethod <EOL> def _correct_signature_from_indices ( data , indices , free , dum , inverse = False ) : <EOL> """<STR_LIT>""" <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> for i , indx in enumerate ( indices ) : <EOL> if not indx . is_up and not inverse : <EOL> data = _TensorDataLazyEvaluator . _flip_index_by_metric ( data , indx . _tensortype . data , i ) <EOL> elif not indx . is_up and inverse : <EOL> data = _TensorDataLazyEvaluator . _flip_index_by_metric ( <EOL> data , <EOL> _TensorDataLazyEvaluator . inverse_matrix ( indx . _tensortype . data ) , <EOL> i <EOL> ) <EOL> if len ( dum ) > <NUM_LIT:0> : <EOL> axes1 = [ ] <EOL> axes2 = [ ] <EOL> for i , indx1 in enumerate ( indices ) : <EOL> try : <EOL> nd = indices [ : i ] . index ( - indx1 ) <EOL> except ValueError : <EOL> continue <EOL> axes1 . append ( nd ) <EOL> axes2 . append ( i ) <EOL> for ax1 , ax2 in zip ( axes1 , axes2 ) : <EOL> data = numpy . trace ( data , axis1 = ax1 , axis2 = ax2 ) <EOL> return data <EOL> @ staticmethod <EOL> def _sort_data_axes ( old , new ) : <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> new_data = old . data . copy ( ) <EOL> old_free = [ i [ <NUM_LIT:0> ] for i in old . free ] <EOL> new_free = [ i [ <NUM_LIT:0> ] for i in new . free ] <EOL> for i in range ( len ( new_free ) ) : <EOL> for j in range ( i , len ( old_free ) ) : <EOL> if old_free [ j ] == new_free [ i ] : <EOL> old_free [ i ] , old_free [ j ] = old_free [ j ] , old_free [ i ] <EOL> new_data = numpy . swapaxes ( new_data , i , j ) <EOL> break <EOL> return new_data <EOL> @ staticmethod <EOL> def add_rearrange_tensmul_parts ( new_tensmul , old_tensmul ) : <EOL> def sorted_compo ( ) : <EOL> return _TensorDataLazyEvaluator . _sort_data_axes ( old_tensmul , new_tensmul ) <EOL> _TensorDataLazyEvaluator . _substitutions_dict [ new_tensmul ] = sorted_compo ( ) <EOL> @ staticmethod <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> def parse_data ( data ) : <EOL> """<STR_LIT>""" <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> if ( numpy is not None ) and ( not isinstance ( data , numpy . ndarray ) ) : <EOL> if len ( data ) == <NUM_LIT:2> and hasattr ( data [ <NUM_LIT:0> ] , '<STR_LIT>' ) : <EOL> def fromfunction_sympify ( * x ) : <EOL> return sympify ( data [ <NUM_LIT:0> ] ( * x ) ) <EOL> data = numpy . fromfunction ( fromfunction_sympify , data [ <NUM_LIT:1> ] ) <EOL> else : <EOL> vsympify = numpy . vectorize ( sympify ) <EOL> data = vsympify ( numpy . array ( data ) ) <EOL> return data <EOL> _tensor_data_substitution_dict = _TensorDataLazyEvaluator ( ) <EOL> class _TensorManager ( object ) : <EOL> """<STR_LIT>""" <EOL> def __init__ ( self ) : <EOL> self . _comm_init ( ) <EOL> def _comm_init ( self ) : <EOL> self . _comm = [ { } for i in range ( <NUM_LIT:3> ) ] <EOL> for i in range ( <NUM_LIT:3> ) : <EOL> self . _comm [ <NUM_LIT:0> ] [ i ] = <NUM_LIT:0> <EOL> self . _comm [ i ] [ <NUM_LIT:0> ] = <NUM_LIT:0> <EOL> self . _comm [ <NUM_LIT:1> ] [ <NUM_LIT:1> ] = <NUM_LIT:1> <EOL> self . _comm [ <NUM_LIT:2> ] [ <NUM_LIT:1> ] = None <EOL> self . _comm [ <NUM_LIT:1> ] [ <NUM_LIT:2> ] = None <EOL> self . _comm_symbols2i = { <NUM_LIT:0> : <NUM_LIT:0> , <NUM_LIT:1> : <NUM_LIT:1> , <NUM_LIT:2> : <NUM_LIT:2> } <EOL> self . _comm_i2symbol = { <NUM_LIT:0> : <NUM_LIT:0> , <NUM_LIT:1> : <NUM_LIT:1> , <NUM_LIT:2> : <NUM_LIT:2> } <EOL> @ property <EOL> def comm ( self ) : <EOL> return self . _comm <EOL> def comm_symbols2i ( self , i ) : <EOL> """<STR_LIT>""" <EOL> if i not in self . _comm_symbols2i : <EOL> n = len ( self . _comm ) <EOL> self . _comm . append ( { } ) <EOL> self . _comm [ n ] [ <NUM_LIT:0> ] = <NUM_LIT:0> <EOL> self . _comm [ <NUM_LIT:0> ] [ n ] = <NUM_LIT:0> <EOL> self . _comm_symbols2i [ i ] = n <EOL> self . _comm_i2symbol [ n ] = i <EOL> return n <EOL> return self . _comm_symbols2i [ i ] <EOL> def comm_i2symbol ( self , i ) : <EOL> """<STR_LIT>""" <EOL> return self . _comm_i2symbol [ i ] <EOL> def set_comm ( self , i , j , c ) : <EOL> """<STR_LIT>""" <EOL> if c not in ( <NUM_LIT:0> , <NUM_LIT:1> , None ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if i not in self . _comm_symbols2i : <EOL> n = len ( self . _comm ) <EOL> self . _comm . append ( { } ) <EOL> self . _comm [ n ] [ <NUM_LIT:0> ] = <NUM_LIT:0> <EOL> self . _comm [ <NUM_LIT:0> ] [ n ] = <NUM_LIT:0> <EOL> self . _comm_symbols2i [ i ] = n <EOL> self . _comm_i2symbol [ n ] = i <EOL> if j not in self . _comm_symbols2i : <EOL> n = len ( self . _comm ) <EOL> self . _comm . append ( { } ) <EOL> self . _comm [ <NUM_LIT:0> ] [ n ] = <NUM_LIT:0> <EOL> self . _comm [ n ] [ <NUM_LIT:0> ] = <NUM_LIT:0> <EOL> self . _comm_symbols2i [ j ] = n <EOL> self . _comm_i2symbol [ n ] = j <EOL> ni = self . _comm_symbols2i [ i ] <EOL> nj = self . _comm_symbols2i [ j ] <EOL> self . _comm [ ni ] [ nj ] = c <EOL> self . _comm [ nj ] [ ni ] = c <EOL> def set_comms ( self , * args ) : <EOL> """<STR_LIT>""" <EOL> for i , j , c in args : <EOL> self . set_comm ( i , j , c ) <EOL> def get_comm ( self , i , j ) : <EOL> """<STR_LIT>""" <EOL> return self . _comm [ i ] . get ( j , <NUM_LIT:0> if i == <NUM_LIT:0> or j == <NUM_LIT:0> else None ) <EOL> def clear ( self ) : <EOL> """<STR_LIT>""" <EOL> self . _comm_init ( ) <EOL> TensorManager = _TensorManager ( ) <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensorIndexType ( Basic ) : <EOL> """<STR_LIT>""" <EOL> def __new__ ( cls , name , metric = False , dim = None , eps_dim = None , <EOL> dummy_fmt = None ) : <EOL> if isinstance ( name , string_types ) : <EOL> name = Symbol ( name ) <EOL> obj = Basic . __new__ ( cls , name , S . One if metric else S . Zero ) <EOL> obj . _name = str ( name ) <EOL> if not dummy_fmt : <EOL> obj . _dummy_fmt = '<STR_LIT>' % obj . name <EOL> else : <EOL> obj . _dummy_fmt = '<STR_LIT>' % dummy_fmt <EOL> if metric is None : <EOL> obj . metric_antisym = None <EOL> obj . metric = None <EOL> else : <EOL> if metric in ( True , False , <NUM_LIT:0> , <NUM_LIT:1> ) : <EOL> metric_name = '<STR_LIT>' <EOL> obj . metric_antisym = metric <EOL> else : <EOL> metric_name = metric . name <EOL> obj . metric_antisym = metric . antisym <EOL> sym2 = TensorSymmetry ( get_symmetric_group_sgs ( <NUM_LIT:2> , obj . metric_antisym ) ) <EOL> S2 = TensorType ( [ obj ] * <NUM_LIT:2> , sym2 ) <EOL> obj . metric = S2 ( metric_name ) <EOL> obj . metric . _matrix_behavior = True <EOL> obj . _dim = dim <EOL> obj . _delta = obj . get_kronecker_delta ( ) <EOL> obj . _eps_dim = eps_dim if eps_dim else dim <EOL> obj . _epsilon = obj . get_epsilon ( ) <EOL> obj . _autogenerated = [ ] <EOL> return obj <EOL> @ property <EOL> def auto_right ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _auto_right = TensorIndex ( "<STR_LIT>" , self ) <EOL> return self . _auto_right <EOL> @ property <EOL> def auto_left ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _auto_left = TensorIndex ( "<STR_LIT>" , self ) <EOL> return self . _auto_left <EOL> @ property <EOL> def auto_index ( self ) : <EOL> if not hasattr ( self , '<STR_LIT>' ) : <EOL> self . _auto_index = TensorIndex ( "<STR_LIT>" , self ) <EOL> return self . _auto_index <EOL> @ property <EOL> def data ( self ) : <EOL> return _tensor_data_substitution_dict [ self ] <EOL> @ data . setter <EOL> def data ( self , data ) : <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> data = _TensorDataLazyEvaluator . parse_data ( data ) <EOL> if data . ndim > <NUM_LIT:2> : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> if data . ndim == <NUM_LIT:1> : <EOL> if self . dim is not None : <EOL> nda_dim = data . shape [ <NUM_LIT:0> ] <EOL> if nda_dim != self . dim : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> dim = data . shape [ <NUM_LIT:0> ] <EOL> newndarray = numpy . zeros ( ( dim , dim ) , dtype = object ) <EOL> for i , val in enumerate ( data ) : <EOL> newndarray [ i , i ] = val <EOL> data = newndarray <EOL> dim1 , dim2 = data . shape <EOL> if dim1 != dim2 : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> if self . dim is not None : <EOL> if self . dim != dim1 : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> _tensor_data_substitution_dict [ self ] = data <EOL> _tensor_data_substitution_dict . add_metric_data ( self . metric , data ) <EOL> delta = self . get_kronecker_delta ( ) <EOL> i1 = TensorIndex ( '<STR_LIT>' , self ) <EOL> i2 = TensorIndex ( '<STR_LIT>' , self ) <EOL> delta ( i1 , - i2 ) . data = _TensorDataLazyEvaluator . parse_data ( eye ( dim1 ) ) <EOL> @ data . deleter <EOL> def data ( self ) : <EOL> if self in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self ] <EOL> if self . metric in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self . metric ] <EOL> @ property <EOL> def name ( self ) : <EOL> return self . _name <EOL> @ property <EOL> def dim ( self ) : <EOL> return self . _dim <EOL> @ property <EOL> def delta ( self ) : <EOL> return self . _delta <EOL> @ property <EOL> def eps_dim ( self ) : <EOL> return self . _eps_dim <EOL> @ property <EOL> def epsilon ( self ) : <EOL> return self . _epsilon <EOL> @ property <EOL> def dummy_fmt ( self ) : <EOL> return self . _dummy_fmt <EOL> def get_kronecker_delta ( self ) : <EOL> sym2 = TensorSymmetry ( get_symmetric_group_sgs ( <NUM_LIT:2> ) ) <EOL> S2 = TensorType ( [ self ] * <NUM_LIT:2> , sym2 ) <EOL> delta = S2 ( '<STR_LIT>' ) <EOL> delta . _matrix_behavior = True <EOL> return delta <EOL> def get_epsilon ( self ) : <EOL> if not isinstance ( self . _eps_dim , int ) : <EOL> return None <EOL> sym = TensorSymmetry ( get_symmetric_group_sgs ( self . _eps_dim , <NUM_LIT:1> ) ) <EOL> Sdim = TensorType ( [ self ] * self . _eps_dim , sym ) <EOL> epsilon = Sdim ( '<STR_LIT>' ) <EOL> return epsilon <EOL> def __lt__ ( self , other ) : <EOL> return self . name < other . name <EOL> def __str__ ( self ) : <EOL> return self . name <EOL> __repr__ = __str__ <EOL> def _components_data_full_destroy ( self ) : <EOL> """<STR_LIT>""" <EOL> if self in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self ] <EOL> def delete_tensmul_data ( key ) : <EOL> if key in _tensor_data_substitution_dict . _substitutions_dict_tensmul : <EOL> del _tensor_data_substitution_dict . _substitutions_dict_tensmul [ key ] <EOL> delete_tensmul_data ( ( self . metric , True , True ) ) <EOL> delete_tensmul_data ( ( self . metric , True , False ) ) <EOL> delete_tensmul_data ( ( self . metric , False , True ) ) <EOL> delete_tensmul_data ( ( self . metric , False , False ) ) <EOL> delta = self . get_kronecker_delta ( ) <EOL> if delta in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ delta ] <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensorIndex ( Basic ) : <EOL> """<STR_LIT>""" <EOL> def __new__ ( cls , name , tensortype , is_up = True ) : <EOL> if isinstance ( name , string_types ) : <EOL> name_symbol = Symbol ( name ) <EOL> elif isinstance ( name , Symbol ) : <EOL> name_symbol = name <EOL> elif name is True : <EOL> name = "<STR_LIT>" . format ( len ( tensortype . _autogenerated ) ) <EOL> name_symbol = Symbol ( name ) <EOL> tensortype . _autogenerated . append ( name_symbol ) <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> obj = Basic . __new__ ( cls , name_symbol , tensortype , S . One if is_up else S . Zero ) <EOL> obj . _name = str ( name ) <EOL> obj . _tensortype = tensortype <EOL> obj . _is_up = is_up <EOL> return obj <EOL> @ property <EOL> def name ( self ) : <EOL> return self . _name <EOL> @ property <EOL> def tensortype ( self ) : <EOL> return self . _tensortype <EOL> @ property <EOL> def is_up ( self ) : <EOL> return self . _is_up <EOL> def _print ( self ) : <EOL> s = self . _name <EOL> if not self . _is_up : <EOL> s = '<STR_LIT>' % s <EOL> return s <EOL> def __lt__ ( self , other ) : <EOL> return ( self . _tensortype , self . _name ) < ( other . _tensortype , other . _name ) <EOL> def __neg__ ( self ) : <EOL> t1 = TensorIndex ( self . _name , self . _tensortype , <EOL> ( not self . _is_up ) ) <EOL> return t1 <EOL> def tensor_indices ( s , typ ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( s , str ) : <EOL> a = [ x . name for x in symbols ( s , seq = True ) ] <EOL> else : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> tilist = [ TensorIndex ( i , typ ) for i in a ] <EOL> if len ( tilist ) == <NUM_LIT:1> : <EOL> return tilist [ <NUM_LIT:0> ] <EOL> return tilist <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensorSymmetry ( Basic ) : <EOL> """<STR_LIT>""" <EOL> def __new__ ( cls , * args , ** kw_args ) : <EOL> if len ( args ) == <NUM_LIT:1> : <EOL> base , generators = args [ <NUM_LIT:0> ] <EOL> elif len ( args ) == <NUM_LIT:2> : <EOL> base , generators = args <EOL> else : <EOL> raise TypeError ( "<STR_LIT>" ) <EOL> if not isinstance ( base , Tuple ) : <EOL> base = Tuple ( * base ) <EOL> if not isinstance ( generators , Tuple ) : <EOL> generators = Tuple ( * generators ) <EOL> obj = Basic . __new__ ( cls , base , generators , ** kw_args ) <EOL> return obj <EOL> @ property <EOL> def base ( self ) : <EOL> return self . args [ <NUM_LIT:0> ] <EOL> @ property <EOL> def generators ( self ) : <EOL> return self . args [ <NUM_LIT:1> ] <EOL> @ property <EOL> def rank ( self ) : <EOL> return self . args [ <NUM_LIT:1> ] [ <NUM_LIT:0> ] . size - <NUM_LIT:2> <EOL> def tensorsymmetry ( * args ) : <EOL> """<STR_LIT>""" <EOL> from sympy . combinatorics import Permutation <EOL> def tableau2bsgs ( a ) : <EOL> if len ( a ) == <NUM_LIT:1> : <EOL> n = a [ <NUM_LIT:0> ] <EOL> bsgs = get_symmetric_group_sgs ( n , <NUM_LIT:1> ) <EOL> else : <EOL> if all ( x == <NUM_LIT:1> for x in a ) : <EOL> n = len ( a ) <EOL> bsgs = get_symmetric_group_sgs ( n ) <EOL> elif a == [ <NUM_LIT:2> , <NUM_LIT:2> ] : <EOL> bsgs = riemann_bsgs <EOL> else : <EOL> raise NotImplementedError <EOL> return bsgs <EOL> if not args : <EOL> return TensorSymmetry ( Tuple ( ) , Tuple ( Permutation ( <NUM_LIT:1> ) ) ) <EOL> if len ( args ) == <NUM_LIT:2> and isinstance ( args [ <NUM_LIT:1> ] [ <NUM_LIT:0> ] , Permutation ) : <EOL> return TensorSymmetry ( args ) <EOL> base , sgs = tableau2bsgs ( args [ <NUM_LIT:0> ] ) <EOL> for a in args [ <NUM_LIT:1> : ] : <EOL> basex , sgsx = tableau2bsgs ( a ) <EOL> base , sgs = bsgs_direct_product ( base , sgs , basex , sgsx ) <EOL> return TensorSymmetry ( Tuple ( base , sgs ) ) <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensorType ( Basic ) : <EOL> """<STR_LIT>""" <EOL> is_commutative = False <EOL> def __new__ ( cls , index_types , symmetry , ** kw_args ) : <EOL> assert symmetry . rank == len ( index_types ) <EOL> obj = Basic . __new__ ( cls , Tuple ( * index_types ) , symmetry , ** kw_args ) <EOL> return obj <EOL> @ property <EOL> def index_types ( self ) : <EOL> return self . args [ <NUM_LIT:0> ] <EOL> @ property <EOL> def symmetry ( self ) : <EOL> return self . args [ <NUM_LIT:1> ] <EOL> @ property <EOL> def types ( self ) : <EOL> return sorted ( set ( self . index_types ) , key = lambda x : x . name ) <EOL> def __str__ ( self ) : <EOL> return '<STR_LIT>' % ( [ str ( x ) for x in self . index_types ] ) <EOL> def __call__ ( self , s , comm = <NUM_LIT:0> , matrix_behavior = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( s , str ) : <EOL> names = [ x . name for x in symbols ( s , seq = True ) ] <EOL> else : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if len ( names ) == <NUM_LIT:1> : <EOL> return TensorHead ( names [ <NUM_LIT:0> ] , self , comm , matrix_behavior = matrix_behavior ) <EOL> else : <EOL> return [ TensorHead ( name , self , comm , matrix_behavior = matrix_behavior ) for name in names ] <EOL> def tensorhead ( name , typ , sym , comm = <NUM_LIT:0> , matrix_behavior = <NUM_LIT:0> ) : <EOL> """<STR_LIT>""" <EOL> sym = tensorsymmetry ( * sym ) <EOL> S = TensorType ( typ , sym ) <EOL> th = S ( name , comm , matrix_behavior = matrix_behavior ) <EOL> return th <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensorHead ( Basic ) : <EOL> r"""<STR_LIT>""" <EOL> is_commutative = False <EOL> def __new__ ( cls , name , typ , comm = <NUM_LIT:0> , matrix_behavior = <NUM_LIT:0> , ** kw_args ) : <EOL> if isinstance ( name , string_types ) : <EOL> name_symbol = Symbol ( name ) <EOL> elif isinstance ( name , Symbol ) : <EOL> name_symbol = name <EOL> else : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> comm2i = TensorManager . comm_symbols2i ( comm ) <EOL> obj = Basic . __new__ ( cls , name_symbol , typ , ** kw_args ) <EOL> obj . _matrix_behavior = matrix_behavior <EOL> obj . _name = obj . args [ <NUM_LIT:0> ] . name <EOL> obj . _rank = len ( obj . index_types ) <EOL> obj . _types = typ . types <EOL> obj . _symmetry = typ . symmetry <EOL> obj . _comm = comm2i <EOL> return obj <EOL> @ property <EOL> def name ( self ) : <EOL> return self . _name <EOL> @ property <EOL> def rank ( self ) : <EOL> return self . _rank <EOL> @ property <EOL> def types ( self ) : <EOL> return self . _types [ : ] <EOL> @ property <EOL> def symmetry ( self ) : <EOL> return self . _symmetry <EOL> @ property <EOL> def typ ( self ) : <EOL> return self . args [ <NUM_LIT:1> ] <EOL> @ property <EOL> def comm ( self ) : <EOL> return self . _comm <EOL> @ property <EOL> def index_types ( self ) : <EOL> return self . args [ <NUM_LIT:1> ] . index_types [ : ] <EOL> def __lt__ ( self , other ) : <EOL> return ( self . name , self . index_types ) < ( other . name , other . index_types ) <EOL> def commutes_with ( self , other ) : <EOL> """<STR_LIT>""" <EOL> r = TensorManager . get_comm ( self . _comm , other . _comm ) <EOL> return r <EOL> def _print ( self ) : <EOL> return '<STR_LIT>' % ( self . name , '<STR_LIT:U+002C>' . join ( [ str ( x ) for x in self . index_types ] ) ) <EOL> def _check_auto_matrix_indices_in_call ( self , * indices ) : <EOL> matrix_behavior_kinds = dict ( ) <EOL> if len ( indices ) != len ( self . index_types ) : <EOL> if not self . _matrix_behavior : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> ldiff = len ( self . index_types ) - len ( indices ) <EOL> if ldiff > <NUM_LIT:2> : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if ldiff == <NUM_LIT:2> : <EOL> mat_ind = [ len ( indices ) , len ( indices ) + <NUM_LIT:1> ] <EOL> elif ldiff == <NUM_LIT:1> : <EOL> mat_ind = [ len ( indices ) ] <EOL> not_equal = True <EOL> else : <EOL> not_equal = False <EOL> mat_ind = [ i for i , e in enumerate ( indices ) if e is True ] <EOL> if mat_ind : <EOL> not_equal = True <EOL> indices = tuple ( [ _ for _ in indices if _ is not True ] ) <EOL> for i , el in enumerate ( indices ) : <EOL> if not isinstance ( el , TensorIndex ) : <EOL> not_equal = True <EOL> break <EOL> if el . _tensortype != self . index_types [ i ] : <EOL> not_equal = True <EOL> break <EOL> if not_equal : <EOL> for el in mat_ind : <EOL> eltyp = self . index_types [ el ] <EOL> if eltyp in matrix_behavior_kinds : <EOL> elind = - self . index_types [ el ] . auto_right <EOL> matrix_behavior_kinds [ eltyp ] . append ( elind ) <EOL> else : <EOL> elind = self . index_types [ el ] . auto_left <EOL> matrix_behavior_kinds [ eltyp ] = [ elind ] <EOL> indices = indices [ : el ] + ( elind , ) + indices [ el : ] <EOL> return indices , matrix_behavior_kinds <EOL> def __call__ ( self , * indices , ** kw_args ) : <EOL> """<STR_LIT>""" <EOL> indices , matrix_behavior_kinds = self . _check_auto_matrix_indices_in_call ( * indices ) <EOL> tensor = Tensor . _new_with_dummy_replacement ( self , indices , ** kw_args ) <EOL> return tensor <EOL> def __pow__ ( self , other ) : <EOL> if self . data is None : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> metrics = [ _ . data for _ in self . args [ <NUM_LIT:1> ] . args [ <NUM_LIT:0> ] ] <EOL> marray = self . data <EOL> for metric in metrics : <EOL> marray = numpy . tensordot ( marray , numpy . tensordot ( metric , marray , ( <NUM_LIT:1> , <NUM_LIT:0> ) ) , ( <NUM_LIT:0> , <NUM_LIT:0> ) ) <EOL> pow2 = marray [ ( ) ] <EOL> return pow2 ** ( Rational ( <NUM_LIT:1> , <NUM_LIT:2> ) * other ) <EOL> @ property <EOL> def data ( self ) : <EOL> return _tensor_data_substitution_dict [ self ] <EOL> @ data . setter <EOL> def data ( self , data ) : <EOL> _tensor_data_substitution_dict [ self ] = data <EOL> @ data . deleter <EOL> def data ( self ) : <EOL> if self in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self ] <EOL> def __iter__ ( self ) : <EOL> return self . data . flatten ( ) . __iter__ ( ) <EOL> def _components_data_full_destroy ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . name == "<STR_LIT>" : <EOL> return <EOL> if self in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self ] <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensExpr ( Basic ) : <EOL> """<STR_LIT>""" <EOL> _op_priority = <NUM_LIT> <EOL> is_commutative = False <EOL> def __neg__ ( self ) : <EOL> return self * S . NegativeOne <EOL> def __abs__ ( self ) : <EOL> raise NotImplementedError <EOL> def __add__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __radd__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __sub__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __rsub__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __mul__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __rmul__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __pow__ ( self , other ) : <EOL> if self . data is None : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> numpy = import_module ( '<STR_LIT>' ) <EOL> free = self . free <EOL> marray = self . data <EOL> for metric in free : <EOL> marray = numpy . tensordot ( <EOL> marray , <EOL> numpy . tensordot ( <EOL> metric [ <NUM_LIT:0> ] . _tensortype . data , <EOL> marray , <EOL> ( <NUM_LIT:1> , <NUM_LIT:0> ) <EOL> ) , <EOL> ( <NUM_LIT:0> , <NUM_LIT:0> ) <EOL> ) <EOL> pow2 = marray [ ( ) ] <EOL> return pow2 ** ( Rational ( <NUM_LIT:1> , <NUM_LIT:2> ) * other ) <EOL> def __rpow__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __div__ ( self , other ) : <EOL> raise NotImplementedError <EOL> def __rdiv__ ( self , other ) : <EOL> raise NotImplementedError ( ) <EOL> __truediv__ = __div__ <EOL> __rtruediv__ = __rdiv__ <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> def get_matrix ( self ) : <EOL> """<STR_LIT>""" <EOL> if <NUM_LIT:0> < self . rank <= <NUM_LIT:2> : <EOL> rows = self . data . shape [ <NUM_LIT:0> ] <EOL> columns = self . data . shape [ <NUM_LIT:1> ] if self . rank == <NUM_LIT:2> else <NUM_LIT:1> <EOL> if self . rank == <NUM_LIT:2> : <EOL> mat_list = [ ] * rows <EOL> for i in range ( rows ) : <EOL> mat_list . append ( [ ] ) <EOL> for j in range ( columns ) : <EOL> mat_list [ i ] . append ( self [ i , j ] ) <EOL> else : <EOL> mat_list = [ None ] * rows <EOL> for i in range ( rows ) : <EOL> mat_list [ i ] = self [ i ] <EOL> return Matrix ( mat_list ) <EOL> else : <EOL> raise NotImplementedError ( <EOL> "<STR_LIT>" ) <EOL> def _eval_simplify ( self , ratio , measure ) : <EOL> expr = self <EOL> for i in list ( set ( self . components ) ) : <EOL> if hasattr ( i , '<STR_LIT>' ) : <EOL> expr = i . simplify_this_type ( expr ) <EOL> return expr <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensAdd ( TensExpr ) : <EOL> """<STR_LIT>""" <EOL> def __new__ ( cls , * args , ** kw_args ) : <EOL> args = [ sympify ( x ) for x in args if x ] <EOL> args = TensAdd . _tensAdd_flatten ( args ) <EOL> if not args : <EOL> return S . Zero <EOL> if len ( args ) == <NUM_LIT:1> and not isinstance ( args [ <NUM_LIT:0> ] , TensExpr ) : <EOL> return args [ <NUM_LIT:0> ] <EOL> args = TensAdd . _tensAdd_check_automatrix ( args ) <EOL> TensAdd . _tensAdd_check ( args ) <EOL> if len ( args ) == <NUM_LIT:1> and isinstance ( args [ <NUM_LIT:0> ] , TensMul ) : <EOL> obj = Basic . __new__ ( cls , * args , ** kw_args ) <EOL> return obj <EOL> args = [ canon_bp ( x ) for x in args if x ] <EOL> args = [ x for x in args if x ] <EOL> if not args : <EOL> return S . Zero <EOL> if len ( args ) == <NUM_LIT:1> : <EOL> return args [ <NUM_LIT:0> ] <EOL> def sort_key ( t ) : <EOL> x = get_tids ( t ) <EOL> return ( x . components , x . free , x . dum ) <EOL> args . sort ( key = sort_key ) <EOL> args = TensAdd . _tensAdd_collect_terms ( args ) <EOL> if not args : <EOL> return S . Zero <EOL> if len ( args ) == <NUM_LIT:1> : <EOL> return args [ <NUM_LIT:0> ] <EOL> obj = Basic . __new__ ( cls , * args , ** kw_args ) <EOL> return obj <EOL> @ staticmethod <EOL> def _tensAdd_flatten ( args ) : <EOL> if not all ( isinstance ( x , TensExpr ) for x in args ) : <EOL> args1 = [ ] <EOL> for x in args : <EOL> if isinstance ( x , TensExpr ) : <EOL> if isinstance ( x , TensAdd ) : <EOL> args1 . extend ( list ( x . args ) ) <EOL> else : <EOL> args1 . append ( x ) <EOL> args1 = [ x for x in args1 if isinstance ( x , TensExpr ) and x . coeff ] <EOL> args2 = [ x for x in args if not isinstance ( x , TensExpr ) ] <EOL> t1 = TensMul . from_data ( Add ( * args2 ) , [ ] , [ ] , [ ] ) <EOL> args = [ t1 ] + args1 <EOL> a = [ ] <EOL> for x in args : <EOL> if isinstance ( x , TensAdd ) : <EOL> a . extend ( list ( x . args ) ) <EOL> else : <EOL> a . append ( x ) <EOL> args = [ x for x in a if x . coeff ] <EOL> return args <EOL> @ staticmethod <EOL> def _tensAdd_check_automatrix ( args ) : <EOL> if not args : <EOL> return args <EOL> auto_left_types = set ( [ ] ) <EOL> auto_right_types = set ( [ ] ) <EOL> args_auto_left_types = [ ] <EOL> args_auto_right_types = [ ] <EOL> for i , arg in enumerate ( args ) : <EOL> arg_auto_left_types = set ( [ ] ) <EOL> arg_auto_right_types = set ( [ ] ) <EOL> for index in get_indices ( arg ) : <EOL> if index in ( index . _tensortype . auto_left , - index . _tensortype . auto_left ) : <EOL> auto_left_types . add ( index . _tensortype ) <EOL> arg_auto_left_types . add ( index . _tensortype ) <EOL> if index in ( index . _tensortype . auto_right , - index . _tensortype . auto_right ) : <EOL> auto_right_types . add ( index . _tensortype ) <EOL> arg_auto_right_types . add ( index . _tensortype ) <EOL> args_auto_left_types . append ( arg_auto_left_types ) <EOL> args_auto_right_types . append ( arg_auto_right_types ) <EOL> for arg , aas_left , aas_right in zip ( args , args_auto_left_types , args_auto_right_types ) : <EOL> missing_left = auto_left_types - aas_left <EOL> missing_right = auto_right_types - aas_right <EOL> missing_intersection = missing_left & missing_right <EOL> for j in missing_intersection : <EOL> args [ i ] *= j . delta ( j . auto_left , - j . auto_right ) <EOL> if missing_left != missing_right : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> return args <EOL> @ staticmethod <EOL> def _tensAdd_check ( args ) : <EOL> indices0 = { x [ <NUM_LIT:0> ] for x in get_tids ( args [ <NUM_LIT:0> ] ) . free } <EOL> list_indices = [ { y [ <NUM_LIT:0> ] for y in get_tids ( x ) . free } for x in args [ <NUM_LIT:1> : ] ] <EOL> if not all ( x == indices0 for x in list_indices ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> @ staticmethod <EOL> def _tensAdd_collect_terms ( args ) : <EOL> a = [ ] <EOL> prev = args [ <NUM_LIT:0> ] <EOL> prev_coeff = get_coeff ( prev ) <EOL> changed = False <EOL> for x in args [ <NUM_LIT:1> : ] : <EOL> x_tids = get_tids ( x ) <EOL> prev_tids = get_tids ( prev ) <EOL> if x_tids . components == prev_tids . components and x_tids . free == prev_tids . free and x_tids . dum == prev_tids . dum : <EOL> prev_coeff = prev_coeff + get_coeff ( x ) <EOL> changed = True <EOL> op = <NUM_LIT:0> <EOL> else : <EOL> if not changed : <EOL> a . append ( prev ) <EOL> else : <EOL> if prev_coeff : <EOL> t = TensMul . from_data ( prev_coeff , prev_tids . components , <EOL> prev_tids . free , prev_tids . dum ) <EOL> a . append ( t ) <EOL> op = <NUM_LIT:1> <EOL> pprev , prev = prev , x <EOL> pprev_coeff , prev_coeff = prev_coeff , get_coeff ( x ) <EOL> changed = False <EOL> if op == <NUM_LIT:0> and prev_coeff : <EOL> prev = TensMul . from_data ( prev_coeff , prev_tids . components , prev_tids . free , prev_tids . dum ) <EOL> a . append ( prev ) <EOL> elif op == <NUM_LIT:1> : <EOL> a . append ( prev ) <EOL> return a <EOL> @ property <EOL> def rank ( self ) : <EOL> return self . args [ <NUM_LIT:0> ] . rank <EOL> @ property <EOL> def free_args ( self ) : <EOL> return self . args [ <NUM_LIT:0> ] . free_args <EOL> def __call__ ( self , * indices ) : <EOL> """<STR_LIT>""" <EOL> free_args = self . free_args <EOL> indices = list ( indices ) <EOL> if [ x . _tensortype for x in indices ] != [ x . _tensortype for x in free_args ] : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if indices == free_args : <EOL> return self <EOL> index_tuples = list ( zip ( free_args , indices ) ) <EOL> a = [ x . func ( * x . fun_eval ( * index_tuples ) . args ) for x in self . args ] <EOL> res = TensAdd ( * a ) <EOL> return res <EOL> def canon_bp ( self ) : <EOL> """<STR_LIT>""" <EOL> args = [ x . canon_bp ( ) for x in self . args ] <EOL> res = TensAdd ( * args ) <EOL> return res <EOL> def equals ( self , other ) : <EOL> other = sympify ( other ) <EOL> if isinstance ( other , TensMul ) and other . _coeff == <NUM_LIT:0> : <EOL> return all ( x . _coeff == <NUM_LIT:0> for x in self . args ) <EOL> if isinstance ( other , TensExpr ) : <EOL> if self . rank != other . rank : <EOL> return False <EOL> if isinstance ( other , TensAdd ) : <EOL> if set ( self . args ) != set ( other . args ) : <EOL> return False <EOL> else : <EOL> return True <EOL> t = self - other <EOL> if not isinstance ( t , TensExpr ) : <EOL> return t == <NUM_LIT:0> <EOL> else : <EOL> if isinstance ( t , TensMul ) : <EOL> return t . _coeff == <NUM_LIT:0> <EOL> else : <EOL> return all ( x . _coeff == <NUM_LIT:0> for x in t . args ) <EOL> def __add__ ( self , other ) : <EOL> return TensAdd ( self , other ) <EOL> def __radd__ ( self , other ) : <EOL> return TensAdd ( other , self ) <EOL> def __sub__ ( self , other ) : <EOL> return TensAdd ( self , - other ) <EOL> def __rsub__ ( self , other ) : <EOL> return TensAdd ( other , - self ) <EOL> def __mul__ ( self , other ) : <EOL> return TensAdd ( * ( x * other for x in self . args ) ) <EOL> def __rmul__ ( self , other ) : <EOL> return self * other <EOL> def __div__ ( self , other ) : <EOL> other = sympify ( other ) <EOL> if isinstance ( other , TensExpr ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> return TensAdd ( * ( x / other for x in self . args ) ) <EOL> def __rdiv__ ( self , other ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> def __getitem__ ( self , item ) : <EOL> return self . data [ item ] <EOL> __truediv__ = __div__ <EOL> __truerdiv__ = __rdiv__ <EOL> def contract_delta ( self , delta ) : <EOL> args = [ x . contract_delta ( delta ) for x in self . args ] <EOL> t = TensAdd ( * args ) <EOL> return canon_bp ( t ) <EOL> def contract_metric ( self , g ) : <EOL> """<STR_LIT>""" <EOL> args = [ contract_metric ( x , g ) for x in self . args ] <EOL> t = TensAdd ( * args ) <EOL> return canon_bp ( t ) <EOL> def fun_eval ( self , * index_tuples ) : <EOL> """<STR_LIT>""" <EOL> args = self . args <EOL> args1 = [ ] <EOL> for x in args : <EOL> y = x . fun_eval ( * index_tuples ) <EOL> args1 . append ( y ) <EOL> return TensAdd ( * args1 ) <EOL> def substitute_indices ( self , * index_tuples ) : <EOL> """<STR_LIT>""" <EOL> args = self . args <EOL> args1 = [ ] <EOL> for x in args : <EOL> y = x . substitute_indices ( * index_tuples ) <EOL> args1 . append ( y ) <EOL> return TensAdd ( * args1 ) <EOL> def _print ( self ) : <EOL> a = [ ] <EOL> args = self . args <EOL> for x in args : <EOL> a . append ( str ( x ) ) <EOL> a . sort ( ) <EOL> s = '<STR_LIT>' . join ( a ) <EOL> s = s . replace ( '<STR_LIT>' , '<STR_LIT>' ) <EOL> return s <EOL> @ staticmethod <EOL> def from_TIDS_list ( coeff , tids_list ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( coeff , ( list , tuple , Tuple ) ) : <EOL> coeff = [ coeff ] * len ( tids_list ) <EOL> tensmul_list = [ TensMul . from_TIDS ( c , t ) for c , t in zip ( coeff , tids_list ) ] <EOL> return TensAdd ( * tensmul_list ) <EOL> @ property <EOL> def data ( self ) : <EOL> return _tensor_data_substitution_dict [ self ] <EOL> @ data . setter <EOL> def data ( self , data ) : <EOL> _tensor_data_substitution_dict [ self ] = data <EOL> @ data . deleter <EOL> def data ( self ) : <EOL> if self in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self ] <EOL> def __iter__ ( self ) : <EOL> if not self . data : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> return self . data . flatten ( ) . __iter__ ( ) <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class Tensor ( TensExpr ) : <EOL> """<STR_LIT>""" <EOL> is_commutative = False <EOL> def __new__ ( cls , tensor_head , indices , ** kw_args ) : <EOL> tids = TIDS . from_components_and_indices ( ( tensor_head , ) , indices ) <EOL> obj = Basic . __new__ ( cls , tensor_head , Tuple ( * indices ) , ** kw_args ) <EOL> obj . _tids = tids <EOL> obj . _indices = indices <EOL> obj . _is_canon_bp = kw_args . get ( '<STR_LIT>' , False ) <EOL> return obj <EOL> @ staticmethod <EOL> def _new_with_dummy_replacement ( tensor_head , indices , ** kw_args ) : <EOL> tids = TIDS . from_components_and_indices ( ( tensor_head , ) , indices ) <EOL> indices = tids . get_indices ( ) <EOL> return Tensor ( tensor_head , indices , ** kw_args ) <EOL> @ property <EOL> def is_canon_bp ( self ) : <EOL> return self . _is_canon_bp <EOL> @ property <EOL> def indices ( self ) : <EOL> return self . _indices <EOL> @ property <EOL> def free ( self ) : <EOL> return self . _tids . free <EOL> @ property <EOL> def dum ( self ) : <EOL> return self . _tids . dum <EOL> @ property <EOL> def rank ( self ) : <EOL> return len ( self . free ) <EOL> @ property <EOL> def free_args ( self ) : <EOL> return sorted ( [ x [ <NUM_LIT:0> ] for x in self . free ] ) <EOL> def perm2tensor ( self , g , canon_bp = False ) : <EOL> """<STR_LIT>""" <EOL> return perm2tensor ( self , g , canon_bp ) <EOL> def canon_bp ( self ) : <EOL> if self . _is_canon_bp : <EOL> return self <EOL> g , dummies , msym , v = self . _tids . canon_args ( ) <EOL> can = canonicalize ( g , dummies , msym , * v ) <EOL> if can == <NUM_LIT:0> : <EOL> return S . Zero <EOL> tensor = self . perm2tensor ( can , True ) <EOL> return tensor <EOL> @ property <EOL> def types ( self ) : <EOL> return get_tids ( self ) . components [ <NUM_LIT:0> ] . _types <EOL> @ property <EOL> def coeff ( self ) : <EOL> return S . One <EOL> @ property <EOL> def component ( self ) : <EOL> return self . args [ <NUM_LIT:0> ] <EOL> @ property <EOL> def components ( self ) : <EOL> return [ self . args [ <NUM_LIT:0> ] ] <EOL> def split ( self ) : <EOL> return [ self ] <EOL> def expand ( self ) : <EOL> return self <EOL> def sorted_components ( self ) : <EOL> return self <EOL> def get_indices ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _tids . get_indices ( ) <EOL> def as_base_exp ( self ) : <EOL> return self , S . One <EOL> def substitute_indices ( self , * index_tuples ) : <EOL> return substitute_indices ( self , * index_tuples ) <EOL> def __call__ ( self , * indices ) : <EOL> """<STR_LIT>""" <EOL> free_args = self . free_args <EOL> indices = list ( indices ) <EOL> if [ x . _tensortype for x in indices ] != [ x . _tensortype for x in free_args ] : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if indices == free_args : <EOL> return self <EOL> t = self . fun_eval ( * list ( zip ( free_args , indices ) ) ) <EOL> if len ( set ( i if i . is_up else - i for i in indices ) ) != len ( indices ) : <EOL> return t . func ( * t . args ) <EOL> return t <EOL> def fun_eval ( self , * index_tuples ) : <EOL> free = self . free <EOL> free1 = [ ] <EOL> for j , ipos , cpos in free : <EOL> for i , v in index_tuples : <EOL> if i == j : <EOL> free1 . append ( ( v , ipos , cpos ) ) <EOL> break <EOL> else : <EOL> free1 . append ( ( j , ipos , cpos ) ) <EOL> return TensMul . from_data ( self . coeff , self . components , free1 , self . dum ) <EOL> def __iter__ ( self ) : <EOL> return self . data . flatten ( ) . __iter__ ( ) <EOL> def __getitem__ ( self , item ) : <EOL> return self . data [ item ] <EOL> @ property <EOL> def data ( self ) : <EOL> return _tensor_data_substitution_dict [ self ] <EOL> @ data . setter <EOL> def data ( self , data ) : <EOL> _tensor_data_substitution_dict [ self ] = data <EOL> @ data . deleter <EOL> def data ( self ) : <EOL> if self in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self ] <EOL> if self . metric in _tensor_data_substitution_dict : <EOL> del _tensor_data_substitution_dict [ self . metric ] <EOL> def __mul__ ( self , other ) : <EOL> if isinstance ( other , TensAdd ) : <EOL> return TensAdd ( * [ self * arg for arg in other . args ] ) <EOL> tmul = TensMul ( self , other ) <EOL> return tmul <EOL> def __rmul__ ( self , other ) : <EOL> return TensMul ( other , self ) <EOL> def __div__ ( self , other ) : <EOL> if isinstance ( other , TensExpr ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> return TensMul ( self , S . One / other , is_canon_bp = self . is_canon_bp ) <EOL> def __rdiv__ ( self , other ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> def __add__ ( self , other ) : <EOL> return TensAdd ( self , other ) <EOL> def __radd__ ( self , other ) : <EOL> return TensAdd ( other , self ) <EOL> def __sub__ ( self , other ) : <EOL> return TensAdd ( self , - other ) <EOL> def __rsub__ ( self , other ) : <EOL> return TensAdd ( other , self ) <EOL> __truediv__ = __div__ <EOL> __rtruediv__ = __rdiv__ <EOL> def __neg__ ( self ) : <EOL> return TensMul ( S . NegativeOne , self ) <EOL> def _print ( self ) : <EOL> indices = [ str ( ind ) for ind in self . indices ] <EOL> component = self . component <EOL> if component . rank > <NUM_LIT:0> : <EOL> return ( '<STR_LIT>' % ( component . name , '<STR_LIT:U+002CU+0020>' . join ( indices ) ) ) <EOL> else : <EOL> return ( '<STR_LIT:%s>' % component . name ) <EOL> def equals ( self , other ) : <EOL> if other == <NUM_LIT:0> : <EOL> return self . coeff == <NUM_LIT:0> <EOL> other = sympify ( other ) <EOL> if not isinstance ( other , TensExpr ) : <EOL> assert not self . components <EOL> return S . One == other <EOL> def _get_compar_comp ( self ) : <EOL> t = self . canon_bp ( ) <EOL> r = ( t . coeff , tuple ( t . components ) , tuple ( sorted ( t . free ) ) , tuple ( sorted ( t . dum ) ) ) <EOL> return r <EOL> return _get_compar_comp ( self ) == _get_compar_comp ( other ) <EOL> def contract_metric ( self , metric ) : <EOL> tids , sign = get_tids ( self ) . contract_metric ( metric ) <EOL> return TensMul . from_TIDS ( sign , tids ) <EOL> def contract_delta ( self , metric ) : <EOL> return self . contract_metric ( metric ) <EOL> @ doctest_depends_on ( modules = ( '<STR_LIT>' , ) ) <EOL> class TensMul ( TensExpr ) : <EOL> """<STR_LIT>""" <EOL> def __new__ ( cls , * args , ** kw_args ) : <EOL> args = [ sympify ( arg ) for arg in args ] <EOL> args = TensMul . _flatten ( args ) <EOL> is_canon_bp = kw_args . get ( '<STR_LIT>' , False ) <EOL> if not any ( [ isinstance ( arg , TensExpr ) for arg in args ] ) : <EOL> tids = TIDS ( [ ] , [ ] , [ ] ) <EOL> else : <EOL> tids_list = [ arg . _tids for arg in args if isinstance ( arg , ( Tensor , TensMul ) ) ] <EOL> if len ( tids_list ) == <NUM_LIT:1> : <EOL> for arg in args : <EOL> if not isinstance ( arg , Tensor ) : <EOL> continue <EOL> is_canon_bp = kw_args . get ( '<STR_LIT>' , arg . _is_canon_bp ) <EOL> tids = reduce ( lambda a , b : a * b , tids_list ) <EOL> if any ( [ isinstance ( arg , TensAdd ) for arg in args ] ) : <EOL> add_args = TensAdd . _tensAdd_flatten ( args ) <EOL> return TensAdd ( * add_args ) <EOL> coeff = reduce ( lambda a , b : a * b , [ S . One ] + [ arg for arg in args if not isinstance ( arg , TensExpr ) ] ) <EOL> args = tids . get_tensors ( ) <EOL> if coeff != <NUM_LIT:1> : <EOL> args = [ coeff ] + args <EOL> if len ( args ) == <NUM_LIT:1> : <EOL> return args [ <NUM_LIT:0> ] <EOL> obj = Basic . __new__ ( cls , * args ) <EOL> obj . _types = [ ] <EOL> for t in tids . components : <EOL> obj . _types . extend ( t . _types ) <EOL> obj . _tids = tids <EOL> obj . _ext_rank = len ( obj . _tids . free ) + <NUM_LIT:2> * len ( obj . _tids . dum ) <EOL> obj . _coeff = coeff <EOL> obj . _is_canon_bp = is_canon_bp <EOL> return obj <EOL> @ staticmethod <EOL> def _flatten ( args ) : <EOL> a = [ ] <EOL> for arg in args : <EOL> if isinstance ( arg , TensMul ) : <EOL> a . extend ( arg . args ) <EOL> else : <EOL> a . append ( arg ) <EOL> return a <EOL> @ staticmethod <EOL> def from_data ( coeff , components , free , dum , ** kw_args ) : <EOL> tids = TIDS ( components , free , dum ) <EOL> return TensMul . from_TIDS ( coeff , tids , ** kw_args ) <EOL> @ staticmethod <EOL> def from_TIDS ( coeff , tids , ** kw_args ) : <EOL> return TensMul ( coeff , * tids . get_tensors ( ) , ** kw_args ) <EOL> @ property <EOL> def free_args ( self ) : <EOL> return sorted ( [ x [ <NUM_LIT:0> ] for x in self . free ] ) <EOL> @ property <EOL> def components ( self ) : <EOL> return self . _tids . components [ : ] <EOL> @ property <EOL> def free ( self ) : <EOL> return self . _tids . free [ : ] <EOL> @ property <EOL> def coeff ( self ) : <EOL> return self . _coeff <EOL> @ property <EOL> def dum ( self ) : <EOL> return self . _tids . dum [ : ] <EOL> @ property <EOL> def rank ( self ) : <EOL> return len ( self . free ) <EOL> @ property <EOL> def types ( self ) : <EOL> return self . _types [ : ] <EOL> def equals ( self , other ) : <EOL> if other == <NUM_LIT:0> : <EOL> return self . coeff == <NUM_LIT:0> <EOL> other = sympify ( other ) <EOL> if not isinstance ( other , TensExpr ) : <EOL> assert not self . components <EOL> return self . _coeff == other <EOL> def _get_compar_comp ( self ) : <EOL> t = self . canon_bp ( ) <EOL> r = ( get_coeff ( t ) , tuple ( t . components ) , tuple ( sorted ( t . free ) ) , tuple ( sorted ( t . dum ) ) ) <EOL> return r <EOL> return _get_compar_comp ( self ) == _get_compar_comp ( other ) <EOL> def get_indices ( self ) : <EOL> """<STR_LIT>""" <EOL> return self . _tids . get_indices ( ) <EOL> def split ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . args == ( ) : <EOL> return [ self ] <EOL> splitp = [ ] <EOL> res = <NUM_LIT:1> <EOL> for arg in self . args : <EOL> if isinstance ( arg , Tensor ) : <EOL> splitp . append ( res * arg ) <EOL> res = <NUM_LIT:1> <EOL> else : <EOL> res *= arg <EOL> return splitp <EOL> def __add__ ( self , other ) : <EOL> return TensAdd ( self , other ) <EOL> def __radd__ ( self , other ) : <EOL> return TensAdd ( other , self ) <EOL> def __sub__ ( self , other ) : <EOL> return TensAdd ( self , - other ) <EOL> def __rsub__ ( self , other ) : <EOL> return TensAdd ( other , - self ) <EOL> def __mul__ ( self , other ) : <EOL> """<STR_LIT>""" <EOL> other = sympify ( other ) <EOL> if not isinstance ( other , TensExpr ) : <EOL> coeff = self . coeff * other <EOL> tmul = TensMul . from_TIDS ( coeff , self . _tids , is_canon_bp = self . _is_canon_bp ) <EOL> return tmul <EOL> if isinstance ( other , TensAdd ) : <EOL> return TensAdd ( * [ self * x for x in other . args ] ) <EOL> new_tids = self . _tids * other . _tids <EOL> coeff = self . coeff * other . coeff <EOL> tmul = TensMul . from_TIDS ( coeff , new_tids ) <EOL> return tmul <EOL> def __rmul__ ( self , other ) : <EOL> other = sympify ( other ) <EOL> coeff = other * self . _coeff <EOL> tmul = TensMul . from_TIDS ( coeff , self . _tids ) <EOL> return tmul <EOL> def __div__ ( self , other ) : <EOL> other = sympify ( other ) <EOL> if isinstance ( other , TensExpr ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> coeff = self . _coeff / other <EOL> tmul = TensMul . from_TIDS ( coeff , self . _tids , is_canon_bp = self . _is_canon_bp ) <EOL> return tmul <EOL> def __rdiv__ ( self , other ) : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> def __getitem__ ( self , item ) : <EOL> return self . data [ item ] <EOL> __truediv__ = __div__ <EOL> __truerdiv__ = __rdiv__ <EOL> def sorted_components ( self ) : <EOL> """<STR_LIT>""" <EOL> new_tids , sign = self . _tids . sorted_components ( ) <EOL> coeff = - self . coeff if sign == - <NUM_LIT:1> else self . coeff <EOL> t = TensMul . from_TIDS ( coeff , new_tids ) <EOL> return t <EOL> def perm2tensor ( self , g , canon_bp = False ) : <EOL> """<STR_LIT>""" <EOL> return perm2tensor ( self , g , canon_bp ) <EOL> def canon_bp ( self ) : <EOL> """<STR_LIT>""" <EOL> if self . _is_canon_bp : <EOL> return self <EOL> if not self . components : <EOL> return self <EOL> t = self . sorted_components ( ) <EOL> g , dummies , msym , v = t . _tids . canon_args ( ) <EOL> can = canonicalize ( g , dummies , msym , * v ) <EOL> if can == <NUM_LIT:0> : <EOL> return S . Zero <EOL> tmul = t . perm2tensor ( can , True ) <EOL> return tmul <EOL> def contract_delta ( self , delta ) : <EOL> t = self . contract_metric ( delta ) <EOL> return t <EOL> def contract_metric ( self , g ) : <EOL> """<STR_LIT>""" <EOL> tids , sign = get_tids ( self ) . contract_metric ( g ) <EOL> res = TensMul . from_TIDS ( sign * self . coeff , tids ) <EOL> return res <EOL> def substitute_indices ( self , * index_tuples ) : <EOL> return substitute_indices ( self , * index_tuples ) <EOL> def fun_eval ( self , * index_tuples ) : <EOL> """<STR_LIT>""" <EOL> free = self . free <EOL> free1 = [ ] <EOL> for j , ipos , cpos in free : <EOL> for i , v in index_tuples : <EOL> if i == j : <EOL> free1 . append ( ( v , ipos , cpos ) ) <EOL> break <EOL> else : <EOL> free1 . append ( ( j , ipos , cpos ) ) <EOL> return TensMul . from_data ( self . coeff , self . components , free1 , self . dum ) <EOL> def __call__ ( self , * indices ) : <EOL> """<STR_LIT>""" <EOL> free_args = self . free_args <EOL> indices = list ( indices ) <EOL> if [ x . _tensortype for x in indices ] != [ x . _tensortype for x in free_args ] : <EOL> raise ValueError ( '<STR_LIT>' ) <EOL> if indices == free_args : <EOL> return self <EOL> t = self . fun_eval ( * list ( zip ( free_args , indices ) ) ) <EOL> if len ( set ( i if i . is_up else - i for i in indices ) ) != len ( indices ) : <EOL> return t . func ( * t . args ) <EOL> return t <EOL> def _print ( self ) : <EOL> args = self . args <EOL> get_str = lambda arg : str ( arg ) if arg . is_Atom or isinstance ( arg , TensExpr ) else ( "<STR_LIT>" % str ( arg ) ) <EOL> if not args : <EOL> return "<STR_LIT:1>" <EOL> if self . coeff == S . NegativeOne : <EOL> return "<STR_LIT:->" + "<STR_LIT:*>" . join ( [ get_str ( arg ) for arg in args [ <NUM_LIT:1> : ] ] ) <EOL> return "<STR_LIT:*>" . join ( [ get_str ( arg ) for arg in self . args ] ) <EOL> @ property <EOL> def data ( self ) : <EOL> dat = _tensor_data_substitution_dict [ self ] <EOL> if dat is None : <EOL> return None <EOL> return self . coeff * dat <EOL> @ data . setter <EOL> def data ( self , data ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> @ data . deleter <EOL> def data ( self ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> def __iter__ ( self ) : <EOL> if self . data is None : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> return ( self . data . flatten ( ) ) . __iter__ ( ) <EOL> def canon_bp ( p ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( p , TensExpr ) : <EOL> return p . canon_bp ( ) <EOL> return p <EOL> def tensor_mul ( * a ) : <EOL> """<STR_LIT>""" <EOL> if not a : <EOL> return TensMul . from_data ( S . One , [ ] , [ ] , [ ] ) <EOL> t = a [ <NUM_LIT:0> ] <EOL> for tx in a [ <NUM_LIT:1> : ] : <EOL> t = t * tx <EOL> return t <EOL> def riemann_cyclic_replace ( t_r ) : <EOL> """<STR_LIT>""" <EOL> free = sorted ( t_r . free , key = lambda x : x [ <NUM_LIT:1> ] ) <EOL> m , n , p , q = [ x [ <NUM_LIT:0> ] for x in free ] <EOL> t0 = S ( <NUM_LIT:2> ) / <NUM_LIT:3> * t_r <EOL> t1 = - S ( <NUM_LIT:1> ) / <NUM_LIT:3> * t_r . substitute_indices ( ( m , m ) , ( n , q ) , ( p , n ) , ( q , p ) ) <EOL> t2 = S ( <NUM_LIT:1> ) / <NUM_LIT:3> * t_r . substitute_indices ( ( m , m ) , ( n , p ) , ( p , n ) , ( q , q ) ) <EOL> t3 = t0 + t1 + t2 <EOL> return t3 <EOL> def riemann_cyclic ( t2 ) : <EOL> """<STR_LIT>""" <EOL> if isinstance ( t2 , ( TensMul , Tensor ) ) : <EOL> args = [ t2 ] <EOL> else : <EOL> args = t2 . args <EOL> a1 = [ x . split ( ) for x in args ] <EOL> a2 = [ [ riemann_cyclic_replace ( tx ) for tx in y ] for y in a1 ] <EOL> a3 = [ tensor_mul ( * v ) for v in a2 ] <EOL> t3 = TensAdd ( * a3 ) <EOL> if not t3 : <EOL> return t3 <EOL> else : <EOL> return canon_bp ( t3 ) <EOL> def get_lines ( ex , index_type ) : <EOL> """<STR_LIT>""" <EOL> def _join_lines ( a ) : <EOL> i = <NUM_LIT:0> <EOL> while i < len ( a ) : <EOL> x = a [ i ] <EOL> xend = x [ - <NUM_LIT:1> ] <EOL> xstart = x [ <NUM_LIT:0> ] <EOL> hit = True <EOL> while hit : <EOL> hit = False <EOL> for j in range ( i + <NUM_LIT:1> , len ( a ) ) : <EOL> if j >= len ( a ) : <EOL> break <EOL> if a [ j ] [ <NUM_LIT:0> ] == xend : <EOL> hit = True <EOL> x . extend ( a [ j ] [ <NUM_LIT:1> : ] ) <EOL> xend = x [ - <NUM_LIT:1> ] <EOL> a . pop ( j ) <EOL> continue <EOL> if a [ j ] [ <NUM_LIT:0> ] == xstart : <EOL> hit = True <EOL> a [ i ] = reversed ( a [ j ] [ <NUM_LIT:1> : ] ) + x <EOL> x = a [ i ] <EOL> xstart = a [ i ] [ <NUM_LIT:0> ] <EOL> a . pop ( j ) <EOL> continue <EOL> if a [ j ] [ - <NUM_LIT:1> ] == xend : <EOL> hit = True <EOL> x . extend ( reversed ( a [ j ] [ : - <NUM_LIT:1> ] ) ) <EOL> xend = x [ - <NUM_LIT:1> ] <EOL> a . pop ( j ) <EOL> continue <EOL> if a [ j ] [ - <NUM_LIT:1> ] == xstart : <EOL> hit = True <EOL> a [ i ] = a [ j ] [ : - <NUM_LIT:1> ] + x <EOL> x = a [ i ] <EOL> xstart = x [ <NUM_LIT:0> ] <EOL> a . pop ( j ) <EOL> continue <EOL> i += <NUM_LIT:1> <EOL> return a <EOL> tids = ex . _tids <EOL> components = tids . components <EOL> dt = { } <EOL> for c in components : <EOL> if c in dt : <EOL> continue <EOL> index_types = c . index_types <EOL> a = [ ] <EOL> for i in range ( len ( index_types ) ) : <EOL> if index_types [ i ] is index_type : <EOL> a . append ( i ) <EOL> if len ( a ) > <NUM_LIT:2> : <EOL> raise ValueError ( '<STR_LIT>' % index_type ) <EOL> if len ( a ) == <NUM_LIT:2> : <EOL> dt [ c ] = a <EOL> dum = tids . dum <EOL> lines = [ ] <EOL> traces = [ ] <EOL> traces1 = [ ] <EOL> for p0 , p1 , c0 , c1 in dum : <EOL> if components [ c0 ] not in dt : <EOL> continue <EOL> if c0 == c1 : <EOL> traces . append ( [ c0 ] ) <EOL> continue <EOL> ta0 = dt [ components [ c0 ] ] <EOL> ta1 = dt [ components [ c1 ] ] <EOL> if p0 not in ta0 : <EOL> continue <EOL> if ta0 . index ( p0 ) == ta1 . index ( p1 ) : <EOL> raise NotImplementedError <EOL> ta0 = dt [ components [ c0 ] ] <EOL> b0 , b1 = ( c0 , c1 ) if p0 == ta0 [ <NUM_LIT:1> ] else ( c1 , c0 ) <EOL> lines1 = lines [ : ] <EOL> for line in lines : <EOL> if line [ - <NUM_LIT:1> ] == b0 : <EOL> if line [ <NUM_LIT:0> ] == b1 : <EOL> n = line . index ( min ( line ) ) <EOL> traces1 . append ( line ) <EOL> traces . append ( line [ n : ] + line [ : n ] ) <EOL> else : <EOL> line . append ( b1 ) <EOL> break <EOL> elif line [ <NUM_LIT:0> ] == b1 : <EOL> line . insert ( <NUM_LIT:0> , b0 ) <EOL> break <EOL> else : <EOL> lines1 . append ( [ b0 , b1 ] ) <EOL> lines = [ x for x in lines1 if x not in traces1 ] <EOL> lines = _join_lines ( lines ) <EOL> rest = [ ] <EOL> for line in lines : <EOL> for y in line : <EOL> rest . append ( y ) <EOL> for line in traces : <EOL> for y in line : <EOL> rest . append ( y ) <EOL> rest = [ x for x in range ( len ( components ) ) if x not in rest ] <EOL> return lines , traces , rest <EOL> def get_indices ( t ) : <EOL> if not isinstance ( t , TensExpr ) : <EOL> return ( ) <EOL> return t . get_indices ( ) <EOL> def get_tids ( t ) : <EOL> if isinstance ( t , TensExpr ) : <EOL> return t . _tids <EOL> return TIDS ( [ ] , [ ] , [ ] ) <EOL> def get_coeff ( t ) : <EOL> if isinstance ( t , Tensor ) : <EOL> return S . One <EOL> if isinstance ( t , TensMul ) : <EOL> return t . coeff <EOL> if isinstance ( t , TensExpr ) : <EOL> raise ValueError ( "<STR_LIT>" ) <EOL> return t <EOL> def contract_metric ( t , g ) : <EOL> if isinstance ( t , TensExpr ) : <EOL> return t . contract_metric ( g ) <EOL> return t <EOL> def perm2tensor ( t , g , canon_bp = False ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( t , TensExpr ) : <EOL> return t <EOL> new_tids = get_tids ( t ) . perm2tensor ( g , canon_bp ) <EOL> coeff = get_coeff ( t ) <EOL> if g [ - <NUM_LIT:1> ] != len ( g ) - <NUM_LIT:1> : <EOL> coeff = - coeff <EOL> res = TensMul . from_TIDS ( coeff , new_tids , is_canon_bp = canon_bp ) <EOL> return res <EOL> def substitute_indices ( t , * index_tuples ) : <EOL> """<STR_LIT>""" <EOL> if not isinstance ( t , TensExpr ) : <EOL> return t <EOL> free = t . free <EOL> free1 = [ ] <EOL> for j , ipos , cpos in free : <EOL> for i , v in index_tuples : <EOL> if i . _name == j . _name and i . _tensortype == j . _tensortype : <EOL> if i . _is_up == j . _is_up : <EOL> free1 . append ( ( v , ipos , cpos ) ) <EOL> else : <EOL> free1 . append ( ( - v , ipos , cpos ) ) <EOL> break <EOL> else : <EOL> free1 . append ( ( j , ipos , cpos ) ) <EOL> t = TensMul . from_data ( t . coeff , t . components , free1 , t . dum ) <EOL> return t </s>
