소스 검색

Added sum rule for integrals.

Taddeus Kroes 14 년 전
부모
커밋
1328764fb1
3개의 변경된 파일60개의 추가작업 그리고 4개의 파일을 삭제
  1. 3 2
      src/rules/__init__.py
  2. 35 1
      src/rules/integrals.py
  3. 22 1
      tests/test_rules_integrals.py

+ 3 - 2
src/rules/__init__.py

@@ -25,7 +25,8 @@ from .logarithmic import match_constant_logarithm, \
         match_factor_in_multiplicant, match_expand_terms
 from .integrals import match_solve_indef, match_constant_integral, \
         match_integrate_variable_power, match_factor_out_constant, \
-        match_division_integral, match_function_integral
+        match_division_integral, match_function_integral, \
+        match_sum_rule_integral
 from .lineq import match_move_term
 from .absolute import match_factor_out_abs_term
 
@@ -60,7 +61,7 @@ RULES = {
                  match_expand_terms],
         OP_INT: [match_integrate_variable_power, match_constant_integral,
                  match_factor_out_constant, match_division_integral,
-                 match_function_integral],
+                 match_function_integral, match_sum_rule_integral],
         OP_INT_INDEF: [match_solve_indef],
         OP_EQ: [match_move_term],
         OP_ABS: [match_factor_out_abs_term],

+ 35 - 1
src/rules/integrals.py

@@ -1,6 +1,7 @@
 from .utils import find_variables, substitute, find_variable
 from ..node import ExpressionLeaf as L, OP_INT, OP_INT_INDEF, OP_MUL, OP_DIV, \
-        OP_LOG, OP_SIN, OP_COS, Scope, sin, cos, ln, integral, indef, absolute
+        OP_LOG, OP_SIN, OP_COS, Scope, sin, cos, ln, integral, indef, \
+        absolute, OP_ADD
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
@@ -307,3 +308,36 @@ def cosinus_integral(root, args):
 
 MESSAGES[cosinus_integral] = \
         _('{0[0]} has the standard anti-derivative sin({0[0][0]}) + c.')
+
+
+def match_sum_rule_integral(node):
+    """
+    int f(x) + g(x) dx  ->  int f(x) dx + int g(x) dx
+    """
+    assert node.is_op(OP_INT)
+
+    if not node[0].is_op(OP_ADD):
+        return []
+
+    p = []
+    scope = Scope(node[0])
+
+    if len(scope) == 2:
+        return [P(node, sum_rule_integral, (scope, scope[0]))]
+
+    return [P(node, sum_rule_integral, (scope, n)) for n in scope]
+
+
+def sum_rule_integral(root, args):
+    """
+    int f(x) + g(x) dx  ->  int f(x) dx + int g(x) dx
+    """
+    scope, f = args
+    x = root[1]
+    scope.remove(f)
+    addition = integral(f, x) + integral(scope.as_nary_node(), x)
+
+    return addition.negate(root.negated)
+
+
+MESSAGES[sum_rule_integral] = _('Apply the sum rule to {0}.')

+ 22 - 1
tests/test_rules_integrals.py

@@ -5,7 +5,8 @@ from src.rules.integrals import indef, choose_constant, solve_integral, \
         match_factor_out_constant, split_negation_to_constant, \
         factor_out_constant, match_division_integral, division_integral, \
         extend_division_integral, match_function_integral, \
-        logarithm_integral, sinus_integral, cosinus_integral
+        logarithm_integral, sinus_integral, cosinus_integral, \
+        match_sum_rule_integral, sum_rule_integral
 from src.node import Scope
 from src.possibilities import Possibility as P
 from tests.rulestestcase import RulesTestCase, tree
@@ -158,3 +159,23 @@ class TestRulesIntegrals(RulesTestCase):
     def test_cosinus_integral(self):
         root, expect = tree('int cos x, sin x + c')
         self.assertEqual(cosinus_integral(root, ()), expect)
+
+    def test_match_sum_rule_integral(self):
+        (f, g), x = root = tree('int 2x + 3x dx')
+        self.assertEqualPos(match_sum_rule_integral(root),
+                [P(root, sum_rule_integral, (Scope(root[0]), f))])
+
+        ((f, g), h), x = root = tree('int 2x + 3x + 4x dx')
+        self.assertEqualPos(match_sum_rule_integral(root),
+                [P(root, sum_rule_integral, (Scope(root[0]), f)),
+                 P(root, sum_rule_integral, (Scope(root[0]), g)),
+                 P(root, sum_rule_integral, (Scope(root[0]), h))])
+
+    def test_sum_rule_integral(self):
+        ((f, g), h), x = root = tree('int 2x + 3x + 4x dx')
+        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), f)),
+                         tree('int 2x dx + int 3x + 4x dx'))
+        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), g)),
+                         tree('int 3x dx + int 2x + 4x dx'))
+        self.assertEqual(sum_rule_integral(root, (Scope(root[0]), h)),
+                         tree('int 4x dx + int 2x + 3x dx'))