Commit a3de7119 authored by Taddeus Kroes's avatar Taddeus Kroes

Generalized structure of sort rules.

parent 77ae42a0
......@@ -181,6 +181,9 @@ class ExpressionBase(object):
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):
"""
Check strict inequivalence, using the strict equivalence operator.
......
......@@ -14,7 +14,7 @@ from .fractions import match_constant_division, match_add_fractions, \
match_extract_fraction_terms, match_division_in_denominator
from .negation import match_negated_factor, match_negate_polynome, \
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, \
match_half_pi_subtraction, match_standard_radian
from .derivatives import match_zero_derivative, \
......@@ -39,8 +39,8 @@ RULES = {
match_add_logarithms],
OP_MUL: [match_multiply_numerics, match_expand, match_add_exponents,
match_multiply_zero, match_negated_factor,
match_sort_multiplicants, match_multiply_fractions,
match_factor_in_multiplicant],
match_multiply_fractions, match_factor_in_multiplicant,
match_sort_molinome],
OP_DIV: [match_subtract_exponents, match_divide_numerics,
match_constant_division, match_divide_fractions,
match_negated_division, match_extract_fraction_terms,
......
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, \
raise_numerics, remove_zero, multiply_numerics, add_numerics
from .logarithmic import factor_in_exponent_multiplicant, \
......@@ -36,7 +36,7 @@ LOW = [
# Sorting expression terms has a low priority because it is assumed to
# 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 ..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)
for i, n in enumerate(scope[1:]):
left_nb = scope[i]
return [P(node, swap_factors, (scope, l, r))
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):
scope, constant, destination = args
def swap_factors(root, args):
"""
left * right
"""
scope, left, right = args
scope.replace(destination, constant * destination)
scope.remove(constant)
scope.replace(left, N(root.op, right, left))
scope.remove(right)
return scope.as_nary_node()
MESSAGES[move_constant] = \
_('Move constant {2} to the left of the multiplication {0}.')
MESSAGES[swap_factors] = _('Move {2} to the left of {1}.')
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.possibilities import Possibility as P
from tests.rulestestcase import RulesTestCase, tree
......@@ -6,13 +7,23 @@ from tests.rulestestcase import RulesTestCase, tree
class TestRulesSort(RulesTestCase):
def test_match_sort_multiplicants(self):
def test_match_sort_molinome_constant(self):
x, l2 = root = tree('x * 2')
possibilities = match_sort_multiplicants(root)
self.assertEqualPos(possibilities,
[P(root, move_constant, (Scope(root), l2, x))])
self.assertEqualPos(match_sort_molinome(root),
[P(root, swap_factors, (Scope(root), x, l2))])
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')
self.assertEqualNodes(move_constant(root, (Scope(root), l2, x)),
self.assertEqualNodes(swap_factors(root, (Scope(root), x, l2)),
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