Rule Based Integration(RUBI) module in SymPy uses set of transformation rules to integrate an expression. All the transformation rules are compiled as a discrimination-net which helps in matching expression with the rule efficiently. Due to large number of rules, the module would normally take lot of time to load. Hence, it is better to use Rubi while doing multiple integrations. Rules are taken from Rubi version 4.10.8.
Note: This module has dependency on MatchPy library.
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
- Pattern with constraints. Expression is matched against this pattern.
- 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 accessed byrules_applied
inrubi.py
- 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.
- Use code generation to implement all rules.
- Testing of all the tests from rubi test suit. See: http://www.apmaths.uwo.ca/~arich/IntegrationProblems/MathematicaSyntaxFiles/MathematicaSyntaxFiles.html
- Add support for
Piecewise
functions.
When an integration is not successful. We can see which rule is matching the
expression by using get_matching_rule_definition()
function. We can cross-check
if correct rule is being applied by evaluating the same expression in Mathematica.
If the applied rule is same, then we need to check the ReplacementRule
and
the utility functions used in the ReplacementRule
.
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
.
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 = [])
.
[1] http://www.apmaths.uwo.ca/~arich/ [2] sympy/sympy#7749 [3] sympy/sympy#12978