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
Removed evaluate=False
from the Lark-based LaTeX parser
#25515
Conversation
…=False`, and made the integral tests pass.
Added evaluated expression pair lists for simple expressions, fractional expressions, and power expressions. Prepended "unevaluated" to all the existing expression lists. Removed a few unnecessary tests from `MISCELLANEOUS_EXPRESSION_PAIRS` because they test for features we won't support. Added tests for the evaluated expression pair lists for simple expressions and fractional expressions.
…uare root expressions, factorial expressions, sum expressions, and common function expressions, and binomial expressions.
✅ Hi, I am the SymPy bot (v170). I'm here to help you write a release notes entry. Please read the guide on how to write release notes. Your release notes are in good order. Here is what the release notes will look like:
This will be added to https://github.com/sympy/sympy/wiki/Release-Notes-for-1.13. Click here to see the pull request description that was parsed.
Update The release notes on the wiki have been updated. |
…ols instead of the `sympy` functions like `Add`, `Mul` and `Pow`.
Benchmark results from GitHub Actions Lower numbers are good, higher numbers are bad. A ratio less than 1 Significantly changed benchmark results (PR vs master) Significantly changed benchmark results (master vs previous release) before after ratio
[8059df73] [77010f3b]
<sympy-1.12^0>
- 87.1±0.8ms 56.5±0.7ms 0.65 integrate.TimeIntegrationRisch02.time_doit(10)
- 87.1±0.6ms 55.0±0.4ms 0.63 integrate.TimeIntegrationRisch02.time_doit_risch(10)
- 2.11±0.01ms 655±0.9μs 0.31 polys.TimePREM_LinearDenseQuadraticGCD.time_op(3, 'sparse')
- 10.3±0.02ms 1.95±0.01ms 0.19 polys.TimePREM_LinearDenseQuadraticGCD.time_op(5, 'sparse')
- 366±0.8μs 81.6±0.3μs 0.22 polys.TimePREM_QuadraticNonMonicGCD.time_op(1, 'sparse')
- 4.82±0.01ms 362±0.9μs 0.08 polys.TimePREM_QuadraticNonMonicGCD.time_op(3, 'sparse')
- 10.6±0.4ms 1.09±0ms 0.10 polys.TimePREM_QuadraticNonMonicGCD.time_op(5, 'sparse')
- 6.25±0.01ms 3.94±0.01ms 0.63 polys.TimeSUBRESULTANTS_LinearDenseQuadraticGCD.time_op(2, 'sparse')
- 27.2±0.02ms 12.0±0.02ms 0.44 polys.TimeSUBRESULTANTS_LinearDenseQuadraticGCD.time_op(3, 'sparse')
- 6.97±0.03ms 1.17±0ms 0.17 polys.TimeSUBRESULTANTS_QuadraticNonMonicGCD.time_op(1, 'sparse')
- 16.1±0.02ms 9.16±0.01ms 0.57 polys.TimeSUBRESULTANTS_QuadraticNonMonicGCD.time_op(2, 'sparse')
- 210±0.08ms 70.5±0.1ms 0.34 polys.TimeSUBRESULTANTS_QuadraticNonMonicGCD.time_op(3, 'sparse')
- 6.37±0.01ms 534±2μs 0.08 polys.TimeSUBRESULTANTS_SparseGCDHighDegree.time_op(3, 'sparse')
- 27.7±0.04ms 856±1μs 0.03 polys.TimeSUBRESULTANTS_SparseGCDHighDegree.time_op(5, 'sparse')
- 611±2μs 197±0.9μs 0.32 polys.TimeSUBRESULTANTS_SparseNonMonicQuadratic.time_op(1, 'sparse')
- 6.46±0.01ms 202±0.7μs 0.03 polys.TimeSUBRESULTANTS_SparseNonMonicQuadratic.time_op(3, 'sparse')
- 17.0±0.02ms 206±0.8μs 0.01 polys.TimeSUBRESULTANTS_SparseNonMonicQuadratic.time_op(5, 'sparse')
- 161±0.3μs 88.5±0.2μs 0.55 solve.TimeMatrixOperations.time_rref(3, 0)
- 309±0.4μs 107±0.4μs 0.35 solve.TimeMatrixOperations.time_rref(4, 0)
- 31.7±0.1ms 13.7±0.05ms 0.43 solve.TimeSolveLinSys189x49.time_solve_lin_sys
Full benchmark results can be found as artifacts in GitHub Actions |
@sylee957 Some tests for the |
…cal symbols instead of the `sympy` functions like `Add`, `Mul` and `Pow`." This reverts commit b703a70.
@sylee957 I've reverted the change that you suggested because tests were failing due to it. I'm not convinced that we should remove support for |
The reason that we don’t have to support that is because evaluate(false) context manager can support that behavior orthogonally. I don’t think that we should really add any options for sake of the future. And we are also very unsure supporting evaluate=False in the future as well, because that doesn’t work with lots of other sympy features, so I don’t want to make the surface area more larger for maintanance. As you see, you always have to drill evaluate=False everywhere to support that. This is a mess, and although drilling down the property seems easy, it is one of the red flag that you are not factoring out the features well. |
When I removed the
That's a good point. While I personally have no issue with making the change, I'd feel better if we got Aaron and Francesco's thoughts on this. Perhaps we can discuss the matter on the Matrix chat. I'll bring it up there, and also cc them here. cc @asmeurer @Upabjojr for thoughts: Do we want to support |
I also recognize that some of the code path is not consistently returning SymPy objects
My opinion is that these should be the analysis why |
I think that with evaluate(False):
expr = parse_latex(text) is probably a bad idea. The Writing any nontrivial code for the internals of SymPy that could reasonably be expected to work under the impact of |
Passing the keyword I really don't get what's the problem of shoving the option In fact, I don't really had a need to use |
It is not the same effect because using In [5]: cat t.py
def func(a, b, evaluate=None):
stuff1 = a + b
stuff2 = Add(a, b, evaluate=evaluate)
return stuff1, stuff2
In [8]: func(x, x)
Out[8]: (2⋅x, 2⋅x)
In [9]: func(x, x, evaluate=False)
Out[9]: (2⋅x, x + x)
In [10]: with evaluate(False):
...: y = func(x, x)
...:
In [11]: y
Out[11]: (x + x, x + x) I agree that there are problems with unevaluated expressions but I think that |
I ask that high level functions of SymPy shouldn't that SymPy needs It already looks like having that as user option, is very unsatisfactory because the behavior it is complicated if evaluate=False is used shallowly or deeply. |
And anyway I think that your example is artificial though And in fact, this shows the reason that having options about
|
The major problem about this is the roadmap problem, than its implementation detail. The real problem about roadmap is that we are not sure about we are not sure about how SymPy is going to handle eager evaluation, You should drop |
I think that we should take this discussion to another issue that is specifically for discussing what to do about I do want to respond to this though:
It is very clear that many users want the option to prevent automatic evaluation somehow and that they would like SymPy to be able to make that work without everything just breaking. Especially there are many users who want this in the context of parsing. Those users really want to be able to parse an expression and get something that looks like an exact representation of what was parsed and that can then be printed back out in such a way that still looks exactly the same so e.g. (modulo whitespace, and braces etc) they want the following invariant: >>> latex(parse_latex(string)) == string
True |
Just thought I'd chime in: The relevant issue for that is #24116. |
My opinion is that ‘we start minimal’ However, as far as I have done during previous job, which actually had involved parsing SymPy expressions unevaluated. I’ve just done by referencing the Transformer and overriding the rules individually, |
While I got the sentiment, I'd like to point out that, as it's stated, this is not a meaningful metric: >>> string = r"\int\limits_0^1 \sin x dx"
>>> sympy_repr = parse_latex(string)
>>> print(sympy_repr)
Integral(sin(x), (x, 0, 1))
>>> latex_string = latex(sympy_repr)
>>> print(latex_string)
\int\limits_{0}^{1} \sin{\left(x \right)}\, dx
>>> latex_string == string
False |
I may request to fix the inconsistency issue of integers here Try to change int to Integer. We should always return SymPy objects anyway. |
Alright, I'll open a separate PR for that. I was originally planning to do that as a part of this PR, but it seems that we have a few blocking discussions that we need to resolve before this PR can find its way into |
I don’t think that this PR is blocking though. We agree to drop the evaluate=False as default, and we don’t have to add options here. |
And what about |
I think that you need to fix the issues about integer returns before trying that. |
Should the issue be closed? |
Passing evaluate=False through everywhere does suck, because it's not the default so it has to manually be disabled everywhere. It would be much better if the classes just didn't evaluate, so the parser could just use Add(...), Mul(...) and so on, then have a single call to doit() at the end to evaluate everything. This is how things work in the matrix expressions, but not anywhere else. Changing this design in the core is not easy, though. The best we have right now is the evaluate(False) context manager which basically forces the core to work like this. Of course, we could have also fixed this by keeping the evaluate=False everywhere, but just evaluating by default at the end, and having a flag to disable it. But this fix ends up being cleaner and you can still achieve the same result with evaluate(False). At any rate, I don't see an issue with |
References to other Issues or PRs
Addresses #24116 for the Lark-based LaTeX parser.
Brief description of what is fixed or changed
Originally, the ANTLR LaTeX parser returned unevaluated expressions. There were concerns that unevaluated expressions can create all sorts of issues , so we wanted to change this behavior.
I made it so that both
evaluate=False
andevaluate=True
work with the Lark-based LaTeX parser, withevaluate=True
being the default.Other comments
Release Notes
"\sqrt{\frac{12}{6}}"
will re turn\sqrt(2)
now. The previous behavior can achieved by using theevaluate(False)
context manager.