Commit a3de7119 authored by Taddeus Kroes's avatar Taddeus Kroes

Generalized structure of sort rules.

parent 77ae42a0
...@@ -181,6 +181,9 @@ class ExpressionBase(object): ...@@ -181,6 +181,9 @@ class ExpressionBase(object):
return s_root < o_root or s_exp < o_exp or s_coeff < o_coeff return s_root < o_root or s_exp < o_exp or s_coeff < o_coeff
def __gt__(self, other):
return other < self
def __ne__(self, other): def __ne__(self, other):
""" """
Check strict inequivalence, using the strict equivalence operator. Check strict inequivalence, using the strict equivalence operator.
......
...@@ -14,7 +14,7 @@ from .fractions import match_constant_division, match_add_fractions, \ ...@@ -14,7 +14,7 @@ from .fractions import match_constant_division, match_add_fractions, \
match_extract_fraction_terms, match_division_in_denominator match_extract_fraction_terms, match_division_in_denominator
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_multiplicants from .sort import match_sort_polynome, match_sort_molinome
from .goniometry import match_add_quadrants, match_negated_parameter, \ from .goniometry import match_add_quadrants, match_negated_parameter, \
match_half_pi_subtraction, match_standard_radian match_half_pi_subtraction, match_standard_radian
from .derivatives import match_zero_derivative, \ from .derivatives import match_zero_derivative, \
...@@ -39,8 +39,8 @@ RULES = { ...@@ -39,8 +39,8 @@ RULES = {
match_add_logarithms], match_add_logarithms],
OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents, OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents,
match_multiply_zero, match_negated_factor, match_multiply_zero, match_negated_factor,
match_sort_multiplicants, match_multiply_fractions, match_multiply_fractions, match_factor_in_multiplicant,
match_factor_in_multiplicant], match_sort_molinome],
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,
......
from .factors import expand_double, expand_single from .factors import expand_double, expand_single
from .sort import move_constant from .sort import swap_factors
from .numerics import multiply_one, multiply_zero, reduce_fraction_constants, \ from .numerics import multiply_one, multiply_zero, reduce_fraction_constants, \
raise_numerics, remove_zero, multiply_numerics, add_numerics raise_numerics, remove_zero, multiply_numerics, add_numerics
from .logarithmic import factor_in_exponent_multiplicant, \ from .logarithmic import factor_in_exponent_multiplicant, \
...@@ -36,7 +36,7 @@ LOW = [ ...@@ -36,7 +36,7 @@ LOW = [
# Sorting expression terms has a low priority because it is assumed to # Sorting expression terms has a low priority because it is assumed to
# be handled by the user # be handled by the user
move_constant, swap_factors,
] ]
......
from ..node import Scope, OP_MUL from .utils import iter_pairs
from ..node import ExpressionNode as N, Scope, OP_ADD, OP_MUL
from ..possibilities import Possibility as P, MESSAGES from ..possibilities import Possibility as P, MESSAGES
from ..translate import _ from ..translate import _
def match_sort_multiplicants(node): def swap_moni((left, right)):
left_num, right_num = left.is_numeric(), right.is_numeric()
if left_num and right_num:
return False
left_var, right_var = left.is_variable(), right.is_variable()
if left_var and right_var:
return cmp(left.value, right.value)
if left_var and right_num:
return True
def swap_poly((left, right)):
pass
def match_sort_polynome(node):
""" """
Sort multiplicant factors by swapping
x * 2 -> 2x
""" """
assert node.is_op(OP_MUL) assert node.is_op(OP_ADD)
p = []
scope = Scope(node) scope = Scope(node)
for i, n in enumerate(scope[1:]): return [P(node, swap_factors, (scope, l, r))
left_nb = scope[i] for l, r in filter(swap_poly, iter_pairs(scope))]
if n.is_numeric() and not left_nb.is_numeric():
p.append(P(node, move_constant, (scope, n, left_nb)))
return p def match_sort_molinome(node):
"""
x * 2 -> 2x # variable > number
x ^ 2 * x ^ 3 -> x ^ 3 * x ^ 2 # exponents
yx -> xy # alphabetically
"""
assert node.is_op(OP_MUL)
scope = Scope(node)
return [P(node, swap_factors, (scope, l, r))
for l, r in filter(swap_moni, iter_pairs(scope))]
def move_constant(root, args): def swap_factors(root, args):
scope, constant, destination = args """
left * right
"""
scope, left, right = args
scope.replace(destination, constant * destination) scope.replace(left, N(root.op, right, left))
scope.remove(constant) scope.remove(right)
return scope.as_nary_node() return scope.as_nary_node()
MESSAGES[move_constant] = \ MESSAGES[swap_factors] = _('Move {2} to the left of {1}.')
_('Move constant {2} to the left of the multiplication {0}.')
from src.rules.sort import match_sort_multiplicants, move_constant from src.rules.sort import match_sort_polynome, swap_factors, \
match_sort_molinome, iter_pairs
from src.node import Scope from src.node import Scope
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
...@@ -6,13 +7,23 @@ from tests.rulestestcase import RulesTestCase, tree ...@@ -6,13 +7,23 @@ from tests.rulestestcase import RulesTestCase, tree
class TestRulesSort(RulesTestCase): class TestRulesSort(RulesTestCase):
def test_match_sort_multiplicants(self): def test_match_sort_molinome_constant(self):
x, l2 = root = tree('x * 2') x, l2 = root = tree('x * 2')
possibilities = match_sort_multiplicants(root) self.assertEqualPos(match_sort_molinome(root),
self.assertEqualPos(possibilities, [P(root, swap_factors, (Scope(root), x, l2))])
[P(root, move_constant, (Scope(root), l2, x))])
def test_move_constant(self): root = tree('2x')
self.assertEqualPos(match_sort_molinome(root), [])
#def test_match_sort_molinome_variables(self):
# y, x = root = tree('yx')
# self.assertEqualPos(match_sort_molinome(root),
# [P(root, swap_factors, (Scope(root), y, x))])
# root = tree('xy')
# self.assertEqualPos(match_sort_molinome(root), [])
def test_swap_factors(self):
x, l2 = root = tree('x * 2') x, l2 = root = tree('x * 2')
self.assertEqualNodes(move_constant(root, (Scope(root), l2, x)), self.assertEqualNodes(swap_factors(root, (Scope(root), x, l2)),
l2 * x) l2 * x)
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