diff --git a/src/sage/tensor/modules/comp.py b/src/sage/tensor/modules/comp.py index 2850069cb96..5fa035d5596 100644 --- a/src/sage/tensor/modules/comp.py +++ b/src/sage/tensor/modules/comp.py @@ -242,12 +242,13 @@ # the License, or (at your option) any later version. # https://www.gnu.org/licenses/ # **************************************************************************** +from operator import itemgetter +from typing import Iterator -from sage.structure.sage_object import SageObject -from sage.rings.integer import Integer from sage.parallel.decorate import parallel from sage.parallel.parallelism import Parallelism -from operator import itemgetter +from sage.rings.integer import Integer +from sage.structure.sage_object import SageObject class Components(SageObject): @@ -484,7 +485,7 @@ class Components(SageObject): True """ def __init__(self, ring, frame, nb_indices, start_index=0, - output_formatter=None): + output_formatter=None) -> None: r""" TESTS:: @@ -500,10 +501,11 @@ def __init__(self, ring, frame, nb_indices, start_index=0, self._dim = len(frame) self._sindex = start_index self._output_formatter = output_formatter - self._comp = {} # the dictionary of components, with the index tuples - # as keys - def _repr_(self): + # the dictionary of components, with the index tuples as keys + self._comp = {} + + def _repr_(self) -> str: r""" Return a string representation of ``self``. @@ -542,9 +544,9 @@ def _repr_(self): description += suffix return description - def _repr_symmetry(self): + def _repr_symmetry(self) -> tuple[str, str]: r""" - Return a prefix and a suffix string describing the symmetry of ``self``. + Return prefix and suffix strings describing the symmetry of ``self``. EXAMPLES:: @@ -606,11 +608,13 @@ def copy(self): result._comp[ind] = val return result - def _del_zeros(self): + def _del_zeros(self) -> None: r""" Delete all the zeros in the dictionary :attr:`_comp`. - NB: The use case of this method must be rare because zeros are not + .. NOTE:: + + The use case of this method must be rare because zeros are not stored in :attr:`_comp`. EXAMPLES:: @@ -624,14 +628,11 @@ def _del_zeros(self): """ # The zeros are first searched; they are deleted in a second stage, to # avoid changing the dictionary while it is read - zeros = [] - for ind, value in self._comp.items(): - if value == 0: - zeros.append(ind) + zeros = [ind for ind, value in self._comp.items() if value == 0] for ind in zeros: del self._comp[ind] - def _check_indices(self, indices): + def _check_indices(self, indices) -> tuple: r""" Check the validity of a list of indices and returns a tuple from it. @@ -722,12 +723,12 @@ def __getitem__(self, args): [ 0 0 0] """ no_format = self._output_formatter is None - format_type = None # default value, possibly redefined below + format_type = None # default value, possibly redefined below if isinstance(args, list): # case of [[...]] syntax no_format = True if isinstance(args[0], slice): indices = args[0] - elif isinstance(args[0], (tuple, list)): # to ensure equivalence between + elif isinstance(args[0], (tuple, list)): # to ensure equivalence between indices = args[0] # [[(i,j,...)]] or [[[i,j,...]]] and [[i,j,...]] else: indices = tuple(args) @@ -829,8 +830,8 @@ def _get_list(self, ind_slice, no_format=True, format_type=None): else: return [self[i, format_type] for i in range(start, stop)] if ind_slice.start is not None or ind_slice.stop is not None: - raise NotImplementedError("function [start:stop] not " + - "implemented for components with {} indices".format(self._nid)) + raise NotImplementedError("function [start:stop] not implemented " + + f"for components with {self._nid} indices") resu = [self._gen_list([i], no_format, format_type) for i in range(si, nsi)] if self._nid == 2: @@ -874,7 +875,7 @@ def _gen_list(self, ind, no_format=True, format_type=None): return [self._gen_list(ind + [i], no_format, format_type) for i in range(si, nsi)] - def __setitem__(self, args, value): + def __setitem__(self, args, value) -> None: r""" Set the component corresponding to the given indices. @@ -906,11 +907,11 @@ def __setitem__(self, args, value): [3 4 5] [6 7 8] """ - format_type = None # default value, possibly redefined below + format_type = None # default value, possibly redefined below if isinstance(args, list): # case of [[...]] syntax if isinstance(args[0], slice): indices = args[0] - elif isinstance(args[0], (tuple, list)): # to ensure equivalence between + elif isinstance(args[0], (tuple, list)): # to ensure equivalence between indices = args[0] # [[(i,j,...)]] or [[[i,j,...]]] and [[i,j,...]] else: indices = tuple(args) @@ -954,7 +955,7 @@ def __setitem__(self, args, value): # element of the algebra's base ring, cf. the discussion at # https://github.com/sagemath/sage/issues/16054 - def _set_list(self, ind_slice, format_type, values): + def _set_list(self, ind_slice, format_type, values) -> None: r""" Set the components from a list. @@ -1033,7 +1034,7 @@ def _set_value_list(self, ind, format_type, val): for i in range(si, nsi): self._set_value_list(ind + [i], format_type, val[i-si]) - def items(self): + def items(self) -> Iterator: r""" Return an iterable of ``(indices, value)`` elements. @@ -1265,8 +1266,8 @@ def display(self, symbol, latex_symbol=None, index_positions=None, zero_value = val == 0 if not zero_value or not only_nonzero: indices = '' # text indices - d_indices = '' # LaTeX down indices - u_indices = '' # LaTeX up indices + d_indices = '' # LaTeX down indices + u_indices = '' # LaTeX up indices previous = None # position of previous index for k in range(self._nid): i = ind[k] - si @@ -1359,7 +1360,7 @@ def swap_adjacent_indices(self, pos1, pos2, pos3): # called and not the present function. return result - def is_zero(self): + def is_zero(self) -> bool: r""" Return ``True`` if all the components are zero and ``False`` otherwise. @@ -1400,13 +1401,13 @@ def is_zero(self): if not self._comp: return True - #!# What follows could be skipped since _comp should not contain + # What follows could be skipped since _comp should not contain # any zero value # In other words, the full method should be # return self.comp == {} return all(val == 0 for val in self._comp.values()) - def __eq__(self, other): + def __eq__(self, other) -> bool: r""" Comparison (equality) operator. @@ -1436,12 +1437,12 @@ def __eq__(self, other): sage: c.__eq__(v) False """ - if isinstance(other, (int, Integer)): # other is 0 + if isinstance(other, (int, Integer)): # other is 0 if other == 0: return self.is_zero() else: raise TypeError("cannot compare a set of components to a number") - else: # other is another Components + else: # other is another Components if not isinstance(other, Components): raise TypeError("an instance of Components is expected") if other._frame != self._frame: @@ -1454,7 +1455,7 @@ def __eq__(self, other): return False return (self - other).is_zero() - def __ne__(self, other): + def __ne__(self, other) -> bool: r""" Non-equality operator. @@ -1817,14 +1818,14 @@ def __mul__(self, other): # list of input parameters: listParalInput = [(self, ind_part) for ind_part in local_list] - @parallel(p_iter='multiprocessing',ncpus=nproc) + @parallel(p_iter='multiprocessing', ncpus=nproc) def paral_mul(a, local_list_ind): partial = [] for ind in local_list_ind: partial.append([ind, a[[ind[0]]]*a[[ind[1]]]]) return partial - for ii,val in paral_mul(listParalInput): + for ii, val in paral_mul(listParalInput): for jj in val: result[[jj[0]]] = jj[1] else: @@ -1856,7 +1857,7 @@ def paral_mul(a, b, local_list_ind): partial.append([ind + ind_o, a._comp[ind]*val_o]) return partial - for ii,val in paral_mul(listParalInput): + for ii, val in paral_mul(listParalInput): for jj in val: result._comp[jj[0]] = jj[1] else: @@ -1991,7 +1992,7 @@ def trace(self, pos1, pos2): if self._nid == 2: res = 0 for i in range(si, nsi): - res += self[[i,i]] + res += self[[i, i]] return res else: # More than 2 indices @@ -2228,8 +2229,8 @@ def compprod(a, b): # (None = the position is involved in a contraction and therefore # does not appear in the final result) # - pos_s = [None for i in range(self._nid)] # initialization - pos_o = [None for i in range(other._nid)] # initialization + pos_s = [None for i in range(self._nid)] # initialization + pos_o = [None for i in range(other._nid)] # initialization shift = 0 for pos in range(self._nid): for contract_pair in contractions: @@ -2250,8 +2251,8 @@ def compprod(a, b): # # Determination of the symmetries of the result # - max_len_sym = 0 # maximum length of symmetries in the result - max_len_antisym = 0 # maximum length of antisymmetries in the result + max_len_sym = 0 # maximum length of symmetries in the result + max_len_antisym = 0 # maximum length of antisymmetries in the result if res_nid > 1: # no need to search for symmetries if res_nid == 1 if isinstance(self, CompWithSym): s_sym = self._sym @@ -2300,7 +2301,7 @@ def compprod(a, b): res_antisym.append(r_isym) max_len_antisym = max(max_len_antisym, len(r_isym)) # - # Construction of the result object in view of the remaining symmetries: + # Construction of the result object in view of the remaining symmetries # if max_len_sym == 0 and max_len_antisym == 0: res = Components(self._ring, self._frame, res_nid, @@ -2348,8 +2349,8 @@ def make_Contraction(this, other, local_list, rev_s, rev_o, shift_o, contractions, comp_for_contr): local_res = [] for ind in local_list: - ind_s = [None for i in range(this._nid)] # initialization - ind_o = [None for i in range(other._nid)] # initialization + ind_s = [None for _ in range(this._nid)] # initialization + ind_o = [None for _ in range(other._nid)] # initialization for i, pos in enumerate(rev_s): ind_s[pos] = ind[i] for i, pos in enumerate(rev_o): @@ -2370,8 +2371,8 @@ def make_Contraction(this, other, local_list, rev_s, rev_o, else: # sequential computation for ind in res.non_redundant_index_generator(): - ind_s = [None for i in range(self._nid)] # initialization - ind_o = [None for i in range(other._nid)] # initialization + ind_s = [None for _ in range(self._nid)] # initialization + ind_o = [None for _ in range(other._nid)] # initialization for i, pos in enumerate(rev_s): ind_s[pos] = ind[i] for i, pos in enumerate(rev_o): @@ -2387,7 +2388,7 @@ def make_Contraction(this, other, local_list, rev_s, rev_o, return res - def index_generator(self): + def index_generator(self) -> Iterator: r""" Generator of indices. @@ -2415,16 +2416,16 @@ def index_generator(self): ind = [si for k in range(self._nid)] while True: yield tuple(ind) - for pos in range(self._nid-1,-1,-1): + for pos in range(self._nid-1, -1, -1): if ind[pos] != imax: ind[pos] += 1 break elif pos != 0: ind[pos] = si else: - return # end point reached + return # end point reached - def non_redundant_index_generator(self): + def non_redundant_index_generator(self) -> Iterator: r""" Generator of non redundant indices. @@ -2767,11 +2768,11 @@ def _matrix_(self): raise ValueError("the set of components must have 2 indices") si = self._sindex nsi = self._dim + si - tab = [[self[[i,j]] for j in range(si, nsi)] for i in range(si, nsi)] + tab = [[self[[i, j]] for j in range(si, nsi)] for i in range(si, nsi)] return matrix(tab) -# ***************************************************************************** +# **************************************************************************** class CompWithSym(Components): r""" @@ -2971,7 +2972,7 @@ class CompWithSym(Components): True """ def __init__(self, ring, frame, nb_indices, start_index=0, - output_formatter=None, sym=None, antisym=None): + output_formatter=None, sym=None, antisym=None) -> None: r""" TESTS:: @@ -3080,9 +3081,9 @@ def _canonicalize_sym_antisym(nb_indices, sym=None, antisym=None): "index position appears more than once") return result_sym, result_antisym - def _repr_symmetry(self): + def _repr_symmetry(self) -> tuple[str, str]: r""" - Return a prefix and a suffix string describing the symmetry of ``self``. + Return prefix and suffix strings describing the symmetry of ``self``. EXAMPLES:: @@ -3117,9 +3118,9 @@ def _new_instance(self): 4-indices components w.r.t. [1, 2, 3], with symmetry on the index positions (0, 1) """ return CompWithSym(self._ring, self._frame, self._nid, self._sindex, - self._output_formatter, self._sym, self._antisym) + self._output_formatter, self._sym, self._antisym) - def _ordered_indices(self, indices): + def _ordered_indices(self, indices) -> tuple: r""" Given a set of indices, return a set of indices with the indices at the positions of symmetries or antisymmetries being ordered, @@ -3247,14 +3248,14 @@ def __getitem__(self, args): return self._get_list(indices, no_format, format_type) else: sign, ind = self._ordered_indices(indices) - if (sign == 0) or (ind not in self._comp): # the value is zero: + if sign == 0 or ind not in self._comp: # the value is zero: if no_format: return self._ring.zero() elif format_type is None: return self._output_formatter(self._ring.zero()) else: return self._output_formatter(self._ring.zero(), - format_type) + format_type) else: # nonzero value if no_format: if sign == 1: @@ -3269,12 +3270,12 @@ def __getitem__(self, args): else: if sign == 1: return self._output_formatter( - self._comp[ind], format_type) + self._comp[ind], format_type) else: # sign = -1 return self._output_formatter( - -self._comp[ind], format_type) + -self._comp[ind], format_type) - def __setitem__(self, args, value): + def __setitem__(self, args, value) -> None: r""" Set the component corresponding to the given indices. @@ -3578,7 +3579,7 @@ def paral_sum(a, b, local_list_ind): partial.append([ind, a[[ind]]+b[[ind]]]) return partial - for ii,val in paral_sum(listParalInput): + for ii, val in paral_sum(listParalInput): for jj in val: result[[jj[0]]] = jj[1] else: @@ -3682,7 +3683,7 @@ def paral_mul(a, b, local_list_ind): partial.append([ind + ind_o, a._comp[ind]*val_o]) return partial - for ii,val in paral_mul(listParalInput): + for ii, val in paral_mul(listParalInput): for jj in val: result._comp[jj[0]] = jj[1] else: @@ -3817,7 +3818,7 @@ def trace(self, pos1, pos2): if self._nid == 2: res = 0 for i in range(si, nsi): - res += self[[i,i]] + res += self[[i, i]] return res else: # More than 2 indices @@ -3901,7 +3902,7 @@ def trace(self, pos1, pos2): result[[ind_res]] = res return result - def non_redundant_index_generator(self): + def non_redundant_index_generator(self) -> Iterator: r""" Generator of indices, with only ordered indices in case of symmetries, so that only non-redundant indices are generated. @@ -3989,17 +3990,17 @@ def non_redundant_index_generator(self): return ind[pos] = ind[isym[k-1]] + 1 if not any(pos in isym for isym in sym) and not any(pos in isym for isym in antisym): - sym.append([pos]) # treat non-symmetrized indices as being symmetrized with themselves + sym.append([pos]) # treat non-symmetrized indices as being symmetrized with themselves while True: yield tuple(ind) - step_finished = False # each step generates a new index - for i in range(len(sym)-1,-1,-1): + step_finished = False # each step generates a new index + for i in range(len(sym)-1, -1, -1): # start with symmetrized indices, loop until we find # an index which we can increase without going over # the maximum isym = sym[i] if not step_finished: - for k in range(len(isym)-1,-1,-1): + for k in range(len(isym)-1, -1, -1): if ind[isym[k]] != imax: # we have found an index which we can # increase; adjust other indices in the @@ -4014,7 +4015,7 @@ def non_redundant_index_generator(self): # to reset it ind[isym[k]] = si if not step_finished and i == 0 and len(antisym) == 0: - # we went through all indices and didn't find one + # we went through all indices and did not find one # which we can increase, thus we have generated # all indices return @@ -4035,7 +4036,7 @@ def non_redundant_index_generator(self): # reset the index ind[isym[k]] = si + k if not step_finished and i == 0: - return # end point reach + return # end point reach def symmetrize(self, *pos): r""" @@ -4606,7 +4607,7 @@ def antisymmetrize(self, *pos): return result -# ***************************************************************************** +# **************************************************************************** class CompFullySym(CompWithSym): r""" @@ -4737,7 +4738,7 @@ class CompFullySym(CompWithSym): True """ def __init__(self, ring, frame, nb_indices, start_index=0, - output_formatter=None): + output_formatter=None) -> None: r""" TESTS:: @@ -4748,9 +4749,9 @@ def __init__(self, ring, frame, nb_indices, start_index=0, CompWithSym.__init__(self, ring, frame, nb_indices, start_index, output_formatter, sym=range(nb_indices)) - def _repr_symmetry(self): + def _repr_symmetry(self) -> tuple[str, str]: r""" - Return a prefix and a suffix string describing the symmetry of ``self``. + Return prefix and suffix strings describing the symmetry of ``self``. EXAMPLES:: @@ -4849,9 +4850,9 @@ def __getitem__(self, args): return self._output_formatter(self._ring.zero()) else: return self._output_formatter(self._ring.zero(), - format_type) + format_type) - def __setitem__(self, args, value): + def __setitem__(self, args, value) -> None: r""" Set the component corresponding to the given indices. @@ -5038,7 +5039,7 @@ def paral_sum(a, b, local_list_ind): partial.append([ind, a[[ind]]+b[[ind]]]) return partial - for ii,val in paral_sum(listParalInput): + for ii, val in paral_sum(listParalInput): for jj in val: result[[jj[0]]] = jj[1] @@ -5051,7 +5052,7 @@ def paral_sum(a, b, local_list_ind): return CompWithSym.__add__(self, other) -# ***************************************************************************** +# **************************************************************************** class CompFullyAntiSym(CompWithSym): r""" @@ -5187,7 +5188,7 @@ class CompFullyAntiSym(CompWithSym): True """ def __init__(self, ring, frame, nb_indices, start_index=0, - output_formatter=None): + output_formatter=None) -> None: r""" TESTS:: @@ -5198,9 +5199,9 @@ def __init__(self, ring, frame, nb_indices, start_index=0, CompWithSym.__init__(self, ring, frame, nb_indices, start_index, output_formatter, antisym=range(nb_indices)) - def _repr_symmetry(self): + def _repr_symmetry(self) -> tuple[str, str]: r""" - Return a prefix and a suffix string describing the symmetry of ``self``. + Return prefix and suffix strings describing the symmetry of ``self``. EXAMPLES:: @@ -5223,8 +5224,8 @@ def _new_instance(self): sage: c._new_instance() Fully antisymmetric 4-indices components w.r.t. (1, 2, 3) """ - return CompFullyAntiSym(self._ring, self._frame, self._nid, self._sindex, - self._output_formatter) + return CompFullyAntiSym(self._ring, self._frame, self._nid, + self._sindex, self._output_formatter) def __add__(self, other): r""" @@ -5235,7 +5236,9 @@ def __add__(self, other): - ``other`` -- components of the same number of indices and defined on the same frame as ``self`` - OUTPUT: components resulting from the addition of ``self`` and ``other`` + OUTPUT: + + components resulting from the addition of ``self`` and ``other`` EXAMPLES:: @@ -5488,7 +5491,7 @@ def interior_product(self, other): res[[ind]] = factorial_s*sm return res -# ***************************************************************************** +# **************************************************************************** class KroneckerDelta(CompFullySym): @@ -5548,7 +5551,8 @@ class KroneckerDelta(CompFullySym): sage: d[:] [['1', '0', '0'], ['0', '1', '0'], ['0', '0', '1']] """ - def __init__(self, ring, frame, start_index=0, output_formatter=None): + def __init__(self, ring, frame, start_index=0, + output_formatter=None) -> None: r""" TESTS:: @@ -5559,9 +5563,9 @@ def __init__(self, ring, frame, start_index=0, output_formatter=None): CompFullySym.__init__(self, ring, frame, 2, start_index, output_formatter) for i in range(self._sindex, self._dim + self._sindex): - self._comp[(i,i)] = self._ring(1) + self._comp[(i, i)] = self._ring(1) - def _repr_(self): + def _repr_(self) -> str: r""" Return a string representation of ``self``.