Просмотр исходного кода

Added integral rules for functions and fractions.

Taddeus Kroes 14 лет назад
Родитель
Сommit
3cfe9c2e98
3 измененных файлов с 91 добавлено и 7 удалено
  1. 3 2
      src/rules/__init__.py
  2. 63 3
      src/rules/integrals.py
  3. 25 2
      tests/test_rules_integrals.py

+ 3 - 2
src/rules/__init__.py

@@ -26,7 +26,7 @@ from src.rules.logarithmic import match_constant_logarithm, \
         match_factor_in_multiplicant
 from src.rules.integrals import match_solve_indef, match_constant_integral, \
         match_integrate_variable_power, match_factor_out_constant, \
-        match_division_integral
+        match_division_integral, match_function_integral
 
 RULES = {
         OP_ADD: [match_add_numerics, match_add_constant_fractions,
@@ -57,6 +57,7 @@ RULES = {
                  match_quotient_rule],
         OP_LOG: [match_constant_logarithm, match_factor_out_exponent],
         OP_INT: [match_integrate_variable_power, match_constant_integral,
-                 match_factor_out_constant, match_division_integral],
+                 match_factor_out_constant, match_division_integral,
+                 match_function_integral],
         OP_INT_INDEF: [match_solve_indef],
         }

+ 63 - 3
src/rules/integrals.py

@@ -1,9 +1,9 @@
 from .utils import find_variables, infinity, replace_variable, find_variable, \
         absolute
 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, \
-        OP_INT_INDEF, OP_MUL, OP_DIV, Scope
+        OP_INT_INDEF, OP_MUL, OP_DIV, OP_LOG, OP_SIN, OP_COS, Scope
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
@@ -215,7 +215,7 @@ def division_integral(root, args):
 
 
 MESSAGES[division_integral] = \
-        _('1 / {0[1]} has the standard ant-derivative ln|{0[1]}|.')
+        _('1 / {0[1]} has the standard anti-derivative ln|{0[1]}| + c.')
 
 
 def extend_division_integral(root, args):
@@ -229,3 +229,63 @@ def extend_division_integral(root, args):
 
 MESSAGES[extend_division_integral] = _('Bring nominator {0[0][0]} out of the' \
         ' fraction to obtain a standard 1 / {0[0][1]} integral.')
+
+
+def match_function_integral(node):
+    """
+    int log_g(x) dx  ->  (xln(x) - x) / log_g(x)
+    int sin(x) dx    ->  -cos(x)
+    int cos(x) dx    ->  sin(x)
+    """
+    assert node.is_op(OP_INT)
+
+    fx, x = node[:2]
+
+    if fx.is_leaf or fx[0] != x:
+        return []
+
+    if fx.op == OP_LOG:
+        return [P(node, logarithm_integral)]
+
+    if fx.op == OP_SIN:
+        return [P(node, sinus_integral)]
+
+    if fx.op == OP_COS:
+        return [P(node, cosinus_integral)]
+
+    return []
+
+
+def logarithm_integral(root, args):
+    """
+    int log_g(x) dx  ->  (xln(x) - x) / log_g(x)
+    """
+    x, g = root[0]
+
+    return solve_integral(root, (x * ln(x) - x) / ln(g))
+
+
+MESSAGES[logarithm_integral] = _('log_g(x) has the standard anti-derivative ' \
+        '(xln(x) - x) / log_g(x) + c.')
+
+
+def sinus_integral(root, args):
+    """
+    int sin(x) dx  ->  -cos(x)
+    """
+    return solve_integral(root, -cos(root[0][0]))
+
+
+MESSAGES[sinus_integral] = \
+        _('{0[0]} has the standard anti-derivative -cos({0[0][0]}) + c.')
+
+
+def cosinus_integral(root, args):
+    """
+    int cos(x) dx  ->  sin(x)
+    """
+    return solve_integral(root, sin(root[0][0]))
+
+
+MESSAGES[cosinus_integral] = \
+        _('{0[0]} has the standard anti-derivative sin({0[0][0]}) + c.')

+ 25 - 2
tests/test_rules_integrals.py

@@ -3,9 +3,11 @@ from src.rules.integrals import indef, choose_constant, solve_integral, \
         integrate_variable_root, integrate_variable_exponent, \
         match_constant_integral, constant_integral, \
         match_factor_out_constant, factor_out_constant, \
-        match_division_integral, division_integral, extend_division_integral
+        match_division_integral, division_integral, extend_division_integral, \
+        match_function_integral, logarithm_integral, sinus_integral, \
+        cosinus_integral
 from src.rules.logarithmic import ln
-#from .goniometry import sin, cos
+from src.rules.goniometry import sin, cos
 from src.node import Scope
 from src.possibilities import Possibility as P
 from tests.rulestestcase import RulesTestCase, tree
@@ -103,3 +105,24 @@ class TestRulesIntegrals(RulesTestCase):
             # FIXME: 'a int 1 / x dx',  # fix with strategy
             # FIXME: 'aln|x| + c',
         ])
+
+    def test_match_function_integral(self):
+        root0, root1, root2 = tree('int ln x, int sin x, int cos x')
+        self.assertEqualPos(match_function_integral(root0),
+                [P(root0, logarithm_integral)])
+        self.assertEqualPos(match_function_integral(root1),
+                [P(root1, sinus_integral)])
+        self.assertEqualPos(match_function_integral(root2),
+                [P(root2, cosinus_integral)])
+
+    def test_logarithm_integral(self):
+        root, expect = tree('int ln x, (xlnx - x) / ln e + c')
+        self.assertEqual(logarithm_integral(root, ()), expect)
+
+    def test_sinus_integral(self):
+        root, expect = tree('int sin x, -cos x + c')
+        self.assertEqual(sinus_integral(root, ()), expect)
+
+    def test_cosinus_integral(self):
+        root, expect = tree('int cos x, sin x + c')
+        self.assertEqual(cosinus_integral(root, ()), expect)