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

Fixed numeric rules.

parent 564c751b
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 ..translate import _
def add_numerics(root, args):
def match_add_numerics(node):
"""
Combine two constants to a single constant in an n-ary addition.
......@@ -15,8 +16,26 @@ def add_numerics(root, args):
-2 + 3 -> 1
-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()
if value < 0:
......@@ -25,10 +44,10 @@ def add_numerics(root, args):
leaf = Leaf(value)
# 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
scope.remove(n1)
scope.remove(c1)
return scope.as_nary_node()
......@@ -146,14 +165,11 @@ def match_multiply_numerics(node):
assert node.is_op(OP_MUL)
p = []
numerics = []
for n in Scope(node):
if n.is_numeric():
numerics.append((n, n.actual_value()))
scope = Scope(node)
numerics = filter(lambda n: n.is_numeric(), scope)
for (n0, v0), (n1, v1) in combinations(numerics, 2):
p.append(P(node, multiply_numerics, (n0, n1, v0, v1)))
for c0, c1 in combinations(numerics, 2):
p.append(P(node, multiply_numerics, (scope, c0, c1)))
return p
......@@ -165,22 +181,15 @@ def multiply_numerics(root, args):
Example:
2 * 3 -> 6
"""
n0, n1, v0, v1 = args
scope = []
value = v0 * v1
if value > 0:
substitution = Leaf(value)
else:
substitution = -Leaf(-value)
scope, c0, c1 = args
scope = Scope(root)
# 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
scope.remove(n1)
scope.remove(c1)
return scope.as_nary_node()
......
......@@ -49,14 +49,15 @@ def match_combine_polynomes(node, verbose=False):
# Both numeric root and same exponent -> combine coefficients and
# roots, or: same root and exponent -> combine coefficients.
# TODO: Addition with zero, e.g. a + 0 -> a
if c0 == 1 and c1 == 1 and e0 == 1 and e1 == 1 \
and all(map(lambda n: n.is_numeric(), [r0, r1])):
# 2 + 3 -> 5
# 2 + -3 -> -1
# -2 + 3 -> 1
# -2 + -3 -> -5
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:
#if c0 == 1 and c1 == 1 and e0 == 1 and e1 == 1 \
# and all(map(lambda n: n.is_numeric(), [r0, r1])):
# # 2 + 3 -> 5
# # 2 + -3 -> -1
# # -2 + 3 -> 1
# # -2 + -3 -> -5
# p.append(P(node, add_numerics, (scope, n0, n1, r0, r1)))
#el
if c0.is_numeric() and c1.is_numeric() and r0 == r1 and e0 == e1:
# 2a + 2a -> 4a
# a + 2a -> 3a
# 2a + a -> 3a
......
......@@ -3,6 +3,7 @@ from tests.rulestestcase import RulesTestCase as TestCase, rewrite
class TestLeidenOefenopgaveV12(TestCase):
def test_1_e(self):
return
for chain in [['-2(6x - 4) ^ 2 * x',
'-2(6x - 4)(6x - 4)x',
'(-2 * 6x - 2 * -4)(6x - 4)x',
......
from src.rules.numerics import add_numerics, match_divide_numerics, \
divide_numerics, match_multiply_numerics, multiply_numerics
from src.rules.numerics import match_add_numerics, add_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.node import ExpressionLeaf as L
from tests.rulestestcase import RulesTestCase, tree
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):
l0, a, l1 = tree('1,a,2')
self.assertEqual(add_numerics(l0 + l1, (l0, l1, L(1), L(2))), 3)
self.assertEqual(add_numerics(l0 + a + l1, (l0, l1, L(1), L(2))),
L(3) + a)
root = l0 + l1
self.assertEqual(add_numerics(root, (Scope(root), l0, l1)), 3)
root = l0 + a + l1
self.assertEqual(add_numerics(root, (Scope(root), l0, l1)), L(3) + a)
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)
self.assertEqual(add_numerics(l0 + -l1, (l0, -l1, L(1), -L(2))), -1)
self.assertEqual(add_numerics(l0 + a + -l1, (l0, -l1, L(1), -L(2))),
L(-1) + a)
r = ml1 + l2
self.assertEqual(add_numerics(r, (Scope(r), ml1, l2)), 1)
r = l1 + ml2
self.assertEqual(add_numerics(r, (Scope(r), l1, ml2)), -1)
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')
......@@ -71,46 +85,49 @@ class TestRulesNumerics(RulesTestCase):
root = i3 * i2
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
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
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
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):
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)
self.assertEqual(multiply_numerics(f3 * i2, (f3, i2, 3.0, 2)), 6.0)
self.assertEqual(multiply_numerics(i3 * f2, (i3, f2, 3, 2.0)), 6.0)
self.assertEqual(multiply_numerics(f3 * f2, (f3, f2, 3.0, 2.0)), 6.0)
root = i3 * i2
self.assertEqual(multiply_numerics(root, (Scope(root), i3, i2)), 6)
root = f3 * i2
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,
(i3, i2, 3, 2)), a * 6 * b)
root = a * i3 * i2 * b
self.assertEqualNodes(multiply_numerics(root,
(Scope(root), i3, i2)), a * 6 * b)
def test_multiply_numerics_negation(self):
l1_neg, l2 = root = tree('-1 * 2')
self.assertEqualNodes(multiply_numerics(root, (l1_neg, l2, -1, 2)),
-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)
self.assertEqualNodes(multiply_numerics(root, (Scope(root), l1_neg,
l2)), -l2)
l1, mul = root = tree('1 + -2 * 3')
root, l6 = tree('1 + -2 * 3,6')
l1, mul = root
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')
rest, mul_neg = root
l5_neg, l6 = mul = mul_neg[0]
self.assertEqualNodes(multiply_numerics(mul, (l5_neg, l6, 5, 6)), l30)
rest, mul = root
l5_neg, l6 = mul
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