absolute.py 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697
  1. from .utils import evals_to_numeric
  2. from ..node import OP_ABS, OP_SQRT, OP_MUL, OP_POW, Scope, absolute, sqrt
  3. from ..possibilities import Possibility as P, MESSAGES
  4. from ..translate import _
  5. def match_factor_out_abs_term(node):
  6. """
  7. |-a| -> |a|
  8. |c| and c in Z -> eval(|c|)
  9. |sqrt a| -> sqrt |a|
  10. |ab| -> |a||b|
  11. |abc| -> |a||bc|
  12. |abc| -> |c||ab|
  13. |abc| -> |b||ac|
  14. |a ^ c| and eval(c) in Z -> |a| ^ c
  15. """
  16. assert node.is_op(OP_ABS)
  17. exp = node[0]
  18. if exp.negated:
  19. return [P(node, remove_absolute_negation)]
  20. if exp.is_numeric():
  21. return [P(node, absolute_numeric)]
  22. if exp.is_op(OP_MUL):
  23. scope = Scope(exp)
  24. return [P(node, factor_out_abs_term, (scope, n)) for n in scope]
  25. if exp.is_op(OP_SQRT):
  26. return [P(node, factor_out_abs_sqrt)]
  27. if exp.is_op(OP_POW) and evals_to_numeric(exp[1]):
  28. return [P(node, factor_out_abs_exponent)]
  29. return []
  30. def remove_absolute_negation(root, args):
  31. """
  32. |-a| -> |a|
  33. """
  34. return absolute(+root[0]).negate(root.negated)
  35. MESSAGES[remove_absolute_negation] = \
  36. _('The absolute value of a negated expression is the expression.')
  37. def absolute_numeric(root, args):
  38. """
  39. |c| and c in Z -> eval(|c|)
  40. """
  41. return root[0].negate(root.negated)
  42. MESSAGES[absolute_numeric] = _('The absolute value of {0[0]} is {0[0]}.')
  43. def factor_out_abs_term(root, args):
  44. """
  45. |ab| -> |a||b|
  46. """
  47. scope, a = args
  48. scope.remove(a)
  49. return (absolute(a) * absolute(scope.as_nary_node())).negate(root.negated)
  50. MESSAGES[factor_out_abs_term] = _('Split the multplication in absolute ' \
  51. 'value {0} into a multiplication of absolute values.')
  52. def factor_out_abs_sqrt(root, args):
  53. """
  54. |sqrt a| -> sqrt|a|
  55. """
  56. return sqrt(absolute(root[0][0])).negate(root.negated)
  57. MESSAGES[factor_out_abs_sqrt] = \
  58. _('Move the absolute value in {0} to the operand of the square root.')
  59. def factor_out_abs_exponent(root, args):
  60. """
  61. |a ^ c| and eval(c) in Z -> |a| ^ c
  62. """
  63. a, c = root[0]
  64. return (absolute(a) ** c).negate(root.negated)
  65. MESSAGES[factor_out_abs_exponent] = _('Factor out the exponent in {0}.')