Commit a77a8977 authored by Taddeus Kroes's avatar Taddeus Kroes

Fixed scope index replacement issue in fraction rule.

parent 91a26452
...@@ -592,7 +592,7 @@ class Scope(object): ...@@ -592,7 +592,7 @@ class Scope(object):
del self.nodes[i] del self.nodes[i]
# Update remaining scope indices # Update remaining scope indices
for n in self[max(i, 1):]: for n in self.nodes[i:]:
n.scope_index -= 1 n.scope_index -= 1
except AttributeError: except AttributeError:
raise ValueError('Node "%s" is not in the scope of "%s".' raise ValueError('Node "%s" is not in the scope of "%s".'
...@@ -603,6 +603,14 @@ class Scope(object): ...@@ -603,6 +603,14 @@ class Scope(object):
def as_nary_node(self): def as_nary_node(self):
return nary_node(self.node.op, self.nodes).negate(self.node.negated) return nary_node(self.node.op, self.nodes).negate(self.node.negated)
#return negate(nary_node(self.node.op, self.nodes), self.node.negated)
def all_except(self, node):
before = range(0, node.scope_index)
after = range(node.scope_index + 1, len(self))
nodes = [self[i] for i in before + after]
return nary_node(self.node.op, nodes).negate(self.node.negated)
def nary_node(operator, scope): def nary_node(operator, scope):
......
...@@ -222,12 +222,12 @@ def multiply_with_fraction(root, args): ...@@ -222,12 +222,12 @@ def multiply_with_fraction(root, args):
scope, ab, c = args scope, ab, c = args
a, b = ab a, b = ab
if scope.index(ab) - scope.index(c) < 0: if scope.index(ab) < scope.index(c):
replacement = a * c / b nominator = a * c
else: else:
replacement = c * a / b nominator = c * a
scope.replace(ab, replacement.negate(ab.negated)) scope.replace(ab, negate(nominator / b, ab.negated))
scope.remove(c) scope.remove(c)
return scope.as_nary_node() return scope.as_nary_node()
...@@ -246,7 +246,7 @@ def match_divide_fractions(node): ...@@ -246,7 +246,7 @@ def match_divide_fractions(node):
a / (b / c) -> ac / b a / (b / c) -> ac / b
Note that: Note that:
a / b / (c / d) ->* ad / bd # chain test! a / b / (c / d) => ad / bd
""" """
assert node.is_op(OP_DIV) assert node.is_op(OP_DIV)
...@@ -347,7 +347,12 @@ def match_extract_fraction_terms(node): ...@@ -347,7 +347,12 @@ def match_extract_fraction_terms(node):
# ac / b # ac / b
for n in ifilterfalse(evals_to_numeric, n_scope): for n in ifilterfalse(evals_to_numeric, n_scope):
a_scope = mult_scope(nominator) a_scope = mult_scope(nominator)
a = remove_from_mult_scope(a_scope, n)
#a = remove_from_mult_scope(a_scope, n)
if len(a_scope) == 1:
a = L(1)
else:
a = a_scope.all_except(n)
if evals_to_numeric(a / denominator): if evals_to_numeric(a / denominator):
p.append(P(node, extract_nominator_term, (a, n))) p.append(P(node, extract_nominator_term, (a, n)))
......
...@@ -2,7 +2,7 @@ from itertools import combinations ...@@ -2,7 +2,7 @@ from itertools import combinations
from .utils import greatest_common_divisor, is_numeric_node from .utils import greatest_common_divisor, is_numeric_node
from ..node import ExpressionLeaf as Leaf, Scope, OP_ADD, OP_DIV, OP_MUL, \ from ..node import ExpressionLeaf as Leaf, Scope, OP_ADD, OP_DIV, OP_MUL, \
OP_POW OP_POW, negate
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
...@@ -61,7 +61,7 @@ def add_numerics(root, args): ...@@ -61,7 +61,7 @@ def add_numerics(root, args):
value = c0.actual_value() + c1.actual_value() value = c0.actual_value() + c1.actual_value()
# Replace the left node with the new expression # Replace the left node with the new expression
scope.replace(c0, Leaf(abs(value)).negate(int(value < 0))) scope.replace(c0, Leaf(abs(value), negated=int(value < 0)))
# Remove the right node # Remove the right node
scope.remove(c1) scope.remove(c1)
...@@ -141,7 +141,7 @@ def divide_numerics(root, args): ...@@ -141,7 +141,7 @@ def divide_numerics(root, args):
""" """
n, d = root n, d = root
return Leaf(n.value / d.value).negate(root.negated) return Leaf(n.value / d.value, negated=root.negated)
MESSAGES[divide_numerics] = _('Constant division {0} reduces to a number.') MESSAGES[divide_numerics] = _('Constant division {0} reduces to a number.')
...@@ -248,7 +248,7 @@ def multiply_numerics(root, args): ...@@ -248,7 +248,7 @@ def multiply_numerics(root, args):
scope, c0, c1 = args scope, c0, c1 = args
# Replace the left node with the new expression # Replace the left node with the new expression
substitution = Leaf(c0.value * c1.value).negate(c0.negated + c1.negated) substitution = Leaf(c0.value * c1.value, negated=c0.negated + c1.negated)
scope.replace(c0, substitution) scope.replace(c0, substitution)
# Remove the right node # Remove the right node
...@@ -284,7 +284,7 @@ def raise_numerics(root, args): ...@@ -284,7 +284,7 @@ def raise_numerics(root, args):
""" """
r, e = args r, e = args
return Leaf(r.value ** e.value).negate(r.negated * e.value) return Leaf(r.value ** e.value, negated=r.negated * e.value)
MESSAGES[raise_numerics] = _('Raise constant {1} with {2}.') MESSAGES[raise_numerics] = _('Raise constant {1} with {2}.')
...@@ -205,3 +205,7 @@ def iter_pairs(list_iterable): ...@@ -205,3 +205,7 @@ def iter_pairs(list_iterable):
for i, left in enumerate(list_iterable[:-1]): for i, left in enumerate(list_iterable[:-1]):
yield left, list_iterable[i + 1] yield left, list_iterable[i + 1]
def range_except(start, end, exception):
return range(start, exception) + range(exception + 1, end)
...@@ -2,7 +2,7 @@ from src.rules import utils ...@@ -2,7 +2,7 @@ from src.rules import utils
from src.rules.utils import least_common_multiple, is_fraction, partition, \ from src.rules.utils import least_common_multiple, is_fraction, partition, \
find_variables, first_sorted_variable, find_variable, substitute, \ find_variables, first_sorted_variable, find_variable, substitute, \
divides, dividers, is_prime, prime_dividers, evals_to_numeric, \ divides, dividers, is_prime, prime_dividers, evals_to_numeric, \
iter_pairs iter_pairs, range_except
from tests.rulestestcase import tree, RulesTestCase from tests.rulestestcase import tree, RulesTestCase
...@@ -110,3 +110,8 @@ class TestRulesUtils(RulesTestCase): ...@@ -110,3 +110,8 @@ class TestRulesUtils(RulesTestCase):
self.assertEqual(list(iter_pairs([1, 2])), [(1, 2)]) self.assertEqual(list(iter_pairs([1, 2])), [(1, 2)])
self.assertEqual(list(iter_pairs([1, 2, 3])), [(1, 2), (2, 3)]) self.assertEqual(list(iter_pairs([1, 2, 3])), [(1, 2), (2, 3)])
self.assertEqual(list(iter_pairs([1, 2, 3, 4])), [(1, 2), (2, 3), (3, 4)]) self.assertEqual(list(iter_pairs([1, 2, 3, 4])), [(1, 2), (2, 3), (3, 4)])
def test_range_except(self):
self.assertEqual(range_except(0, 5, 2), [0, 1, 3, 4])
self.assertEqual(range_except(0, 4, 0), [1, 2, 3])
self.assertEqual(range_except(0, 3, 3), [0, 1, 2])
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