Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement call method for elements in CDGA's #36329

Merged
merged 12 commits into from
Mar 25, 2024
77 changes: 77 additions & 0 deletions src/sage/algebras/commutative_dga.py
Original file line number Diff line number Diff line change
Expand Up @@ -1562,6 +1562,83 @@ def dict(self):
"""
return self.lift().dict()

def __call__(self, *values, **kwargs):
r"""
Evaluate the reduced expression of this element at ``x``, where ``x``
is either the tuple of values to evaluate in, a dictionary indicating
to which value is each generator evaluated, or keywords giving
the value to which generators should be evaluated.

INPUT:

- ``values`` -- (optional) either the values in which the variables
will be evaluated or a dictionary

OUTPUT:

this element evaluated at the given values

EXAMPLES::

sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
sage: f = x*y - 5*y*z + 7*x*y^2*z^3*t
sage: f(3, y, x^2, x*z)
3*y
sage: f(x=3)
21*y^2*z^3*t - 5*y*z + 3*y
sage: f({x:3, z:x^2})
3*y

If the wrong number of values is provided, it results in an error::

sage: f(3, 5, y)
Traceback (most recent call last):
...
ValueError: number of arguments does not match number of variables in parent

It is also possible to use keywords like this::

sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
sage: f = x*y - 5*y*z + 7*x*y^2*z^3*t
sage: f(x=3)
21*y^2*z^3*t - 5*y*z + 3*y
sage: f(t=x,y=z)
-5*z^2 + x*z

If both a dictionary and keywords are used, only the dictionary is
considered::

sage: A.<x,y,z,t> = GradedCommutativeAlgebra(QQ, degrees=(1, 2, 2, 3))
sage: f = x*y - 5*y*z + 7*x*y^2*z^3*t
sage: f({x:1}, t=x,y=z)
7*y^2*z^3*t - 5*y*z + y
"""
gens = self.parent().gens()
images = list(gens)
if values and not isinstance(values[0], dict):
for (i, p) in enumerate(values):
images[i] = p
if len(values) == 1 and isinstance(values[0], dict):
images = list(gens)
for (i, g) in enumerate(gens):
if g in values[0]:
images[i] = values[0][g]
elif len(values) == len(gens):
images = list(values)
elif values:
raise ValueError("number of arguments does not match number of variables in parent")
Comment on lines +1628 to +1629
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By this point, you have not used/parsed the keywords. So if someone passes in a mixture, then this might give a false result. In general, you probably should at least document the behavior and what you expect to have happen.

else:
images = list(gens)
for (i, g) in enumerate(gens):
gstr = str(g)
if gstr in kwargs:
images[i] = kwargs[gstr]
res = 0
for (m, c) in self.dict().items():
term = prod((gen**y for (y, gen) in zip(m, images)), c)
res += term
return res

def basis_coefficients(self, total=False):
"""
Return the coefficients of this homogeneous element with
Expand Down
Loading