Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
8 changes: 7 additions & 1 deletion CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,9 @@ New builtins

* ``Arg``
* ``Dispatch``
* ``FullSimplify``
* ``LetterNumber`` #1298. The ``alphabet`` parameter supports only a minimal number of languages.
* ``Nand`` and ``Nor`` logical functions.
* ``Series``, ``O`` and ``SeriesData``
* ``StringReverse``
* Add all of the named colors, e.g. ``Brown`` or ``LighterMagenta``.
Expand All @@ -20,19 +22,23 @@ New builtins
Enhancements
++++++++++++

* a function `evaluate_predicate` allows for a basic predicate evaluation using `$Assumptions`.
* ``Attributes`` accepts a string parameter.
* ``ColorNegate`` for colors is supported.
* ``D`` and ``Derivative`` improvements.
* ``FileNames`` returns a sorted list (#1250).
* ``FindRoot`` now receives several optional parameters like ``Method`` and ``MaxIterations``.
* ``FixedPoint`` now supports the ``SameTest`` option.
* ``FixedPoint`` now supports the ``SameTest`` option.
* ``Prime`` and ``PrimePi`` now accept a list parameter and have the ``NumericFunction`` attribute.
* ``ReplaceRepeated`` and ``FixedPoint`` now supports the ``MaxIteration`` option (#1260).
* ``Simplify`` performs a more sophisticated set of simplifications.
* ``Simplify`` accepts a second parameter that temporarily overwrites ``$Assumptions``.
* ``StringTake`` now accepts form containing a list of strings and specification (#1297).
* ``Table`` [*expr*, *n*] is supported.
* ``ToString`` accepts an optional *form* parameter.
* ``ToExpression`` handles multi-line string input
* The implementation of Streams was redone.


Bug fixes
+++++++++
Expand Down
66 changes: 63 additions & 3 deletions mathics/builtin/algebra.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,21 +3,26 @@
Algebraic Manipulation
"""


from mathics.version import __version__ # noqa used in loading to check consistency.

from mathics.builtin.base import Builtin
from mathics.core.expression import (
Atom,
Expression,
Integer,
Integer0,
Integer1,
Number,
Symbol,
SymbolFalse,
SymbolList,
SymbolNull,
SymbolTrue,
)
from mathics.core.convert import from_sympy, sympy_symbol_prefix
from mathics.builtin.scoping import dynamic_scoping
from mathics.builtin.inference import evaluate_predicate

import sympy

Expand Down Expand Up @@ -287,6 +292,8 @@ class Simplify(Builtin):
<dl>
<dt>'Simplify[$expr$]'
<dd>simplifies $expr$.
<dt>'Simplify[$expr$, $assump$]'
<dd>simplifies $expr$ assuming $assump$ instead of $Assumptions$.
</dl>

>> Simplify[2*Sin[x]^2 + 2*Cos[x]^2]
Expand All @@ -296,6 +303,14 @@ class Simplify(Builtin):
>> Simplify[f[x]]
= f[x]

Simplify over conditional expressions uses $Assumptions, or $assump$
to evaluate the condition:
>> $Assumptions={a <= 0};
>> Simplify[ConditionalExpression[1, a > 0]]
= Undefined
>> Simplify[ConditionalExpression[1, a > 0], { a > 0 }]
= 1

#> Simplify[a*x^2+b*x^2]
= x ^ 2 (a + b)

Expand All @@ -307,11 +322,31 @@ class Simplify(Builtin):
rules = {
"Simplify[list_List]": "Simplify /@ list",
"Simplify[rule_Rule]": "Simplify /@ rule",
"Simplify[eq_Equal]": "Simplify /@ eq",
"Simplify[list_List, assum_]": "Simplify[#1, assum]& /@ list",
"Simplify[rule_Rule, assum_]": "Simplify[#1, assum]& /@ rule",
"Simplify[0^a_, assum_]": "ConditionalExpression[0,Simplify[a>0]]",
"Simplify[b_^a_, assum_]": "ConditionalExpression[b,Simplify[{Or[a>0, b!=0]}]]",
}

def apply_assuming(self, expr, assumptions, evaluation):
"%(name)s[expr_, assumptions_]"
assumptions = assumptions.evaluate(evaluation)
return dynamic_scoping(
lambda ev: self.apply(expr, ev),
{"System`$Assumptions": assumptions},
evaluation,
)

def apply(self, expr, evaluation):
"Simplify[expr_]"
"%(name)s[expr_]"
# Check first if we are dealing with a logic expression...
expr = evaluate_predicate(expr, evaluation)
if expr.is_atom():
return expr
# else, use sympy:
leaves = [self.apply(leaf, evaluation) for leaf in expr._leaves]
head = self.apply(expr.get_head(), evaluation)
expr = Expression(head, *leaves)

sympy_expr = expr.to_sympy()
if sympy_expr is None:
Expand All @@ -320,6 +355,31 @@ def apply(self, expr, evaluation):
return from_sympy(sympy_result)


class FullSimplify(Simplify):
"""
<dl>
<dt>'FullSimplify[$expr$]'
<dd>simplifies $expr$ using an extended set of simplification rules.
<dt>'FullSimplify[$expr$, $assump$]'
<dd>simplifies $expr$ assuming $assump$ instead of $Assumptions$.
</dl>
TODO: implement the extension. By now, this does the same than Simplify...

>> FullSimplify[2*Sin[x]^2 + 2*Cos[x]^2]
= 2

"""

rules = {
"FullSimplify[list_List]": "FullSimplify /@ list",
"FullSimplify[rule_Rule]": "FullSimplify /@ rule",
"FullSimplify[eq_Equal]": "FullSimplify /@ eq",
"FullSimplify[list_List, assum_]": "FullSimplify[#1, assum]& /@ list",
"FullSimplify[rule_Rule, assum_]": "FullSimplify[#1, assum]& /@ rule",
"FullSimplify[eq_Equal, assum_]": "FullSimplify[#1, assum]& /@ eq",
}


class Together(Builtin):
"""
<dl>
Expand Down Expand Up @@ -1263,7 +1323,7 @@ def apply(self, expr, form, evaluation):
if expr == Integer(0):
return Expression("List")
elif e_null and f_null:
return Expression("List", Integer(0))
return Expression(SymbolList, Integer0)
elif e_null and not f_null:
return Expression("List", SymbolNull)
elif f_null:
Expand Down
Loading