Переглянути джерело

Fixed nominator term extraction rule for single-term nominators.

Taddeus Kroes 14 роки тому
батько
коміт
dedcf309dc
3 змінених файлів з 30 додано та 20 видалено
  1. 20 16
      src/rules/fractions.py
  2. 9 2
      tests/test_rules_fractions.py
  3. 1 2
      tests/test_rules_lineq.py

+ 20 - 16
src/rules/fractions.py

@@ -1,4 +1,4 @@
-from itertools import combinations, product
+from itertools import combinations, product, ifilterfalse
 import copy
 
 from .utils import least_common_multiple, partition, is_numeric_node, \
@@ -289,7 +289,7 @@ MESSAGES[divide_by_fraction] = \
         _('Move {3} to nominator of fraction {1} / {2}.')
 
 
-def is_power_combination(a, b):
+def is_power_combination(pair):
     """
     Check if two nodes are powers that can be combined in a fraction, for
     example:
@@ -298,6 +298,8 @@ def is_power_combination(a, b):
     a^2 and a^2
     a^2 and a
     """
+    a, b = pair
+
     if a.is_power():
         a = a[0]
 
@@ -343,24 +345,22 @@ def match_extract_fraction_terms(node):
 
     n_scope, d_scope = map(mult_scope, node)
     p = []
-
-    if len(n_scope) == 1 and len(d_scope) == 1:
-        return p
-
     nominator, denominator = node
 
-    for n in n_scope:
-        # ac / b
-        if not evals_to_numeric(n):
-            a_scope = mult_scope(nominator)
-            a = remove_from_mult_scope(a_scope, n)
+    # ac / b
+    for n in ifilterfalse(evals_to_numeric, n_scope):
+        a_scope = mult_scope(nominator)
+        a = remove_from_mult_scope(a_scope, n)
 
-            if evals_to_numeric(a / denominator):
-                p.append(P(node, extract_nominator_term, (a, n)))
+        if evals_to_numeric(a / denominator):
+            p.append(P(node, extract_nominator_term, (a, n)))
 
-        # a ^ b * c / (a ^ d * e)
-        for d in [d for d in d_scope if is_power_combination(n, d)]:
-            p.append(P(node, extract_fraction_terms, (n_scope, d_scope, n, d)))
+    if len(n_scope) == 1 and len(d_scope) == 1:
+        return p
+
+    # a ^ b * c / (a ^ d * e)
+    for n, d in filter(is_power_combination, product(n_scope, d_scope)):
+        p.append(P(node, extract_fraction_terms, (n_scope, d_scope, n, d)))
 
     return p
 
@@ -374,6 +374,10 @@ def extract_nominator_term(root, args):
     return a / root[1] * c
 
 
+MESSAGES[extract_nominator_term] = \
+        _('Extract {2} from the nominator of fraction {0}.')
+
+
 def extract_fraction_terms(root, args):
     """
     ab / a                   ->  a / a * (b / 1)

+ 9 - 2
tests/test_rules_fractions.py

@@ -238,19 +238,26 @@ class TestRulesFractions(RulesTestCase):
         self.assertEqualPos(match_extract_fraction_terms(root),
                 [P(root, extract_nominator_term, (2, a))])
 
+        a, l3 = n, d = root = tree('a / 3')
+        self.assertEqualPos(match_extract_fraction_terms(root),
+                [P(root, extract_nominator_term, (1, a))])
+
         root = tree('2*4 / 3')
         self.assertEqualPos(match_extract_fraction_terms(root), [])
 
         n, d = root = tree('2a / 2')
         self.assertEqualPos(match_extract_fraction_terms(root),
-                [P(root, extract_fraction_terms, (Scope(n), lscp(d), 2, 2)),
-                 P(root, extract_nominator_term, (2, a))])
+                [P(root, extract_nominator_term, (2, a)),
+                 P(root, extract_fraction_terms, (Scope(n), lscp(d), 2, 2))])
 
     def test_extract_nominator_term(self):
         root, expect = tree('2a / 3, 2 / 3 * a')
         l2, a = root[0]
         self.assertEqual(extract_nominator_term(root, (l2, a)), expect)
 
+        root, expect, l1 = tree('a / 3, 1 / 3 * a, 1')
+        self.assertEqual(extract_nominator_term(root, (l1, root[0])), expect)
+
     def test_extract_fraction_terms_basic(self):
         root, expect = tree('ab / (ca), a / a * (b / c)')
         n, d = root

+ 1 - 2
tests/test_rules_lineq.py

@@ -75,8 +75,7 @@ class TestRulesLineq(RulesTestCase):
             '5x = 0 - 5',
             '5x = -5',
             '5x / 5 = (-5) / 5',
-            '5 / 5 * (x / 1) = (-5) / 5',
-            '1(x / 1) = (-5) / 5',
+            '5 / 5 * x = (-5) / 5',
             '1x = (-5) / 5',
             'x = (-5) / 5',
             'x = -5 / 5',