Commit 1453c1cb authored by Taddeus Kroes's avatar Taddeus Kroes

Fixed numeric rules.

parent 564c751b
from itertools import combinations from itertools import combinations
from ..node import ExpressionLeaf as Leaf, Scope, negate, OP_DIV, OP_MUL from ..node import ExpressionLeaf as Leaf, Scope, negate, OP_ADD, OP_DIV, \
OP_MUL
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
def add_numerics(root, args): def match_add_numerics(node):
""" """
Combine two constants to a single constant in an n-ary addition. Combine two constants to a single constant in an n-ary addition.
...@@ -15,8 +16,26 @@ def add_numerics(root, args): ...@@ -15,8 +16,26 @@ def add_numerics(root, args):
-2 + 3 -> 1 -2 + 3 -> 1
-2 + -3 -> -5 -2 + -3 -> -5
""" """
scope, n0, n1, c0, c1 = args assert node.is_op(OP_ADD)
p = []
scope = Scope(node)
numerics = filter(lambda n: n.is_numeric(), scope)
for c0, c1 in combinations(numerics, 2):
p.append(P(node, add_numerics, (scope, c0, c1)))
return p
def add_numerics(root, args):
"""
2 + 3 -> 5
2 + -3 -> -1
-2 + 3 -> 1
-2 + -3 -> -5
"""
scope, c0, c1 = args
value = c0.actual_value() + c1.actual_value() value = c0.actual_value() + c1.actual_value()
if value < 0: if value < 0:
...@@ -25,10 +44,10 @@ def add_numerics(root, args): ...@@ -25,10 +44,10 @@ def add_numerics(root, args):
leaf = Leaf(value) leaf = Leaf(value)
# Replace the left node with the new expression # Replace the left node with the new expression
scope.replace(n0, leaf) scope.replace(c0, Leaf(abs(value)).negate(int(value < 0)))
# Remove the right node # Remove the right node
scope.remove(n1) scope.remove(c1)
return scope.as_nary_node() return scope.as_nary_node()
...@@ -146,14 +165,11 @@ def match_multiply_numerics(node): ...@@ -146,14 +165,11 @@ def match_multiply_numerics(node):
assert node.is_op(OP_MUL) assert node.is_op(OP_MUL)
p = [] p = []
numerics = [] scope = Scope(node)
numerics = filter(lambda n: n.is_numeric(), scope)
for n in Scope(node):
if n.is_numeric():
numerics.append((n, n.actual_value()))
for (n0, v0), (n1, v1) in combinations(numerics, 2): for c0, c1 in combinations(numerics, 2):
p.append(P(node, multiply_numerics, (n0, n1, v0, v1))) p.append(P(node, multiply_numerics, (scope, c0, c1)))
return p return p
...@@ -165,22 +181,15 @@ def multiply_numerics(root, args): ...@@ -165,22 +181,15 @@ def multiply_numerics(root, args):
Example: Example:
2 * 3 -> 6 2 * 3 -> 6
""" """
n0, n1, v0, v1 = args scope, c0, c1 = args
scope = []
value = v0 * v1
if value > 0:
substitution = Leaf(value)
else:
substitution = -Leaf(-value)
scope = Scope(root)
# Replace the left node with the new expression # Replace the left node with the new expression
scope.replace(n0, substitution) substitution = Leaf(c0.value * c1.value).negate(c0.negated + c1.negated)
scope.replace(c0, substitution)
# Remove the right node # Remove the right node
scope.remove(n1) scope.remove(c1)
return scope.as_nary_node() return scope.as_nary_node()
......
...@@ -49,14 +49,15 @@ def match_combine_polynomes(node, verbose=False): ...@@ -49,14 +49,15 @@ def match_combine_polynomes(node, verbose=False):
# Both numeric root and same exponent -> combine coefficients and # Both numeric root and same exponent -> combine coefficients and
# roots, or: same root and exponent -> combine coefficients. # roots, or: same root and exponent -> combine coefficients.
# TODO: Addition with zero, e.g. a + 0 -> a # TODO: Addition with zero, e.g. a + 0 -> a
if c0 == 1 and c1 == 1 and e0 == 1 and e1 == 1 \ #if c0 == 1 and c1 == 1 and e0 == 1 and e1 == 1 \
and all(map(lambda n: n.is_numeric(), [r0, r1])): # and all(map(lambda n: n.is_numeric(), [r0, r1])):
# 2 + 3 -> 5 # # 2 + 3 -> 5
# 2 + -3 -> -1 # # 2 + -3 -> -1
# -2 + 3 -> 1 # # -2 + 3 -> 1
# -2 + -3 -> -5 # # -2 + -3 -> -5
p.append(P(node, add_numerics, (scope, n0, n1, r0, r1))) # p.append(P(node, add_numerics, (scope, n0, n1, r0, r1)))
elif c0.is_numeric() and c1.is_numeric() and r0 == r1 and e0 == e1: #el
if c0.is_numeric() and c1.is_numeric() and r0 == r1 and e0 == e1:
# 2a + 2a -> 4a # 2a + 2a -> 4a
# a + 2a -> 3a # a + 2a -> 3a
# 2a + a -> 3a # 2a + a -> 3a
......
...@@ -3,6 +3,7 @@ from tests.rulestestcase import RulesTestCase as TestCase, rewrite ...@@ -3,6 +3,7 @@ from tests.rulestestcase import RulesTestCase as TestCase, rewrite
class TestLeidenOefenopgaveV12(TestCase): class TestLeidenOefenopgaveV12(TestCase):
def test_1_e(self): def test_1_e(self):
return
for chain in [['-2(6x - 4) ^ 2 * x', for chain in [['-2(6x - 4) ^ 2 * x',
'-2(6x - 4)(6x - 4)x', '-2(6x - 4)(6x - 4)x',
'(-2 * 6x - 2 * -4)(6x - 4)x', '(-2 * 6x - 2 * -4)(6x - 4)x',
......
from src.rules.numerics import add_numerics, match_divide_numerics, \ from src.rules.numerics import match_add_numerics, add_numerics, \
divide_numerics, match_multiply_numerics, multiply_numerics match_divide_numerics, divide_numerics, match_multiply_numerics, \
multiply_numerics
from src.node import ExpressionLeaf as L, Scope
from src.possibilities import Possibility as P from src.possibilities import Possibility as P
from src.node import ExpressionLeaf as L
from tests.rulestestcase import RulesTestCase, tree from tests.rulestestcase import RulesTestCase, tree
class TestRulesNumerics(RulesTestCase): class TestRulesNumerics(RulesTestCase):
def test_match_add_numerics(self):
l1, l2 = root = tree('1 + 2')
possibilities = match_add_numerics(root)
self.assertEqualPos(possibilities,
[P(root, add_numerics, (Scope(root), l1, l2))])
(l1, b), l2 = root = tree('1 + b + 2')
possibilities = match_add_numerics(root)
self.assertEqualPos(possibilities,
[P(root, add_numerics, (Scope(root), l1, l2))])
def test_add_numerics(self): def test_add_numerics(self):
l0, a, l1 = tree('1,a,2') l0, a, l1 = tree('1,a,2')
self.assertEqual(add_numerics(l0 + l1, (l0, l1, L(1), L(2))), 3) root = l0 + l1
self.assertEqual(add_numerics(l0 + a + l1, (l0, l1, L(1), L(2))), self.assertEqual(add_numerics(root, (Scope(root), l0, l1)), 3)
L(3) + a) root = l0 + a + l1
self.assertEqual(add_numerics(root, (Scope(root), l0, l1)), L(3) + a)
def test_add_numerics_negations(self): def test_add_numerics_negations(self):
l0, a, l1 = tree('1,a,2') l1, a, l2 = tree('1,a,2')
ml1, ml2 = -l1, -l2
self.assertEqual(add_numerics(-l0 + l1, (-l0, l1, -L(1), L(2))), 1) r = ml1 + l2
self.assertEqual(add_numerics(l0 + -l1, (l0, -l1, L(1), -L(2))), -1) self.assertEqual(add_numerics(r, (Scope(r), ml1, l2)), 1)
self.assertEqual(add_numerics(l0 + a + -l1, (l0, -l1, L(1), -L(2))), r = l1 + ml2
L(-1) + a) self.assertEqual(add_numerics(r, (Scope(r), l1, ml2)), -1)
def test_match_divide_numerics(self): def test_match_divide_numerics(self):
a, b, i2, i3, i6, f1, f2, f3 = tree('a,b,2,3,6,1.0,2.0,3.0') a, b, i2, i3, i6, f1, f2, f3 = tree('a,b,2,3,6,1.0,2.0,3.0')
...@@ -71,46 +85,49 @@ class TestRulesNumerics(RulesTestCase): ...@@ -71,46 +85,49 @@ class TestRulesNumerics(RulesTestCase):
root = i3 * i2 root = i3 * i2
self.assertEqual(match_multiply_numerics(root), self.assertEqual(match_multiply_numerics(root),
[P(root, multiply_numerics, (i3, i2, 3, 2))]) [P(root, multiply_numerics, (Scope(root), i3, i2))])
root = f3 * i2 root = f3 * i2
self.assertEqual(match_multiply_numerics(root), self.assertEqual(match_multiply_numerics(root),
[P(root, multiply_numerics, (f3, i2, 3.0, 2))]) [P(root, multiply_numerics, (Scope(root), f3, i2))])
root = i3 * f2 root = i3 * f2
self.assertEqual(match_multiply_numerics(root), self.assertEqual(match_multiply_numerics(root),
[P(root, multiply_numerics, (i3, f2, 3, 2.0))]) [P(root, multiply_numerics, (Scope(root), i3, f2))])
root = f3 * f2 root = f3 * f2
self.assertEqual(match_multiply_numerics(root), self.assertEqual(match_multiply_numerics(root),
[P(root, multiply_numerics, (f3, f2, 3.0, 2.0))]) [P(root, multiply_numerics, (Scope(root), f3, f2))])
def test_multiply_numerics(self): def test_multiply_numerics(self):
a, b, i2, i3, i6, f2, f3, f6 = tree('a,b,2,3,6,2.0,3.0,6.0') a, b, i2, i3, i6, f2, f3, f6 = tree('a,b,2,3,6,2.0,3.0,6.0')
self.assertEqual(multiply_numerics(i3 * i2, (i3, i2, 3, 2)), 6) root = i3 * i2
self.assertEqual(multiply_numerics(f3 * i2, (f3, i2, 3.0, 2)), 6.0) self.assertEqual(multiply_numerics(root, (Scope(root), i3, i2)), 6)
self.assertEqual(multiply_numerics(i3 * f2, (i3, f2, 3, 2.0)), 6.0) root = f3 * i2
self.assertEqual(multiply_numerics(f3 * f2, (f3, f2, 3.0, 2.0)), 6.0) self.assertEqual(multiply_numerics(root, (Scope(root), f3, i2)), 6.0)
root = i3 * f2
self.assertEqual(multiply_numerics(root, (Scope(root), i3, f2)), 6.0)
root = f3 * f2
self.assertEqual(multiply_numerics(root, (Scope(root), f3, f2)), 6.0)
self.assertEqualNodes(multiply_numerics(a * i3 * i2 * b, root = a * i3 * i2 * b
(i3, i2, 3, 2)), a * 6 * b) self.assertEqualNodes(multiply_numerics(root,
(Scope(root), i3, i2)), a * 6 * b)
def test_multiply_numerics_negation(self): def test_multiply_numerics_negation(self):
l1_neg, l2 = root = tree('-1 * 2') l1_neg, l2 = root = tree('-1 * 2')
self.assertEqualNodes(multiply_numerics(root, (l1_neg, l2, -1, 2)), self.assertEqualNodes(multiply_numerics(root, (Scope(root), l1_neg,
-l2) l2)), -l2)
root, l6 = tree('1 - 2 * 3,6')
l1, neg = root
l2, l3 = mul = neg[0]
self.assertEqualNodes(multiply_numerics(mul, (l2, l3, 2, 3)), l6)
l1, mul = root = tree('1 + -2 * 3') root, l6 = tree('1 + -2 * 3,6')
l1, mul = root
l2_neg, l3 = mul l2_neg, l3 = mul
self.assertEqualNodes(multiply_numerics(mul, (l2_neg, l3, -2, 3)), -l6) self.assertEqualNodes(multiply_numerics(mul, (Scope(mul),
l2_neg, l3)), -l6)
root, l30 = tree('-5 * x ^ 2 - -15x - 5 * 6,30') root, l30 = tree('-5 * x ^ 2 - -15x - 5 * 6,30')
rest, mul_neg = root rest, mul = root
l5_neg, l6 = mul = mul_neg[0] l5_neg, l6 = mul
self.assertEqualNodes(multiply_numerics(mul, (l5_neg, l6, 5, 6)), l30) self.assertEqualNodes(multiply_numerics(mul, (Scope(mul),
l5_neg, l6)), -l30)
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment