Source code for gana.operators.sigma
"""Operators"""
from __future__ import annotations
# from itertools import islice
from typing import TYPE_CHECKING
from ..sets.cases import Elem, FCase
from ..sets.function import F
if TYPE_CHECKING:
from ..sets.index import I
from ..sets.variable import V
[docs]
def sigma(variable: V, over: I = None, position: int = None) -> F:
"""
Summation without recursion, also allows better printing
:param variable: variable set
:type variable: V
:param over: over what index
:type over: I | None
:param position: position of the index in the variable indices. Defaults to None.
:type position: int | None
:returns: summed up function
:rtype: F
"""
def _determine_index(over, position):
if over:
length = len(over)
if not position:
position = variable.index.index(over)
# Precompute slices
before = variable.index[:position]
after = variable.index[position + 1 :]
# Build variables
_variables = [
variable(*before, _index, *after, make_new=True) for _index in over
]
else:
# sum over the entire set
_variables = variable._
length = len(variable)
position = None
over = variable.index
return _variables, over, length, position
def _birth_parent(variable, _variables, over, position, length):
_f = F()
_f.case = FCase.SUM
_f.issumhow = (variable.copy(), over, position)
_f.variables = _variables
_f.index = tuple(v.index for v in _f.variables)
_f.one = _f
_f.one_type = Elem.F
_f.give_name()
_f.rhs_thetas = []
length_var = len(_variables[0])
keys = list(zip(*(v.map for v in _f.variables)))
_f.A = [[1] * length for _ in range(length_var)]
return _f, length_var, keys
def _birth_children(f, length_var, keys):
for n in range(length_var):
# make the child functions
f_child = F()
f_child.variables = [v[n] for v in f.variables]
f_child.P = [v.n for v in f_child.variables]
f_child.A = [1] * length
key = keys[n]
f_child.issumhow = (variable[length * n], over, position)
f_child.parent = f
f_child.case = FCase.SUM
f_child.rhs_thetas = []
f.P.append(f_child.P)
f_child.give_name()
f_child._ = [f_child]
f._.append(f_child)
f.map[key] = f_child
f_child.map[key] = f_child
f_child.parent = f
f_child.index = key
f_child.one = f_child
f_child.one_type = Elem.F
return f
_variables, over, length, position = _determine_index(over, position)
if length == 2:
# short-circuit for length 2
# just v_0 + v_1
return _variables[0] + _variables[1]
f, length_var, keys = _birth_parent(variable, _variables, over, position, length)
return _birth_children(f, length_var, keys)