Commit fa682fe0 authored by Taddeus Kroes's avatar Taddeus Kroes

Added rules for integrals of fractions.

parent 74d5caf1
...@@ -25,7 +25,8 @@ from src.rules.logarithmic import match_constant_logarithm, \ ...@@ -25,7 +25,8 @@ from src.rules.logarithmic import match_constant_logarithm, \
match_add_logarithms, match_raised_base, match_factor_out_exponent, \ match_add_logarithms, match_raised_base, match_factor_out_exponent, \
match_factor_in_multiplicant match_factor_in_multiplicant
from src.rules.integrals import match_solve_indef, match_constant_integral, \ from src.rules.integrals import match_solve_indef, match_constant_integral, \
match_integrate_variable_power, match_factor_out_constant match_integrate_variable_power, match_factor_out_constant, \
match_division_integral
RULES = { RULES = {
OP_ADD: [match_add_numerics, match_add_constant_fractions, OP_ADD: [match_add_numerics, match_add_constant_fractions,
...@@ -56,6 +57,6 @@ RULES = { ...@@ -56,6 +57,6 @@ RULES = {
match_quotient_rule], match_quotient_rule],
OP_LOG: [match_constant_logarithm, match_factor_out_exponent], OP_LOG: [match_constant_logarithm, match_factor_out_exponent],
OP_INT: [match_integrate_variable_power, match_constant_integral, OP_INT: [match_integrate_variable_power, match_constant_integral,
match_factor_out_constant], match_factor_out_constant, match_division_integral],
OP_INT_INDEF: [match_solve_indef], OP_INT_INDEF: [match_solve_indef],
} }
from .utils import find_variables, infinity, replace_variable, find_variable from .utils import find_variables, infinity, replace_variable, find_variable, \
absolute
from .logarithmic import ln from .logarithmic import ln
#from .goniometry import sin, cos #from .goniometry import sin, cos
from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_INT, \ from ..node import ExpressionNode as N, ExpressionLeaf as L, OP_INT, \
OP_INT_INDEF, OP_MUL, Scope OP_INT_INDEF, OP_MUL, OP_DIV, Scope
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
...@@ -186,3 +187,45 @@ def factor_out_constant(root, args): ...@@ -186,3 +187,45 @@ def factor_out_constant(root, args):
MESSAGES[factor_out_constant] = _('Factor out {2} from integral {0}.') MESSAGES[factor_out_constant] = _('Factor out {2} from integral {0}.')
def match_division_integral(node):
"""
int 1 / x dx -> ln|x|
int a / x dx -> int a(1 / x) dx # -> a int 1 / x dx -> aln|x|
"""
assert node.is_op(OP_INT)
fx, x = node[:2]
if fx.is_op(OP_DIV) and fx[1] == x:
if fx[0] == 1:
return [P(node, division_integral)]
return [P(node, extend_division_integral)]
return []
def division_integral(root, args):
"""
int 1 / x dx -> ln|x|
"""
return solve_integral(root, ln(absolute(root[0][1])))
MESSAGES[division_integral] = \
_('1 / {0[1]} has the standard ant-derivative ln|{0[1]}|.')
def extend_division_integral(root, args):
"""
int a / x dx -> int a(1 / x) dx # -> a int 1 / x dx -> aln|x|
"""
a, x = root[0]
return integral(a * (L(1) / x), *root[1:])
MESSAGES[extend_division_integral] = _('Bring nominator {0[0][0]} out of the' \
' fraction to obtain a standard 1 / {0[0][1]} integral.')
...@@ -2,7 +2,8 @@ from src.rules.integrals import indef, choose_constant, solve_integral, \ ...@@ -2,7 +2,8 @@ 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, \
match_factor_out_constant, factor_out_constant match_factor_out_constant, factor_out_constant, \
match_division_integral, division_integral, extend_division_integral
from src.rules.logarithmic import ln from src.rules.logarithmic import ln
#from .goniometry import sin, cos #from .goniometry import sin, cos
from src.node import Scope from src.node import Scope
...@@ -79,3 +80,26 @@ class TestRulesIntegrals(RulesTestCase): ...@@ -79,3 +80,26 @@ class TestRulesIntegrals(RulesTestCase):
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]
self.assertEqual(factor_out_constant(root, (Scope(cx2), c)), expect) self.assertEqual(factor_out_constant(root, (Scope(cx2), c)), expect)
def test_match_division_integral(self):
root0, root1 = tree('int 1 / x, int 2 / x')
self.assertEqualPos(match_division_integral(root0),
[P(root0, division_integral)])
self.assertEqualPos(match_division_integral(root1),
[P(root1, extend_division_integral)])
def test_division_integral(self):
root, expect = tree('int 1 / x dx, ln|x| + c')
self.assertEqual(division_integral(root, ()), expect)
def test_extend_division_integral(self):
root, expect = tree('int a / x dx, int a(1 / x) dx')
self.assertEqual(extend_division_integral(root, ()), expect)
def test_match_division_integral_chain(self):
self.assertRewrite([
'int a / x',
'int a(1 / x) dx',
# FIXME: 'a int 1 / x dx', # fix with strategy
# FIXME: 'aln|x| + c',
])
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