Commit 8d6d4788 authored by Taddeus Kroes's avatar Taddeus Kroes

Removed match_negate_group, replaced it with some more generic rules.

parent fddfbe2d
...@@ -10,17 +10,19 @@ from .numerics import match_divide_numerics, match_multiply_numerics, \ ...@@ -10,17 +10,19 @@ from .numerics import match_divide_numerics, match_multiply_numerics, \
match_multiply_zero match_multiply_zero
from .fractions import match_constant_division, match_add_constant_fractions, \ from .fractions import match_constant_division, match_add_constant_fractions, \
match_expand_and_add_fractions match_expand_and_add_fractions
from .negation import match_negate_group, match_negated_division from .negation import match_negated_factor, match_negate_polynome, \
match_negated_division
RULES = { RULES = {
OP_ADD: [match_add_constant_fractions, match_combine_polynomes, \ OP_ADD: [match_add_constant_fractions, match_combine_polynomes, \
match_combine_groups], match_combine_groups],
OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents, \ OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents, \
match_expand_and_add_fractions, match_multiply_zero], match_expand_and_add_fractions, match_multiply_zero,
match_negated_factor],
OP_DIV: [match_subtract_exponents, match_divide_numerics, \ OP_DIV: [match_subtract_exponents, match_divide_numerics, \
match_constant_division, match_negated_division], match_constant_division, match_negated_division],
OP_POW: [match_multiply_exponents, match_duplicate_exponent, \ OP_POW: [match_multiply_exponents, match_duplicate_exponent, \
match_remove_negative_exponent, match_exponent_to_root, \ match_remove_negative_exponent, match_exponent_to_root, \
match_extend_exponent], match_extend_exponent],
OP_NEG: [match_negate_group], OP_NEG: [match_negate_polynome],
} }
from ..node import get_scope, nary_node, OP_ADD, OP_MUL, OP_DIV from ..node import Scope, nary_node, OP_ADD, OP_MUL, OP_DIV
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
def match_negate_group(node): def match_negated_factor(node):
""" """
--a -> a This rule assures that negations in the scope of a multiplication are
-(a * ... * -b) -> ab brought `outside', to the multiplication itself.
-(a + b + ... + z) -> -a + -b + ... + -z
Example:
a * -b -> -(ab)
""" """
assert node.negated assert node.is_op(OP_MUL)
if node.negated == 2: p = []
# --a scope = Scope(node)
return [P(node, double_negation, (node,))]
if not node.is_leaf: for factor in scope:
scope = get_scope(node) if factor.negated:
p.append(P(node, negated_factor, (scope, factor)))
if node.is_op(OP_MUL) and any(map(lambda n: n.negated, scope)): return p
# -(-a)b
return [P(node, negate_group, (node, scope))]
if node.is_op(OP_ADD):
# -(ab + c) -> -ab - c
# -(-ab + c) -> ab - c
return [P(node, negate_polynome, (node, scope))]
return [] def negated_factor(root, args):
"""
a * -b -> -(ab)
"""
scope, factor = args
scope.replace(factor, +factor)
return -scope.as_nary_node()
def negate_group(root, args): def match_negate_polynome(node):
""" """
-(a * -3c) -> a * 3c --a -> a
-(a * ... * -b) -> ab -(a + b) -> -a - b
""" """
node, scope = args #assert node.negated
for i, n in enumerate(scope): p = []
if n.negated:
scope[i] = n.reduce_negation() if node.negated == 2:
# --a
p.append(P(node, double_negation, ()))
if node.is_op(OP_ADD):
# -(a + b) -> -a - b
p.append(P(node, negate_polynome, ()))
return p
return nary_node('*', scope).reduce_negation()
def double_negation(root, args):
"""
--a -> a
"""
return root.reduce_negation(2)
MESSAGES[negate_group] = _('Apply negation to the polynome {1[0]}.')
MESSAGES[double_negation] = _('Remove double negation in {1}.')
def negate_polynome(root, args): def negate_polynome(root, args):
""" """
-(-ab + ... + c) -> --ab + ... + -c -(a + b) -> -a - b
""" """
node, scope = args scope = Scope(root)
# Negate each group # Negate each group
for i, n in enumerate(scope): for i, n in enumerate(scope):
scope[i] = -n scope[i] = -n
return nary_node('+', scope) return +scope.as_nary_node()
MESSAGES[negate_polynome] = _('Apply negation to the subexpression {1[0]}.') MESSAGES[negate_polynome] = _('Apply negation to the polynome {1}.')
def double_negation(root, args): #def negate_group(root, args):
""" # """
--a -> a # -(a * -3c) -> a * 3c
""" # -(a * ... * -b) -> ab
return args[0].reduce_negation(2) # """
# node, scope = args
#
MESSAGES[double_negation] = _('Remove double negation in {1}.') # for i, n in enumerate(scope):
# if n.negated:
# scope[i] = n.reduce_negation()
#
# return nary_node('*', scope).reduce_negation()
#
#
#MESSAGES[negate_polynome] = _('Apply negation to the subexpression {1[0]}.')
def match_negated_division(node): def match_negated_division(node):
...@@ -82,7 +105,7 @@ def match_negated_division(node): ...@@ -82,7 +105,7 @@ def match_negated_division(node):
a, b = node a, b = node
if a.negated and b.negated: if a.negated and b.negated:
return [P(node, double_negated_division, (node,))] return [P(node, double_negated_division, ())]
elif a.negated: elif a.negated:
return [P(node, single_negated_division, (+a, b))] return [P(node, single_negated_division, (+a, b))]
elif b.negated: elif b.negated:
...@@ -111,7 +134,7 @@ def double_negated_division(root, args): ...@@ -111,7 +134,7 @@ def double_negated_division(root, args):
""" """
-a / -b -> a / b -a / -b -> a / b
""" """
a, b = args[0] a, b = root
return +a / +b return +a / +b
......
from src.rules.negation import match_negated_factor, negated_factor, \
from src.rules.negation import match_negated_division, \ match_negate_polynome, negate_polynome, double_negation, \
single_negated_division, double_negated_division match_negated_division, single_negated_division, \
double_negated_division
from src.node import Scope
from src.possibilities import Possibility as P from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree from tests.rulestestcase import RulesTestCase, tree
class TestRulesNegation(RulesTestCase): class TestRulesNegation(RulesTestCase):
def test_match_negated_factor(self):
a, b = root = tree('a * -b')
self.assertEqualPos(match_negated_factor(root),
[P(root, negated_factor, (Scope(root), b))])
(a, b), c = root = tree('a * -b * -c')
scope = Scope(root)
self.assertEqualPos(match_negated_factor(root),
[P(root, negated_factor, (scope, b)),
P(root, negated_factor, (scope, c))])
def test_negated_factor(self):
a, b = root = tree('a * -b')
self.assertEqualNodes(negated_factor(root, (Scope(root), b)),
-(a * +b))
(a, b), c = root = tree('a * -b * -c')
scope = Scope(root)
self.assertEqualNodes(negated_factor(root, (scope, b)),
-(a * +b * c))
self.assertEqualNodes(negated_factor(root, (scope, c)),
-(a * b * +c))
def test_match_negate_polynome(self):
root = tree('--a')
self.assertEqualPos(match_negate_polynome(root),
[P(root, double_negation, ())])
root = tree('-(a + b)')
self.assertEqualPos(match_negate_polynome(root),
[P(root, negate_polynome, ())])
a, b = root = tree('-(a - -b)')
self.assertEqualPos(match_negate_polynome(root),
[P(root, double_negation, (b,)),
P(root, negate_polynome, ())])
def test_negate_polynome(self):
a, b = root = tree('-(a + b)')
self.assertEqualNodes(negate_polynome(root, ()), -a + -b)
a, b = root = tree('-(a - b)')
self.assertEqualNodes(negate_polynome(root, ()), -a + -b)
def test_match_negated_division_none(self): def test_match_negated_division_none(self):
self.assertEqual(match_negated_division(tree('1 / 2')), []) self.assertEqual(match_negated_division(tree('1 / 2')), [])
...@@ -26,7 +72,7 @@ class TestRulesNegation(RulesTestCase): ...@@ -26,7 +72,7 @@ class TestRulesNegation(RulesTestCase):
possibilities = match_negated_division(root) possibilities = match_negated_division(root)
self.assertEqualPos(possibilities, self.assertEqualPos(possibilities,
[P(root, double_negated_division, (root,))]) [P(root, double_negated_division, ())])
def test_single_negated_division(self): def test_single_negated_division(self):
l1, l2 = root = tree('-1 / 2') l1, l2 = root = tree('-1 / 2')
...@@ -40,5 +86,5 @@ class TestRulesNegation(RulesTestCase): ...@@ -40,5 +86,5 @@ class TestRulesNegation(RulesTestCase):
def test_double_negated_division(self): def test_double_negated_division(self):
l1, l2 = root = tree('-1 / -2') l1, l2 = root = tree('-1 / -2')
self.assertEqualNodes(double_negated_division(root, (root,)), self.assertEqualNodes(double_negated_division(root, ()),
+l1 / +l2) +l1 / +l2)
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