Commit ef8ffd44 authored by Taddeüs Kroes's avatar Taddeüs Kroes

Added new rule for eliminating fractions from fractions.

parent 015cd97f
......@@ -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)
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