Skip to content
Snippets Groups Projects
Commit 7d0df6c9 authored by Taddeus Kroes's avatar Taddeus Kroes
Browse files

Added absolute value to linear equation rules.

parent 03feca7a
No related branches found
No related tags found
No related merge requests found
from .utils import find_variable
from .utils import find_variable, evals_to_numeric
from ..node import ExpressionLeaf as L, Scope, OP_EQ, OP_ADD, OP_MUL, OP_DIV, \
eq
eq, OP_ABS
from ..possibilities import Possibility as P, MESSAGES
from ..translate import _
......@@ -23,18 +23,23 @@ def match_move_term(node):
# Multiplication
x / a = b -> x / a * a = b * a # =>* x = a * b
a / x = b -> a / x * x = b * x # =>* x = a / b
-x = b -> -x * -1 = b * -1 # =>* x = -b
-x = b -> -x * -1 = b * -1 # =>* x = -b
# Absolute value
|f(x)| = c and eval(c) in Z -> f(x) = c vv f(x) = -c
"""
assert node.is_op(OP_EQ)
x = find_variable(node)
left, right = node
p = []
# Swap the left and right side if only the right side contains x
if not left.contains(x):
return [P(node, swap_sides)]
# Swap the left and right side if only the right side contains x
if right.contains(x):
p.append(P(node, swap_sides))
p = []
return p
# Bring terms without x to the right
if left.is_op(OP_ADD):
......@@ -62,6 +67,10 @@ def match_move_term(node):
if left.negated:
p.append(P(node, multiply_term, (-L(1),)))
# Split absolute equations into two separate, non-absolute equations
if left.is_op(OP_ABS) and evals_to_numeric(right):
p.append(P(node, split_absolute_equation))
return p
......@@ -117,3 +126,16 @@ def multiply_term(root, args):
MESSAGES[multiply_term] = _('Multiply both sides of the equation with {1}.')
def split_absolute_equation(root, args):
"""
|f(x)| = c and eval(c) in Z -> f(x) = c vv f(x) = -c
"""
(f,), c = root
return eq(f, c) | eq(f, -c)
MESSAGES[split_absolute_equation] = _('Split absolute equation {0} into a ' \
'negative and a positive equation.')
......@@ -3,6 +3,7 @@ import doctest
from src.node import ExpressionNode
from src.parser import Parser
from src.validation import validate
from tests.parser import ParserWrapper
......@@ -73,3 +74,7 @@ class RulesTestCase(unittest.TestCase):
e.args = (e.message,) + e.args[1:]
raise
def assertValidate(self, exp, result):
self.assertTrue(validate(exp, result),
'Validation failed: %s !=> %s')
from src.rules.lineq import match_move_term, swap_sides, subtract_term, \
divide_term, multiply_term
divide_term, multiply_term, split_absolute_equation
from src.node import Scope
from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree
......@@ -41,6 +41,15 @@ class TestRulesLineq(RulesTestCase):
self.assertEqualPos(match_move_term(root),
[P(root, multiply_term, (l1,))])
def test_match_move_term_absolute(self):
root = tree('|x| = 2')
self.assertEqualPos(match_move_term(root),
[P(root, split_absolute_equation)])
root = tree('|x - 1| = 2')
self.assertEqualPos(match_move_term(root),
[P(root, split_absolute_equation)])
def test_swap_sides(self):
root, expect = tree('a = bx, bx = a')
self.assertEqual(swap_sides(root, ()), expect)
......@@ -57,6 +66,13 @@ class TestRulesLineq(RulesTestCase):
root, a, expect = tree('x / a = b, a, x / a * a = b * a')
self.assertEqual(multiply_term(root, (a,)), expect)
def test_split_absolute_equation(self):
root, expect = tree('|x| = 2, x = 2 vv x = -2')
self.assertEqual(split_absolute_equation(root, ()), expect)
# FIXME: following call exeeds recursion limit
# FIXME: self.assertValidate('|x - 1| = 2', 'x = -1 vv x = 3')
def test_match_move_term_chain_negation(self):
self.assertRewrite([
'2x + 3 = -3x - 2',
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment