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

Rubi progress and tests #14756

Merged
merged 51 commits into from Jul 28, 2018
Commits
Jump to file or symbol
Failed to load files and symbols.
+63,023 −32,256
Diff settings

Always

Just for now

Copy path View file
@@ -105,6 +105,7 @@
'sympy.integrals.benchmarks',
'sympy.integrals.rubi',
'sympy.integrals.rubi.parsetools',
'sympy.integrals.rubi.rubi_tests',
'sympy.integrals.rubi.rules',
'sympy.interactive',
'sympy.liealgebras',
@@ -324,6 +325,7 @@ def run(self):
'sympy.geometry.tests',
'sympy.holonomic.tests',
'sympy.integrals.rubi.parsetools.tests',
'sympy.integrals.rubi.rubi_tests.tests',
'sympy.integrals.rubi.tests',
'sympy.integrals.tests',
'sympy.interactive.tests',
Copy path View file
@@ -4472,3 +4472,42 @@ def test_sympy__physics__wigner__Wigner3j():
def test_sympy__integrals__rubi__symbol__matchpyWC():
from sympy.integrals.rubi.symbol import matchpyWC
assert _test_args(matchpyWC(1, True, 'a'))
def test_sympy__integrals__rubi__utility_function__rubi_unevaluated_expr():
from sympy.integrals.rubi.utility_function import rubi_unevaluated_expr
a = symbols('a')
assert _test_args(rubi_unevaluated_expr(a))
def test_sympy__integrals__rubi__utility_function__exp():
from sympy.integrals.rubi.utility_function import exp
assert _test_args(exp(5))
def test_sympy__integrals__rubi__utility_function__log():
from sympy.integrals.rubi.utility_function import log
assert _test_args(log(5))
def test_sympy__integrals__rubi__utility_function__Int():
from sympy.integrals.rubi.utility_function import Int
assert _test_args(Int(5, x))
def test_sympy__integrals__rubi__utility_function__Util_Coefficient():
from sympy.integrals.rubi.utility_function import Util_Coefficient
a, x = symbols('a x')
assert _test_args(Util_Coefficient(a, x))
def test_sympy__integrals__rubi__utility_function__Gamma():
from sympy.integrals.rubi.utility_function import Gamma
assert _test_args(Gamma(5))
def test_sympy__integrals__rubi__utility_function__Util_Part():
from sympy.integrals.rubi.utility_function import Util_Part
a, b = symbols('a b')
assert _test_args(Util_Part(a + b, 0))
def test_sympy__integrals__rubi__utility_function__PolyGamma():
from sympy.integrals.rubi.utility_function import PolyGamma
assert _test_args(PolyGamma(1, 1))
def test_sympy__integrals__rubi__utility_function__ProductLog():
from sympy.integrals.rubi.utility_function import ProductLog
assert _test_args(ProductLog(1))
@@ -10,6 +10,51 @@
Note: This module has dependency on MatchPy library.
Basic Structure
===============
All rules in matchpy format are in rules folder. They are in separate files.
While matching a pattern, there are constraints that need to be checked.
These constraints are placed in a single file `constraints.py`.
A complete rule look like this:
```
def cons_f1(m, x):
return FreeQ(m, x)
cons1 = CustomConstraint(cons_f1)
def cons_f2(m):
return NonzeroQ(m + S(1))
cons2 = CustomConstraint(cons_f2)
pattern1 = Pattern(Integral(x_**WC('m', S(1)), x_), cons1, cons2)
def replacement1(m, x):
rubi.append(1)
return Simp(x**(m + S(1))/(m + S(1)), x)
rule1 = ReplacementRule(pattern1, replacement1)
```
As seen in the above example, a rule has 3 parts
1. Pattern with constraints. Expression is matched against this pattern.
2. Replacement function, which gives the resulting expression with which the original expression has to be replaced with.
There is also `rubi.append(1)`. This (rubi) is a list which keeps track of rules applied to an expression.
This can be accesed by `rules_applied` in `rubi.py`
3. Rule, which combines pattern and replacement function.
(For more details refer to matchpy documents)
Note:
The name of arguments of function for constraints and replacement should be taken care of.
They need to be exactly same as wildcard in the `Pattern`. Like, in the above example,
if `cons_f1` is written something like this:
```
def cons_f1(a, x):
return FreeQ(a, x)
```
This is not going to work because in the Pattern, `m` has been used as a wildcard. So only thing is
naming of arguments matters.
TODO
====
* Use code generation to implement all rules.
@@ -24,10 +69,20 @@
If the applied rule is same, then we need to check the `ReplacementRule` and
the utility functions used in the `ReplacementRule`.
Parsing Rules
Parsing Rules and Tests
=======================
Code for parsing rule and tests are included in sympy.
They have been properly explained with steps in `sympy/integrals/rubi/parsetools/rubi_parsing_guide.md`.
Running Tests
=============
I have included the parser in /parsetools folder. The parser takes
`FullForm[DownValues[]]` of Mathematica rules as input.
The tests for rubi in `rubi_tests` have been blacklisted as it takes a very long time to run all the tests.
To run a test run the following in a python terminal:
```
>>> import sympy
>>> sympy.test("rubi_tests", blacklist = []) # doctest: +SKIP
```
For specific tests like `test_sine.py` use this `sympy.test("rubi_tests/tests/test_sine.py", blacklist = [])`.
References
==========
Oops, something went wrong.
ProTip! Use n and p to navigate between commits in a pull request.