Commit a7a2bfaa authored by Taddeus Kroes's avatar Taddeus Kroes

Added/improved some simple rules for integrals.

parent 427c18a5
...@@ -73,7 +73,7 @@ def match_integrate_variable_power(node): ...@@ -73,7 +73,7 @@ def match_integrate_variable_power(node):
f, x = node[:2] f, x = node[:2]
if f.is_power(): if f.is_power() and not f.negated:
root, exponent = f root, exponent = f
if root == x and not exponent.contains(x): if root == x and not exponent.contains(x):
...@@ -113,18 +113,33 @@ MESSAGES[integrate_variable_exponent] = \ ...@@ -113,18 +113,33 @@ MESSAGES[integrate_variable_exponent] = \
def match_constant_integral(node): def match_constant_integral(node):
""" """
int x dx -> int x ^ 1 dx # -> x ^ 2 / 2 + c
int c dx -> cx int c dx -> cx
""" """
assert node.is_op(OP_INT) assert node.is_op(OP_INT)
fx, x = node[:2] fx, x = node[:2]
if fx == x:
return [P(node, single_variable_integral)]
if not fx.contains(x): if not fx.contains(x):
return [P(node, constant_integral)] return [P(node, constant_integral)]
return [] return []
def single_variable_integral(root, args):
"""
int x dx -> int x ^ 1 dx # -> x ^ 2 / 2 + c
"""
return integral(root[0] ** 1, *root[1:])
MESSAGES[single_variable_integral] = _('Rewrite {0[0]} to {0[0]} ^ 1 and ' \
'apply the standard integral for {0[0]} ^ n.')
def constant_integral(root, args): def constant_integral(root, args):
""" """
int c dx -> cx int c dx -> cx
...@@ -141,11 +156,15 @@ MESSAGES[constant_integral] = _('{0[0]} does not contain {0[1]}, so its ' \ ...@@ -141,11 +156,15 @@ MESSAGES[constant_integral] = _('{0[0]} does not contain {0[1]}, so its ' \
def match_factor_out_constant(node): def match_factor_out_constant(node):
""" """
int cf(x) dx -> c int f(x) dx int cf(x) dx -> c int f(x) dx
int -f(x) dx -> -1 int f(x) dx
""" """
assert node.is_op(OP_INT) assert node.is_op(OP_INT)
fx, x = node[:2] fx, x = node[:2]
if fx.negated:
return [P(node, split_negation_to_constant)]
if not fx.is_op(OP_MUL): if not fx.is_op(OP_MUL):
return [] return []
...@@ -159,6 +178,17 @@ def match_factor_out_constant(node): ...@@ -159,6 +178,17 @@ def match_factor_out_constant(node):
return p return p
def split_negation_to_constant(root, args):
"""
int -f(x) dx -> int -1 * f(x) dx # =>* -int f(x) dx
"""
return integral(-L(1) * root[0].reduce_negation(), *root[1:])
MESSAGES[split_negation_to_constant] = _('Write the negation of {0[0]} as an' \
' explicit -1 and bring it outside of the integral.')
def factor_out_constant(root, args): def factor_out_constant(root, args):
""" """
int cf(x) dx -> c int f(x) dx int cf(x) dx -> c int f(x) dx
......
from src.rules.integrals import indef, choose_constant, solve_integral, \ from src.rules.integrals import indef, choose_constant, solve_integral, \
match_solve_indef, solve_indef, match_integrate_variable_power, \ match_solve_indef, solve_indef, match_integrate_variable_power, \
integrate_variable_root, integrate_variable_exponent, \ integrate_variable_root, integrate_variable_exponent, \
match_constant_integral, constant_integral, \ match_constant_integral, constant_integral, single_variable_integral, \
match_factor_out_constant, factor_out_constant, \ match_factor_out_constant, split_negation_to_constant, \
match_division_integral, division_integral, extend_division_integral, \ factor_out_constant, match_division_integral, division_integral, \
match_function_integral, logarithm_integral, sinus_integral, \ extend_division_integral, match_function_integral, \
cosinus_integral logarithm_integral, sinus_integral, cosinus_integral
from src.node import Scope from src.node import Scope
from src.possibilities import Possibility as P from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree from tests.rulestestcase import RulesTestCase, tree
...@@ -41,10 +41,17 @@ class TestRulesIntegrals(RulesTestCase): ...@@ -41,10 +41,17 @@ class TestRulesIntegrals(RulesTestCase):
self.assertEqual(solve_indef(root, ()), expect) self.assertEqual(solve_indef(root, ()), expect)
def test_match_integrate_variable_power(self): def test_match_integrate_variable_power(self):
for root in tree('int x ^ n, int x ^ n'): root = tree('int x ^ n')
self.assertEqualPos(match_integrate_variable_power(root), self.assertEqualPos(match_integrate_variable_power(root),
[P(root, integrate_variable_root)]) [P(root, integrate_variable_root)])
root = tree('int x ^ n')
self.assertEqualPos(match_integrate_variable_power(root),
[P(root, integrate_variable_root)])
root = tree('int -x ^ n')
self.assertEqualPos(match_integrate_variable_power(root), [])
for root in tree('int g ^ x, int g ^ x'): for root in tree('int g ^ x, int g ^ x'):
self.assertEqualPos(match_integrate_variable_power(root), self.assertEqualPos(match_integrate_variable_power(root),
[P(root, integrate_variable_exponent)]) [P(root, integrate_variable_exponent)])
...@@ -58,11 +65,21 @@ class TestRulesIntegrals(RulesTestCase): ...@@ -58,11 +65,21 @@ class TestRulesIntegrals(RulesTestCase):
self.assertEqual(integrate_variable_exponent(root, ()), expect) self.assertEqual(integrate_variable_exponent(root, ()), expect)
def test_match_constant_integral(self): def test_match_constant_integral(self):
root0, root1 = tree('int 2, int c dx') root = tree('int x dx')
self.assertEqualPos(match_constant_integral(root0), self.assertEqualPos(match_constant_integral(root),
[P(root0, constant_integral)]) [P(root, single_variable_integral)])
self.assertEqualPos(match_constant_integral(root1),
[P(root1, constant_integral)]) root = tree('int 2')
self.assertEqualPos(match_constant_integral(root),
[P(root, constant_integral)])
root = tree('int c dx')
self.assertEqualPos(match_constant_integral(root),
[P(root, constant_integral)])
def test_single_variable_integral(self):
root, expect = tree('int x, int x ^ 1')
self.assertEqual(single_variable_integral(root, ()), expect)
def test_constant_integral(self): def test_constant_integral(self):
root, expect = tree('int 2, 2x + c') root, expect = tree('int 2, 2x + c')
...@@ -76,6 +93,14 @@ class TestRulesIntegrals(RulesTestCase): ...@@ -76,6 +93,14 @@ class TestRulesIntegrals(RulesTestCase):
self.assertEqualPos(match_factor_out_constant(root), self.assertEqualPos(match_factor_out_constant(root),
[P(root, factor_out_constant, (Scope(cx), c))]) [P(root, factor_out_constant, (Scope(cx), c))])
root = tree('int -x2 dx')
self.assertEqualPos(match_factor_out_constant(root),
[P(root, split_negation_to_constant)])
def test_split_negation_to_constant(self):
root, expect = tree('int -x2 dx, int -1x2 dx')
self.assertEqual(split_negation_to_constant(root, ()), expect)
def test_factor_out_constant(self): def test_factor_out_constant(self):
root, expect = tree('int cx2 dx, c int x2 dx') root, expect = tree('int cx2 dx, c int x2 dx')
c, x2 = cx2 = root[0] c, x2 = cx2 = root[0]
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment