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, \ ...@@ -26,7 +26,8 @@ from .numerics import match_add_numerics, match_divide_numerics, \
from .fractions import match_constant_division, match_add_fractions, \ from .fractions import match_constant_division, match_add_fractions, \
match_multiply_fractions, match_divide_fractions, \ match_multiply_fractions, match_divide_fractions, \
match_extract_fraction_terms, match_division_in_denominator, \ 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, \ from .negation import match_negated_factor, match_negate_polynome, \
match_negated_division match_negated_division
from .sort import match_sort_polynome, match_sort_monomial from .sort import match_sort_polynome, match_sort_monomial
...@@ -59,7 +60,7 @@ RULES = { ...@@ -59,7 +60,7 @@ RULES = {
OP_DIV: [match_subtract_exponents, match_divide_numerics, OP_DIV: [match_subtract_exponents, match_divide_numerics,
match_constant_division, match_divide_fractions, match_constant_division, match_divide_fractions,
match_negated_division, match_extract_fraction_terms, match_negated_division, match_extract_fraction_terms,
match_division_in_denominator, match_division_in_denominator, match_fraction_in_division,
match_remove_division_negation], match_remove_division_negation],
OP_POW: [match_multiply_exponents, match_duplicate_exponent, OP_POW: [match_multiply_exponents, match_duplicate_exponent,
match_raised_fraction, match_remove_negative_child, match_raised_fraction, match_remove_negative_child,
......
...@@ -534,3 +534,56 @@ def remove_division_negation(root, args): ...@@ -534,3 +534,56 @@ def remove_division_negation(root, args):
MESSAGES[remove_division_negation] = \ MESSAGES[remove_division_negation] = \
_('Move negation from fraction {0} to polynome {2}.') _('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): ...@@ -208,16 +208,16 @@ class TestLeidenOefenopgave(TestCase):
'1 / (4x)', '1 / (4x)',
]) ])
#def test_4_6(self): def test_4_6(self):
# self.assertRewrite([ self.assertRewrite([
# '(3 / x^2) / (x / 7)', '(3 / x^2) / (x / 7)',
# '3 / x ^ 2 / (1 / 7 * x)', '3 / x ^ 2 / (1 / 7 * x)',
# '3 / (x ^ 2 * 1 / 7 * x)', '3 / (x ^ 2 * 1 / 7x)',
# '3 / (x ^ (2 + 1)1 / 7)', '3 / (x ^ (2 + 1)1 / 7)',
# '3 / (x ^ 3 * 1 / 7)', '3 / (x ^ 3 * 1 / 7)',
# '3 / (1 / 7 * x ^ 3)', '(7 * 3) / x ^ 3',
# '21 / x^3', '21 / x ^ 3',
# ]) ])
def test_4_7(self): def test_4_7(self):
self.assertEvaluates('1 / x + 2 / (x + 1)', '(3x + 1) / (x(x + 1))') 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, \ ...@@ -20,7 +20,8 @@ from src.rules.fractions import match_constant_division, division_by_one, \
constant_to_fraction, extract_nominator_term, extract_fraction_terms, \ constant_to_fraction, extract_nominator_term, extract_fraction_terms, \
match_division_in_denominator, multiply_with_term, \ match_division_in_denominator, multiply_with_term, \
divide_fraction_by_term, match_combine_fractions, combine_fractions, \ 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.node import ExpressionNode as N, Scope, OP_MUL
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
...@@ -359,3 +360,26 @@ class TestRulesFractions(RulesTestCase): ...@@ -359,3 +360,26 @@ class TestRulesFractions(RulesTestCase):
a, (b, c) = root = tree('-a / (-b + c)') a, (b, c) = root = tree('-a / (-b + c)')
self.assertEqual(remove_division_negation(root, (False, root[1])), self.assertEqual(remove_division_negation(root, (False, root[1])),
+a / (-b - c)) +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