Repository: sympy/sympy
Pull request: Fix Rational parsing in Mathematica parser
<!-- Your title above should be a short description of what
was changed. Do not include the issue number in the title. -->

#### References to other Issues or PRs
Fixes #25716

#### Brief description of what is fixed or changed
The Mathematica parser at present creates an `AppliedUndef` function with the same name and syntax as the built-in sympy `Rational` type, but none of the properties. This is because the conversion is not defined in the parser.

This PR adds the relevant conversion and a simple test to the test cases.


#### Release Notes

<!-- Write the release notes for this release below between the BEGIN and END
statements. The basic format is a bulleted list with the name of the subpackage
and the release note for this PR. For example:


See https://github.com/sympy/sympy/wiki/Writing-Release-Notes for more
information on how to write release notes. The bot will check your release
notes automatically to see if they are formatted correctly. -->

<!-- BEGIN RELEASE NOTES -->
* parsing
  * Fixed a bug in the Mathematica parser parsing rational objects Rational[p,q].
<!-- END RELEASE NOTES -->


Problem statement:
'Rational[m,n]' conversion from Mathematica fails to create a Rational
Minimal working example:

```
> from sympy.parsing.mathematica import parse_mathematica
> parse_mathematica("Rational[1,2]")
Rational(1, 2)
> parse_mathematica("Rational[1,2]") + 2
AttributeError: 'Rational' object has no attribute 'p'
```

I have investigated this a little, and the parser is creating an `AppliedUndef` function called `Rational` which appears to be a Rational as expected, but in fact fails to have any of the required attributes for a type named 'Rational' (in the MWE, it has no numerator attribute), leading to some strange and confusing behaviour.

The fix is to define the map from Mathematica's `Rational` to Sympy's `Rational`. I have a patch which seems to work, which I will submit as a PR shortly.

Hints from issue discussion:

Commit message: Added test for Rational conversion in Mathematica parser

Patch to review:
diff --git a/sympy/parsing/mathematica.py b/sympy/parsing/mathematica.py
index d0cbe7f7b13f..09414d11628e 100644
--- a/sympy/parsing/mathematica.py
+++ b/sympy/parsing/mathematica.py
@@ -5,7 +5,7 @@
 from typing import Any, Callable
 
 import sympy
-from sympy import Mul, Add, Pow, log, exp, sqrt, cos, sin, tan, asin, acos, acot, asec, acsc, sinh, cosh, tanh, asinh, \
+from sympy import Mul, Add, Pow, Rational, log, exp, sqrt, cos, sin, tan, asin, acos, acot, asec, acsc, sinh, cosh, tanh, asinh, \
     acosh, atanh, acoth, asech, acsch, expand, im, flatten, polylog, cancel, expand_trig, sign, simplify, \
     UnevaluatedExpr, S, atan, atan2, Mod, Max, Min, rf, Ei, Si, Ci, airyai, airyaiprime, airybi, primepi, prime, \
     isprime, cot, sec, csc, csch, sech, coth, Function, I, pi, Tuple, GreaterThan, StrictGreaterThan, StrictLessThan, \
@@ -131,6 +131,7 @@ class MathematicaParser:
     # left: Mathematica, right: SymPy
     CORRESPONDENCES = {
         'Sqrt[x]': 'sqrt(x)',
+        'Rational[x,y]': 'Rational(x,y)',
         'Exp[x]': 'exp(x)',
         'Log[x]': 'log(x)',
         'Log[x,y]': 'log(y,x)',
@@ -975,6 +976,7 @@ def converter(expr):
         "Times": Mul,
         "Plus": Add,
         "Power": Pow,
+        "Rational": lambda *a: Rational(*a),
         "Log": lambda *a: log(*reversed(a)),
         "Log2": lambda x: log(x, 2),
         "Log10": lambda x: log(x, 10),
diff --git a/sympy/parsing/tests/test_mathematica.py b/sympy/parsing/tests/test_mathematica.py
index b6df911f30a2..c72b3e5eeaef 100644
--- a/sympy/parsing/tests/test_mathematica.py
+++ b/sympy/parsing/tests/test_mathematica.py
@@ -67,7 +67,8 @@ def test_mathematica():
         'LogIntegral[4]': ' li(4)',
         'PrimePi[7]': 'primepi(7)',
         'Prime[5]': 'prime(5)',
-        'PrimeQ[5]': 'isprime(5)'
+        'PrimeQ[5]': 'isprime(5)',
+        'Rational[2,19]': 'Rational(2,19)',    # test case for issue 25716
         }
 
     for e in d:


Code review comments:
diff_hunk: @@ -975,6 +976,7 @@ def converter(expr):
         "Times": Mul,
         "Plus": Add,
         "Power": Pow,
+        "Rational": lambda *a: Rational(*a),
path: sympy/parsing/mathematica.py
text: @user1:
Why not just 

```suggestion
        "Rational": Rational,
```

@author:
No reason except for clarity that it's a two-argument function that takes its arguments in the same order as Mathematica. Probably better without the lambda-function, so I'll make that change.