-
-
Notifications
You must be signed in to change notification settings - Fork 629
Adds limit(expr, v, a) syntax #39812
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
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.
src/sage/calculus/calculus.py
Outdated
@@ -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
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.
@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! |
8858361
to
e74d80f
Compare
hello, @roed314 can you review and run the workflows if possible, |
Done. It still looks like there's something strange going on with force pushes (if you look at the Files Changed you'll see a bunch of changes that are just 10.6 vs 10.6.rc1). |
Documentation preview for this PR (built with commit ec6e145; changes) is ready! 🎉 |
src/sage/calculus/calculus.py
Outdated
The positional `limit(expr, v, a)` syntax is particularly useful when | ||
the limit variable `v` is an indexed variable or another expression | ||
that cannot be used as a keyword argument (fixes :issue:`38761`):: |
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.
The positional `limit(expr, v, a)` syntax is particularly useful when | |
the limit variable `v` is an indexed variable or another expression | |
that cannot be used as a keyword argument (fixes :issue:`38761`):: | |
The positional ``limit(expr, v, a)`` syntax is particularly useful | |
when the limit variable ``v`` is an indexed variable or another | |
expression that cannot be used as a keyword argument | |
(fixes :issue:`38761`):: |
When referring to code, typeset it with two ticks (code
) rather than one tick (LaTeX
).
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 can see here how the formatting will look in the documentation: https://doc-pr-39812--sagemath.netlify.app/html/en/reference/calculus/sage/calculus/calculus#sage.calculus.calculus.limit
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.
Minor formatting fix
src/sage/calculus/calculus.py
Outdated
""" | ||
from sage.interfaces.mathematica import request_wolfram_alpha, parse_moutput_from_json, symbolic_expression_from_mathematica_string |
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.
did you test this code? I would expect you can't just remove an import and expect the code will still run. I can't find another place where these functions are imported. Do you actually have a reason to touch the mma_free_limit
code in this ticket? It doesn't seem to have anything to do with the topic of the ticket.
The doc build error is separate from this issue, as far as I can tell.
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.
I do have the same question as you as to why this code was removed (I'm guessing an accident). But I tested it and putting this back doesn't seem to fix the issue with giac.
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.
regarding the mma_free_limit
i tried to kind of optimize it, now it seems it was not needed/ also have some issues in implementing, will again look into it and if required will revert to the original implementation,
also,
I can't find another place where these functions are imported
i saw them here: src/sage/symbolic/integration/external.py,
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.
it goes a little further than "some issues". You made the code non-functional in several places that are immediately obvious when you test the code. By removing the import you made sure that the code would eventually run into an undefined identifier, and by changing _mathematica_init_
to _mathematica_
you ensured that on systems where mathematica isn't available you wouldn't even get to that point. Such a level of carelessness makes me worried about any code you're submitting.
If you want to "optimize" some code you should at the very least check that the optimized code is still functional!
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.
one can/should get a free copy of console Mathematica, a.k.a. "WolframScript" for testing these things. a soft link from wolframscript to math will need to be made in a place in your PATH.
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 routine queries wolfram alpha. That's why it's labelled "optional - internet". It's undoubtedly possible to interface with yet another wolfram authored tool, but that's not what this routine is for at the moment. There is no need for additional software to test this routine. Just a network connection.
I have no idea why giac broke here, nothing you did should be causing this issue as far as I can tell. My best guess is some kind of circular import nonsense. I think I have a possible workaround though. Right now the code calls giac by (attempting to) import |
src/sage/calculus/calculus.py
Outdated
a = a._mathematica_init_() | ||
|
||
try: | ||
math_expr = expression._mathematica_().name() |
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 whole routine needs to be reverted.
On a system that does not have mathematica installed, _mathematica_()
raises an error, whereas _mathematica_init_()
doesn't. This routine should be making a web request. It should not be trying to run mathematica locally.
I'm pretty sure that all edits made to this routine are erroneous. They are certainly outside the stated scope of the pull request. If there is a change to be made to mma_free_limit
it needs to happen on a different pull request.
thanks for spotting the error, looking into it now. |
The |
But I agree with @nbruin, leave the changes to |
I think the error with @orlitzky do you have any ideas? Does this code need to change to use the giac interface instead of the giac lib? |
I think instead of |
b42232e
to
dba0423
Compare
doing this only eliminates the giac failure, but the ones related to fricas still exists, my bad, I by mistake force pushed T_T |
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.
Looks good, one minor nitpick that you can take or leave.
Co-authored-by: Vincent Macri <[email protected]>
@vincentmacri this is so strange, before incorporating your suggestion all the CIs successfully passed, now one of the CIs is failing, and i don't think that this is anything related to your suggestion that i committed? could there be any problem with the CIs ? do we need to run them again? |
I think it is a problem with the CI. You can try running that test locally with |
This reverts commit 182ece1.
The CI hiccup seems to have resolved itself. I'm OK with the present state: |
Thank you, @nbruin for all the intense code reviews and feedbacks, and thanks to @vincentmacri and @dimpase for all the guidance and your time. I've learned a lot through this PR. |
sagemathgh-39812: Adds limit(expr, v, a) syntax 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 sagemath#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. <!-- ^ Please provide a concise and informative title. --> <!-- ^ Don't put issue numbers in the title, do this in the PR description below. --> <!-- ^ For example, instead of "Fixes sagemath#12345" use "Introduce new method to calculate 1 + 2". --> <!-- v Describe your changes below in detail. --> <!-- v Why is this change required? What problem does it solve? --> <!-- v If this PR resolves an open issue, please link to it here. For example, "Fixes sagemath#12345". --> ### 📝 Checklist <!-- Put an `x` in all the boxes that apply. --> - [x] The title is concise and informative. - [x] The description explains in detail what this PR is about. - [x] I have linked a relevant issue or discussion. - [x] I have created tests covering the changes. - [ ] I have updated the documentation and checked the documentation preview. ### ⌛ Dependencies Got the idea and direction of fixing the issue and the link to the relevant conversations in the given PR: sagemath#38780 <!-- List all open PRs that this PR logically depends on. For example, --> <!-- - sagemath#12345: short description why this is a dependency --> <!-- - sagemath#34567: ... --> URL: sagemath#39812 Reported by: Ashutosh Rajora Reviewer(s): Ashutosh Rajora, Dima Pasechnik, nbruin, Vincent Macri
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