소스 검색

Merge branch 'sort' into merge_fix

Taddeus Kroes 14 년 전
부모
커밋
ba89b4c54b
5개의 변경된 파일114개의 추가작업 그리고 55개의 파일을 삭제
  1. 3 1
      src/rules/__init__.py
  2. 37 0
      src/rules/sort.py
  3. 31 30
      tests/test_leiden_oefenopgave.py
  4. 25 24
      tests/test_leiden_oefenopgave_v12.py
  5. 18 0
      tests/test_rules_sort.py

+ 3 - 1
src/rules/__init__.py

@@ -11,13 +11,15 @@ from .fractions import match_constant_division, match_add_constant_fractions, \
         match_expand_and_add_fractions
 from .negation import match_negated_factor, match_negate_polynome, \
         match_negated_division
+from .sort import match_sort_multiplicants
 
 RULES = {
         OP_ADD: [match_add_numerics, match_add_constant_fractions,
                  match_combine_groups],
         OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents,
                  match_expand_and_add_fractions, match_multiply_zero,
-                 match_negated_factor, match_multiply_one],
+                 match_negated_factor, match_multiply_one,
+                 match_sort_multiplicants],
         OP_DIV: [match_subtract_exponents, match_divide_numerics,
                  match_constant_division, match_negated_division],
         OP_POW: [match_multiply_exponents, match_duplicate_exponent,

+ 37 - 0
src/rules/sort.py

@@ -0,0 +1,37 @@
+from itertools import product, combinations
+
+from ..node import Scope, OP_ADD, OP_MUL
+from ..possibilities import Possibility as P, MESSAGES
+from ..translate import _
+
+
+def match_sort_multiplicants(node):
+    """
+    Sort multiplicant factors by swapping
+    x * 2  ->  2x
+    """
+    assert node.is_op(OP_MUL)
+
+    p = []
+    scope = Scope(node)
+
+    for i, n in enumerate(scope[1:]):
+        left_nb = scope[i]
+
+        if n.is_numeric() and not left_nb.is_numeric():
+            p.append(P(node, move_constant, (scope, n, left_nb)))
+
+    return p
+
+
+def move_constant(root, args):
+    scope, constant, destination = args
+
+    scope.replace(destination, constant * destination)
+    scope.remove(constant)
+
+    return scope.as_nary_node()
+
+
+MESSAGES[move_constant] = \
+        _('Move constant {2} to the left of the multiplication {0}.')

+ 31 - 30
tests/test_leiden_oefenopgave.py

@@ -4,10 +4,10 @@ from tests.rulestestcase import RulesTestCase as TestCase, rewrite
 class TestLeidenOefenopgave(TestCase):
     def test_1_1(self):
         for chain in [['-5(x2 - 3x + 6)', '-5(x ^ 2 - 3x) - 5 * 6',
-                       '-5 * x ^ 2 - 5 * -3x - 5 * 6',
-                       '-5 * x ^ 2 - -15x - 5 * 6',
-                       '-5 * x ^ 2 + 15x - 5 * 6',
-                       '-5 * x ^ 2 + 15x - 30',
+                       '-5x ^ 2 - 5 * -3x - 5 * 6',
+                       '-5x ^ 2 - -15x - 5 * 6',
+                       '-5x ^ 2 + 15x - 5 * 6',
+                       '-5x ^ 2 + 15x - 30',
                        ],
                      ]:
             self.assertRewrite(chain)
@@ -15,11 +15,11 @@ class TestLeidenOefenopgave(TestCase):
         return
 
         for exp, solution in [
-                ('-5(x2 - 3x + 6)',       '-30 + 15 * x - 5 * x ^ 2'),
-                ('(x+1)^2',              'x ^ 2 + 2 * x + 1'),
-                ('(x-1)^2',              'x ^ 2 - 2 * x + 1'),
-                ('(2x+x)*x',             '3 * x ^ 2'),
-                ('-2(6x-4)^2*x',         '-72 * x^3 + 96 * x ^ 2 + 32 * x'),
+                ('-5(x2 - 3x + 6)',       '-30 + 15x - 5x ^ 2'),
+                ('(x+1)^2',              'x ^ 2 + 2x + 1'),
+                ('(x-1)^2',              'x ^ 2 - 2x + 1'),
+                ('(2x+x)*x',             '3x ^ 2'),
+                ('-2(6x-4)^2*x',         '-72x ^ 3 + 96x ^ 2 + 32x'),
                 ('(4x + 5) * -(5 - 4x)', '16x^2 - 25'),
                 ]:
             self.assertEqual(str(rewrite(exp)), solution)
@@ -36,20 +36,21 @@ class TestLeidenOefenopgave(TestCase):
                 '(x ^ 2 + 2x + 1 * 1)(x + 1)',
                 '(x ^ 2 + 2x + 1)(x + 1)',
                 '(x ^ 2 + 2x)x + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
-                'x * x ^ 2 + x * 2x + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
+                'xx ^ 2 + x * 2x + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
                 'x ^ (1 + 2) + x * 2x + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
                 'x ^ 3 + x * 2x + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
-                'x ^ 3 + x ^ (1 + 1) * 2 + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
-                'x ^ 3 + x ^ 2 * 2 + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
-                'x ^ 3 + x ^ 2 * 2 + 1 * x ^ 2 + 1 * 2x + 1x + 1 * 1',
-                'x ^ 3 + x ^ 2 * 2 + x ^ 2 + 1 * 2x + 1x + 1 * 1',
-                'x ^ 3 + (2 + 1) * x ^ 2 + 1 * 2x + 1x + 1 * 1',
-                'x ^ 3 + 3 * x ^ 2 + 1 * 2x + 1x + 1 * 1',
-                'x ^ 3 + 3 * x ^ 2 + 2x + 1x + 1 * 1',
-                'x ^ 3 + 3 * x ^ 2 + 2x + x + 1 * 1',
-                'x ^ 3 + 3 * x ^ 2 + (2 + 1)x + 1 * 1',
-                'x ^ 3 + 3 * x ^ 2 + 3x + 1 * 1',
-                'x ^ 3 + 3 * x ^ 2 + 3x + 1',
+                'x ^ 3 + 2xx + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
+                'x ^ 3 + 2x ^ (1 + 1) + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
+                'x ^ 3 + 2x ^ 2 + (x ^ 2 + 2x) * 1 + 1x + 1 * 1',
+                'x ^ 3 + 2x ^ 2 + 1x ^ 2 + 1 * 2x + 1x + 1 * 1',
+                'x ^ 3 + 2x ^ 2 + x ^ 2 + 1 * 2x + 1x + 1 * 1',
+                'x ^ 3 + (2 + 1)x ^ 2 + 1 * 2x + 1x + 1 * 1',
+                'x ^ 3 + 3x ^ 2 + 1 * 2x + 1x + 1 * 1',
+                'x ^ 3 + 3x ^ 2 + 2x + 1x + 1 * 1',
+                'x ^ 3 + 3x ^ 2 + 2x + x + 1 * 1',
+                'x ^ 3 + 3x ^ 2 + (2 + 1)x + 1 * 1',
+                'x ^ 3 + 3x ^ 2 + 3x + 1 * 1',
+                'x ^ 3 + 3x ^ 2 + 3x + 1',
                 ]
             ]:
             self.assertRewrite(chain)
@@ -115,7 +116,7 @@ class TestLeidenOefenopgave(TestCase):
 
     def test_1_5(self):
         self.assertRewrite(['(2x + x)x', '(2 + 1)xx', '3xx',
-                            '3 * x ^ (1 + 1)', '3 * x ^ 2'])
+                            '3x ^ (1 + 1)', '3x ^ 2'])
 
     def test_1_7(self):
         self.assertRewrite(['(4x + 5) * -(5 - 4x)',
@@ -124,14 +125,14 @@ class TestLeidenOefenopgave(TestCase):
                             '4x * -5 + 4x * 4x + 5 * -5 + 5 * 4x',
                             '-20x + 4x * 4x + 5 * -5 + 5 * 4x',
                             '-20x + 16xx + 5 * -5 + 5 * 4x',
-                            '-20x + 16 * x ^ (1 + 1) + 5 * -5 + 5 * 4x',
-                            '-20x + 16 * x ^ 2 + 5 * -5 + 5 * 4x',
-                            '-20x + 16 * x ^ 2 - 25 + 5 * 4x',
-                            '-20x + 16 * x ^ 2 - 25 + 20x',
-                            '(-20 + 20)x + 16 * x ^ 2 - 25',
-                            '0x + 16 * x ^ 2 - 25',
-                            '0 + 16 * x ^ 2 - 25',
-                            '-25 + 16 * x ^ 2'])
+                            '-20x + 16x ^ (1 + 1) + 5 * -5 + 5 * 4x',
+                            '-20x + 16x ^ 2 + 5 * -5 + 5 * 4x',
+                            '-20x + 16x ^ 2 - 25 + 5 * 4x',
+                            '-20x + 16x ^ 2 - 25 + 20x',
+                            '(-20 + 20)x + 16x ^ 2 - 25',
+                            '0x + 16x ^ 2 - 25',
+                            '0 + 16x ^ 2 - 25',
+                            '-25 + 16x ^ 2'])
                             # FIXME: '16 * x ^ 2 - 25'])
 
     def test_2(self):

+ 25 - 24
tests/test_leiden_oefenopgave_v12.py

@@ -4,7 +4,7 @@ from tests.rulestestcase import RulesTestCase as TestCase, rewrite
 class TestLeidenOefenopgaveV12(TestCase):
     def test_1_e(self):
         self.assertRewrite([
-            '-2(6x - 4) ^ 2 * x',
+            '-2(6x - 4) ^ 2x',
             '-2(6x - 4)(6x - 4)x',
             '(-2 * 6x - 2 * -4)(6x - 4)x',
             '(-12x - 2 * -4)(6x - 4)x',
@@ -12,26 +12,27 @@ class TestLeidenOefenopgaveV12(TestCase):
             '(-12x + 8)(6x - 4)x',
             '(-12x * 6x - 12x * -4 + 8 * 6x + 8 * -4)x',
             '(-72xx - 12x * -4 + 8 * 6x + 8 * -4)x',
-            '(-72 * x ^ (1 + 1) - 12x * -4 + 8 * 6x + 8 * -4)x',
-            '(-72 * x ^ 2 - 12x * -4 + 8 * 6x + 8 * -4)x',
-            '(-72 * x ^ 2 - -48x + 8 * 6x + 8 * -4)x',
-            '(-72 * x ^ 2 + 48x + 8 * 6x + 8 * -4)x',
-            '(-72 * x ^ 2 + 48x + 48x + 8 * -4)x',
-            '(-72 * x ^ 2 + (1 + 1) * 48x + 8 * -4)x',
-            '(-72 * x ^ 2 + 2 * 48x + 8 * -4)x',
-            '(-72 * x ^ 2 + 96x + 8 * -4)x',
-            '(-72 * x ^ 2 + 96x - 32)x',
-            'x(-72 * x ^ 2 + 96x) + x * -32',
-            'x * -72 * x ^ 2 + x * 96x + x * -32',
-            '-x * 72 * x ^ 2 + x * 96x + x * -32',
-            '-(x ^ (1 + 2)) * 72 + x * 96x + x * -32',
-            '-(x ^ 3) * 72 + x * 96x + x * -32',
-            '-(x ^ 3) * 72 + x ^ (1 + 1) * 96 + x * -32',
-            '-(x ^ 3) * 72 + x ^ 2 * 96 + x * -32',
-            '-(x ^ 3) * 72 + x ^ 2 * 96 - x * 32',
-            '-(x ^ 3) * 72 + x ^ 2 * 96 - x * 32'])
-            # TODO: Should powers have a higher precedence than negation in
-            #       printing?
-            # FIXME: '-72x ^ 3 + x ^ 2 * 96 - x * 32',
-            # FIXME: '-72x ^ 3 + 96x ^ 2 - x * 32',
-            # FIXME: '-72x ^ 3 + 96x ^ 2 - 32x'])
+            '(-72x ^ (1 + 1) - 12x * -4 + 8 * 6x + 8 * -4)x',
+            '(-72x ^ 2 - 12x * -4 + 8 * 6x + 8 * -4)x',
+            '(-72x ^ 2 - -48x + 8 * 6x + 8 * -4)x',
+            '(-72x ^ 2 + 48x + 8 * 6x + 8 * -4)x',
+            '(-72x ^ 2 + 48x + 48x + 8 * -4)x',
+            '(-72x ^ 2 + (1 + 1) * 48x + 8 * -4)x',
+            '(-72x ^ 2 + 2 * 48x + 8 * -4)x',
+            '(-72x ^ 2 + 96x + 8 * -4)x',
+            '(-72x ^ 2 + 96x - 32)x',
+            'x(-72x ^ 2 + 96x) + x * -32',
+            'x * -72x ^ 2 + x * 96x + x * -32',
+            '-x * 72x ^ 2 + x * 96x + x * -32',
+            '72 * -xx ^ 2 + x * 96x + x * -32',
+            '-72xx ^ 2 + x * 96x + x * -32',
+            '-72x ^ (1 + 2) + x * 96x + x * -32',
+            '-72x ^ 3 + x * 96x + x * -32',
+            '-72x ^ 3 + 96xx + x * -32',
+            '-72x ^ 3 + 96x ^ (1 + 1) + x * -32',
+            '-72x ^ 3 + 96x ^ 2 + x * -32',
+            '-72x ^ 3 + 96x ^ 2 - x * 32',
+            '-72x ^ 3 + 96x ^ 2 + 32 * -x',
+            '-72x ^ 3 + 96x ^ 2 - 32x'])
+            # TODO: Should powers have a higher precedence than negation
+            #       while printing?

+ 18 - 0
tests/test_rules_sort.py

@@ -0,0 +1,18 @@
+from src.rules.sort import match_sort_multiplicants, move_constant
+from src.node import Scope
+from src.possibilities import Possibility as P
+from tests.rulestestcase import RulesTestCase, tree
+
+
+class TestRulesSort(RulesTestCase):
+
+    def test_match_sort_multiplicants(self):
+        x, l2 = root = tree('x * 2')
+        possibilities = match_sort_multiplicants(root)
+        self.assertEqualPos(possibilities,
+                [P(root, move_constant, (Scope(root), l2, x))])
+
+    def test_move_constant(self):
+        x, l2 = root = tree('x * 2')
+        self.assertEqualNodes(move_constant(root, (Scope(root), l2, x)),
+                              l2 * x)