Преглед изворни кода

Generalized structure of sort rules.

Taddeus Kroes пре 13 година
родитељ
комит
a3de71193e
5 измењених фајлова са 71 додато и 29 уклоњено
  1. 3 0
      src/node.py
  2. 3 3
      src/rules/__init__.py
  3. 2 2
      src/rules/precedences.py
  4. 45 17
      src/rules/sort.py
  5. 18 7
      tests/test_rules_sort.py

+ 3 - 0
src/node.py

@@ -181,6 +181,9 @@ class ExpressionBase(object):
 
         return s_root < o_root or s_exp < o_exp or s_coeff < o_coeff
 
+    def __gt__(self, other):
+        return other < self
+
     def __ne__(self, other):
         """
         Check strict inequivalence, using the strict equivalence operator.

+ 3 - 3
src/rules/__init__.py

@@ -14,7 +14,7 @@ from .fractions import match_constant_division, match_add_fractions, \
         match_extract_fraction_terms, match_division_in_denominator
 from .negation import match_negated_factor, match_negate_polynome, \
         match_negated_division
-from .sort import match_sort_multiplicants
+from .sort import match_sort_polynome, match_sort_molinome
 from .goniometry import match_add_quadrants, match_negated_parameter, \
         match_half_pi_subtraction, match_standard_radian
 from .derivatives import match_zero_derivative, \
@@ -39,8 +39,8 @@ RULES = {
                  match_add_logarithms],
         OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents,
                  match_multiply_zero, match_negated_factor,
-                 match_sort_multiplicants, match_multiply_fractions,
-                 match_factor_in_multiplicant],
+                 match_multiply_fractions, match_factor_in_multiplicant,
+                 match_sort_molinome],
         OP_DIV: [match_subtract_exponents, match_divide_numerics,
                  match_constant_division, match_divide_fractions,
                  match_negated_division, match_extract_fraction_terms,

+ 2 - 2
src/rules/precedences.py

@@ -1,5 +1,5 @@
 from .factors import expand_double, expand_single
-from .sort import move_constant
+from .sort import swap_factors
 from .numerics import multiply_one, multiply_zero, reduce_fraction_constants, \
         raise_numerics, remove_zero, multiply_numerics, add_numerics
 from .logarithmic import factor_in_exponent_multiplicant, \
@@ -36,7 +36,7 @@ LOW = [
 
         # Sorting expression terms has a low priority because it is assumed to
         # be handled by the user
-        move_constant,
+        swap_factors,
         ]
 
 

+ 45 - 17
src/rules/sort.py

@@ -1,35 +1,63 @@
-from ..node import Scope, OP_MUL
+from .utils import iter_pairs
+from ..node import ExpressionNode as N, Scope, OP_ADD, OP_MUL
 from ..possibilities import Possibility as P, MESSAGES
 from ..translate import _
 
 
-def match_sort_multiplicants(node):
+def swap_moni((left, right)):
+    left_num, right_num = left.is_numeric(), right.is_numeric()
+
+    if left_num and right_num:
+        return False
+
+    left_var, right_var = left.is_variable(), right.is_variable()
+
+    if left_var and right_var:
+        return cmp(left.value, right.value)
+
+    if left_var and right_num:
+        return True
+
+
+def swap_poly((left, right)):
+    pass
+
+
+def match_sort_polynome(node):
     """
-    Sort multiplicant factors by swapping
-    x * 2  ->  2x
     """
-    assert node.is_op(OP_MUL)
+    assert node.is_op(OP_ADD)
 
-    p = []
     scope = Scope(node)
 
-    for i, n in enumerate(scope[1:]):
-        left_nb = scope[i]
+    return [P(node, swap_factors, (scope, l, r))
+            for l, r in filter(swap_poly, iter_pairs(scope))]
 
-        if n.is_numeric() and not left_nb.is_numeric():
-            p.append(P(node, move_constant, (scope, n, left_nb)))
 
-    return p
+def match_sort_molinome(node):
+    """
+    x * 2          ->  2x             # variable > number
+    x ^ 2 * x ^ 3  ->  x ^ 3 * x ^ 2  # exponents
+    yx             ->  xy             # alphabetically
+    """
+    assert node.is_op(OP_MUL)
+
+    scope = Scope(node)
+
+    return [P(node, swap_factors, (scope, l, r))
+            for l, r in filter(swap_moni, iter_pairs(scope))]
 
 
-def move_constant(root, args):
-    scope, constant, destination = args
+def swap_factors(root, args):
+    """
+    left * right
+    """
+    scope, left, right = args
 
-    scope.replace(destination, constant * destination)
-    scope.remove(constant)
+    scope.replace(left, N(root.op, right, left))
+    scope.remove(right)
 
     return scope.as_nary_node()
 
 
-MESSAGES[move_constant] = \
-        _('Move constant {2} to the left of the multiplication {0}.')
+MESSAGES[swap_factors] = _('Move {2} to the left of {1}.')

+ 18 - 7
tests/test_rules_sort.py

@@ -1,4 +1,5 @@
-from src.rules.sort import match_sort_multiplicants, move_constant
+from src.rules.sort import match_sort_polynome, swap_factors, \
+        match_sort_molinome, iter_pairs
 from src.node import Scope
 from src.possibilities import Possibility as P
 from tests.rulestestcase import RulesTestCase, tree
@@ -6,13 +7,23 @@ from tests.rulestestcase import RulesTestCase, tree
 
 class TestRulesSort(RulesTestCase):
 
-    def test_match_sort_multiplicants(self):
+    def test_match_sort_molinome_constant(self):
         x, l2 = root = tree('x * 2')
-        possibilities = match_sort_multiplicants(root)
-        self.assertEqualPos(possibilities,
-                [P(root, move_constant, (Scope(root), l2, x))])
+        self.assertEqualPos(match_sort_molinome(root),
+                [P(root, swap_factors, (Scope(root), x, l2))])
 
-    def test_move_constant(self):
+        root = tree('2x')
+        self.assertEqualPos(match_sort_molinome(root), [])
+
+    #def test_match_sort_molinome_variables(self):
+    #    y, x = root = tree('yx')
+    #    self.assertEqualPos(match_sort_molinome(root),
+    #            [P(root, swap_factors, (Scope(root), y, x))])
+
+    #    root = tree('xy')
+    #    self.assertEqualPos(match_sort_molinome(root), [])
+
+    def test_swap_factors(self):
         x, l2 = root = tree('x * 2')
-        self.assertEqualNodes(move_constant(root, (Scope(root), l2, x)),
+        self.assertEqualNodes(swap_factors(root, (Scope(root), x, l2)),
                               l2 * x)