Commit 261300cc authored by Taddeus Kroes's avatar Taddeus Kroes

add_exponents in powers rules now supports negated iedntifiers.

parent a193b4c2
from itertools import combinations from itertools import combinations
from ..node import ExpressionNode as N, ExpressionLeaf as L, Scope, \ from ..node import ExpressionNode as N, ExpressionLeaf as L, Scope, \
OP_MUL, OP_DIV, OP_POW, OP_ADD OP_MUL, OP_DIV, OP_POW, OP_ADD, negate
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
...@@ -12,6 +12,7 @@ def match_add_exponents(node): ...@@ -12,6 +12,7 @@ def match_add_exponents(node):
a * a^q -> a^(1 + q) a * a^q -> a^(1 + q)
a^p * a -> a^(p + 1) a^p * a -> a^(p + 1)
a * a -> a^(1 + 1) a * a -> a^(1 + 1)
-a * a^q -> -a^(1 + q)
""" """
assert node.is_op(OP_MUL) assert node.is_op(OP_MUL)
...@@ -20,12 +21,12 @@ def match_add_exponents(node): ...@@ -20,12 +21,12 @@ def match_add_exponents(node):
scope = Scope(node) scope = Scope(node)
for n in scope: for n in scope:
# Order powers by their roots, e.g. a^p and a^q are put in the same
# list because of the mutual 'a'
if n.is_identifier(): if n.is_identifier():
s = n s = negate(n, 0)
exponent = L(1) exponent = L(1)
elif n.is_op(OP_POW): elif n.is_op(OP_POW):
# Order powers by their roots, e.g. a^p and a^q are put in the same
# list because of the mutual 'a'
s, exponent = n s, exponent = n
else: # pragma: nocover else: # pragma: nocover
continue continue
...@@ -53,8 +54,10 @@ def add_exponents(root, args): ...@@ -53,8 +54,10 @@ def add_exponents(root, args):
""" """
scope, n0, n1, a, p, q = args scope, n0, n1, a, p, q = args
# TODO: combine exponent negations
# Replace the left node with the new expression # Replace the left node with the new expression
scope.replace(n0, a ** (p + q)) scope.replace(n0, (a ** (p + q)).negate(n0.negated + n1.negated))
# Remove the right node # Remove the right node
scope.remove(n1) scope.remove(n1)
......
...@@ -24,11 +24,14 @@ class TestLeidenOefenopgaveV12(TestCase): ...@@ -24,11 +24,14 @@ class TestLeidenOefenopgaveV12(TestCase):
'x(-72 * x ^ 2 + 96x) + x * -32', 'x(-72 * x ^ 2 + 96x) + x * -32',
'x * -72 * x ^ 2 + x * 96x + x * -32', 'x * -72 * x ^ 2 + x * 96x + x * -32',
'-x * 72 * x ^ 2 + x * 96x + x * -32', '-x * 72 * x ^ 2 + x * 96x + x * -32',
'-x * 72 * x ^ 2 + x ^ (1 + 1) * 96 + x * -32', '-(x ^ (1 + 2)) * 72 + x * 96x + x * -32',
'-x * 72 * x ^ 2 + x ^ 2 * 96 + x * -32', '-(x ^ 3) * 72 + x * 96x + x * -32',
'-x * 72 * x ^ 2 + x ^ 2 * 96 - x * 32']) '-(x ^ 3) * 72 + x ^ (1 + 1) * 96 + x * -32',
# FIXME: '-x ^ (1 + 2) * 72 + x ^ 2 * 96 - x * 32', '-(x ^ 3) * 72 + x ^ 2 * 96 + x * -32',
# FIXME: '-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 + x ^ 2 * 96 - x * 32',
# FIXME: '-72x ^ 3 + 96x ^ 2 - x * 32', # FIXME: '-72x ^ 3 + 96x ^ 2 - x * 32',
# FIXME: '-72x ^ 3 + 96x ^ 2 - 32x']) # FIXME: '-72x ^ 3 + 96x ^ 2 - 32x'])
...@@ -47,6 +47,14 @@ class TestRulesPowers(RulesTestCase): ...@@ -47,6 +47,14 @@ class TestRulesPowers(RulesTestCase):
self.assertEqualPos(possibilities, self.assertEqualPos(possibilities,
[P(root, add_exponents, (Scope(root), n0, n1, a, p, q))]) [P(root, add_exponents, (Scope(root), n0, n1, a, p, q))])
def test_match_add_exponents_negated(self):
a, q = tree('a,q')
n0, n1 = root = (-a) * a ** q
possibilities = match_add_exponents(root)
self.assertEqualPos(possibilities,
[P(root, add_exponents, (Scope(root), n0, n1, a, 1, q))])
def test_match_subtract_exponents_powers(self): def test_match_subtract_exponents_powers(self):
a, p, q = tree('a,p,q') a, p, q = tree('a,p,q')
root = a ** p / a ** q root = a ** p / a ** q
......
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