Skip to content
Snippets Groups Projects
Commit ef8ffd44 authored by Taddeüs Kroes's avatar Taddeüs Kroes
Browse files

Added new rule for eliminating fractions from fractions.

parent 015cd97f
No related branches found
No related tags found
No related merge requests found
......@@ -26,7 +26,8 @@ from .numerics import match_add_numerics, match_divide_numerics, \
from .fractions import match_constant_division, match_add_fractions, \
match_multiply_fractions, match_divide_fractions, \
match_extract_fraction_terms, match_division_in_denominator, \
match_combine_fractions, match_remove_division_negation
match_combine_fractions, match_remove_division_negation, \
match_fraction_in_division
from .negation import match_negated_factor, match_negate_polynome, \
match_negated_division
from .sort import match_sort_polynome, match_sort_monomial
......@@ -59,7 +60,7 @@ RULES = {
OP_DIV: [match_subtract_exponents, match_divide_numerics,
match_constant_division, match_divide_fractions,
match_negated_division, match_extract_fraction_terms,
match_division_in_denominator,
match_division_in_denominator, match_fraction_in_division,
match_remove_division_negation],
OP_POW: [match_multiply_exponents, match_duplicate_exponent,
match_raised_fraction, match_remove_negative_child,
......
......@@ -534,3 +534,56 @@ def remove_division_negation(root, args):
MESSAGES[remove_division_negation] = \
_('Move negation from fraction {0} to polynome {2}.')
def match_fraction_in_division(node):
"""
(1 / a * b) / c -> b / (ac)
c / (1 / a * b) -> (ac) / b
"""
assert node.is_op(OP_DIV)
nom, denom = node
p = []
if nom.is_op(OP_MUL):
scope = Scope(nom)
for n in scope:
if n.is_op(OP_DIV) and n[0] == 1:
p.append(P(node, fraction_in_division, (True, scope, n)))
if denom.is_op(OP_MUL):
scope = Scope(denom)
for n in scope:
if n.is_op(OP_DIV) and n[0] == 1:
p.append(P(node, fraction_in_division, (False, scope, n)))
return p
def fraction_in_division(root, args):
"""
(1 / a * b) / c -> b / (ac)
c / (1 / a * b) -> (ac) / b
"""
is_nominator, scope, fraction = args
nom, denom = root
if fraction.negated:
scope.replace(fraction, fraction[0].negate(fraction.negated))
else:
scope.remove(fraction)
if is_nominator:
nom = scope.as_nary_node()
denom = fraction[1] * denom
else:
nom = fraction[1] * nom
denom = scope.as_nary_node()
return negate(nom / denom, root.negated)
MESSAGES[fraction_in_division] = \
_('Multiply both sides of fraction {0} with {3[1]}.')
......@@ -208,16 +208,16 @@ class TestLeidenOefenopgave(TestCase):
'1 / (4x)',
])
#def test_4_6(self):
# self.assertRewrite([
# '(3 / x^2) / (x / 7)',
# '3 / x ^ 2 / (1 / 7 * x)',
# '3 / (x ^ 2 * 1 / 7 * x)',
# '3 / (x ^ (2 + 1)1 / 7)',
# '3 / (x ^ 3 * 1 / 7)',
# '3 / (1 / 7 * x ^ 3)',
# '21 / x^3',
# ])
def test_4_6(self):
self.assertRewrite([
'(3 / x^2) / (x / 7)',
'3 / x ^ 2 / (1 / 7 * x)',
'3 / (x ^ 2 * 1 / 7x)',
'3 / (x ^ (2 + 1)1 / 7)',
'3 / (x ^ 3 * 1 / 7)',
'(7 * 3) / x ^ 3',
'21 / x ^ 3',
])
def test_4_7(self):
self.assertEvaluates('1 / x + 2 / (x + 1)', '(3x + 1) / (x(x + 1))')
......@@ -20,7 +20,8 @@ from src.rules.fractions import match_constant_division, division_by_one, \
constant_to_fraction, extract_nominator_term, extract_fraction_terms, \
match_division_in_denominator, multiply_with_term, \
divide_fraction_by_term, match_combine_fractions, combine_fractions, \
match_remove_division_negation, remove_division_negation
match_remove_division_negation, remove_division_negation, \
match_fraction_in_division, fraction_in_division
from src.node import ExpressionNode as N, Scope, OP_MUL
from src.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree
......@@ -359,3 +360,26 @@ class TestRulesFractions(RulesTestCase):
a, (b, c) = root = tree('-a / (-b + c)')
self.assertEqual(remove_division_negation(root, (False, root[1])),
+a / (-b - c))
def test_match_fraction_in_division(self):
(fr, b), c = root = tree('(1 / a * b) / c')
self.assertEqualPos(match_fraction_in_division(root),
[P(root, fraction_in_division, (True, Scope(root[0]), fr))])
c, (fr, b) = root = tree('c / (1 / a * b)')
self.assertEqualPos(match_fraction_in_division(root),
[P(root, fraction_in_division, (False, Scope(root[1]), fr))])
(fr0, b), (fr1, d) = root = tree('(1 / a * b) / (1 / c * d)')
self.assertEqualPos(match_fraction_in_division(root),
[P(root, fraction_in_division, (True, Scope(root[0]), fr0)),
P(root, fraction_in_division, (False, Scope(root[1]), fr1))])
def test_fraction_in_division(self):
root, expected = tree('(1 / a * b) / c, b / (ac)')
self.assertEqual(fraction_in_division(root,
(True, Scope(root[0]), root[0][0])), expected)
root, expected = tree('c / (1 / a * b), (ac) / b')
self.assertEqual(fraction_in_division(root,
(False, Scope(root[1]), root[1][0])), expected)
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