-
-
Notifications
You must be signed in to change notification settings - Fork 580
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
Adds limit(expr, v, a) syntax #39812
base: develop
Are you sure you want to change the base?
Adds limit(expr, v, a) syntax #39812
Conversation
Hello, @vincentmacri, @nbruin,
Thanks, |
src/sage/calculus/calculus.py
Outdated
@@ -429,13 +429,16 @@ | |||
from sage.misc.latex import latex | |||
from sage.misc.parser import Parser, LookupNameMaker | |||
from sage.structure.element import Expression | |||
from sage.symbolic.expression import Expression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why this import? It shadows the one above. Figure out which one you need (why not the one that was already there?) and remove the other.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
yes you right, the second import just overwrites the 1st one, made the necessary changes
Thanks,
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
sage.structure.element.Expression and sage.symbolic.expression.Expression aren't the same. Do you have a reason to change which one is imported here? There was probably a good reason why the code here originally imported the abstract base class rather than the concrete one.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs addressing
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
okay, i guess i probably get this now, since the limit function is operating on symbolic expressions (converted via SR), so the abstract base class is probably sufficient, am i right?
28b5916
to
f468ab1
Compare
I'll leave commenting on the code itself to @nbruin since he wrote the first draft of this. All I'll add is that I find the usage of "new syntax" versus "old syntax" in the docstrings a bit confusing. It makes it sounds like we plan to deprecate the old syntax, which I don't think we do plan on doing (or should plan on doing unless there's a good reason). I'm not sure what terms would be better. Maybe just show examples of both without referring to one as being new or old, and just mention in the examples why the syntax you're adding here is preferred/needed in some situations. For example, when I added additional functionality to the |
Hello Vincent, Thanks for your feedback on the documentation. I also think that labeling the syntaxes as "new" and "old" maybe could imply we are deprecating x=a, which isn’t the case—both syntaxes are meant to stay supported, as of now unless( as you said) ...... I just wanted to ask that what should be next course of action ? I am thinking to include something like this in the docstrings: Is this the right way of representation? Thanks, |
No, just be neutral: There are two ways of invoking limit. One can write |
05b3f07
to
e806bf7
Compare
I have made the necessary changes to the doctests and added examples where necessary, can you please review it. |
@nbruin any other feedback regarding the code? |
src/sage/calculus/calculus.py
Outdated
is_getitem = hasattr(v.operator(), '__name__') and v.operator().__name__ == '__getitem__' | ||
if not (is_getitem and v.operands()): | ||
# If it’s not an indexed variable, checking if it’s numeric | ||
if v.is_numeric(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
certainly not necessary to further differentiate if you know you're going to raise an error
src/sage/calculus/calculus.py
Outdated
if not (is_getitem and v.operands()): | ||
# If it’s not an indexed variable, checking if it’s numeric | ||
if v.is_numeric(): | ||
raise TypeError(f"Limit variable must be a variable, not a constant number: {v}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just raise a more generic message here. You don't need to give the value that is causing the error. That's in the backtrace.
src/sage/calculus/calculus.py
Outdated
try: | ||
a = SR(a) | ||
except TypeError: | ||
raise TypeError(f"Cannot convert limit point to symbolic ring: {a}") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
just let SR(a)
raise the error.
@@ -1498,38 +1699,53 @@ def mma_free_limit(expression, v, a, dir=None): | |||
|
|||
EXAMPLES:: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
My expertise does not extend to mma_free_limit
so I cannot review that code.
e806bf7
to
40a04c1
Compare
I've applied the suggested changes from the latest review.
Everything has now been updated as suggested. Do you have any further feedback? |
@vincentmacri any other feedback from your side ,? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Please make sure you address all concerns. I think I have reflagged issues that I flagged before and that did not receive a response.
If you disagree with my assessment on any one of the items you can respond with your reasons and then we can take it from there.
src/sage/calculus/calculus.py
Outdated
@@ -429,13 +429,16 @@ | |||
from sage.misc.latex import latex | |||
from sage.misc.parser import Parser, LookupNameMaker | |||
from sage.structure.element import Expression | |||
from sage.symbolic.expression import Expression |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This still needs addressing
src/sage/calculus/calculus.py
Outdated
|
||
if len(args) == 2: # Syntax: limit(ex, v, a, ...) | ||
if kwargs: # Cannot mix positional v, a with keyword args | ||
raise ValueError(f"Use either limit(expr, v, a, ...) or limit(expr, v=a, ...) syntax. " |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Error message should be an uncapitalized phrase describing the problem; not advice. So:
'''
Cannot mix positional specification of limit variable and point with keyword variable arguments
'''
No need for arguments in message: those can be obtained from traceback.
I don't think advice of the form Use either ... or ...
is necessary here. Any advice would go after the primary error message.
src/sage/calculus/calculus.py
Outdated
elif len(args) == 0: # Potential syntax: limit(ex, v=a, ...) or limit(ex) | ||
if len(kwargs) == 1: | ||
k, = kwargs.keys() | ||
if not isinstance(k, str): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this test is not required:
sage: def f(*args,**kwargs): return args, kwargs
sage: f(**{10:1})
TypeError: keywords must be strings
src/sage/calculus/calculus.py
Outdated
k, = kwargs.keys() | ||
if not isinstance(k, str): | ||
raise ValueError(f"Invalid variable specification in keyword argument: {k} (must be a string)") | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to guard with try. Just let error propagate.
src/sage/calculus/calculus.py
Outdated
|
||
# Ensuring v is a symbolic expression | ||
if not isinstance(v, Expression): | ||
try: |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no need to guard with "try". Just let it raise on error by itself
src/sage/calculus/calculus.py
Outdated
# Ensuring v is a symbolic expression | ||
if not isinstance(v, Expression): | ||
try: | ||
v = SR(v) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
create what you need: use
v=SR.symbol(v)
instead.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@nbruin
This approach is creating an Error:
For the call
limit(x^2 + 5, 5, 10):
v = 5 is an integer, not an instance of Expression
SR.symbol(v) is called with v = 5, but SR.symbol() expects a string to create a symbolic variable. Passing integer like 5 causes a
TypeError: expected string or bytes-like object, got 'sage.rings.integer.Integer'.
I think this error is occuring because the code assumes v can be converted to a symbolic variable directly, but a constant like 5 isn’t a valid limit variable, limits must be taken with respect to a variable (e.g., x), not a constant,
its working fine with this approach:
# Ensuring v is a symbolic expression and a valid limit variable
if not isinstance(v, Expression):
v = SR(v)
if not v.is_symbol():
raise TypeError("limit variable must be a variable, not a constant")
src/sage/calculus/calculus.py
Outdated
v = var(k) | ||
a = argv[k] | ||
# Check if v is a valid limit variable | ||
if not v.is_symbol() and v.is_constant(): |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
you will have a symbol here with the change above, so no reason to check
Implements the limit(expr, variable, value) positional syntax to allow limits with respect to indexed variables or other variables not usable as keyword arguments. Also, Updates documentation and adds doctests for the new syntax and associated error handling. Ensures code coverage for the new argument parsing. Fixes sagemath#38761
40a04c1
to
8858361
Compare
@nbruin does everything looks good now? |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
OK that looks fine now. I did find it painful in the review process to not have the comments and markings from the previous review available. Part of that might be github's interface. Another component is that you squash your commits in a forced push, destroying history. It might be better to just make successive commits. If you really want to squash before merge, you could squash at the very end to make a branch with a different (more concise) history but with the same effect on the tree.
if not isinstance(v, Expression): | ||
v = SR(v) | ||
if not v.is_symbol(): | ||
raise TypeError("limit variable must be a variable, not a constant") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Yes, that should be a satisfactory solution
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
cool
@nbruin , thanks so much for reviewing the PR thoroughly and providing detailed feedback. Regarding the comment on squashing commits with a forced push: I initially thought that working alone on the branch wouldn't be an issue, but I see how it complicates code review. I'll adjust my approach and make successive commits going ahead Thanks again! |
Implemented the limit(expr, variable, value) positional syntax to allow limits with respect to indexed variables or other variables not usable as keyword arguments.
Also, Updated the documentation and added doctests for the new syntax and associated error handling. Ensuring code coverage for the new argument parsing.
Fixes #38761 by allowing limits to be taken with respect to indexed variables like x[0] or other symbolic expressions not usable as keyword arguments.
While testing, the tests passed except the optional fricas ones that were failing before too.
📝 Checklist
⌛ Dependencies
Got the idea and direction of fixing the issue and the link to the relevant conversations in the given PR: #38780