Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Knot theory fixes #1238

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
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
15 changes: 7 additions & 8 deletions CHANGES.rst
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,6 @@ CHANGES
2.1.1
-----


New builtins
++++++++++++

* ``Dispatch``


Enhancements
++++++++++++

Expand All @@ -24,10 +17,16 @@ Enhancements
Bug fixes
+++++++++


* ``SetTagDelayed`` does not evaluate now the rhs before assignment.
* ``$InstallationDirectory`` starts out Unprotected
* Improvings in the implementation of ``D`` and ``Derivative``.

New builtins
++++++++++++

* ``Dispatch``
* ``Series``, ``O`` and ``SeriesData``

2.1.0
-----

Expand Down
150 changes: 145 additions & 5 deletions mathics/builtin/arithmetic.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,19 +33,20 @@
Symbol,
SymbolComplexInfinity,
SymbolDirectedInfinity,
SymbolFalse,
SymbolInfinity,
SymbolN,
SymbolNull,
SymbolSequence,
SymbolTrue,
SymbolFalse,
SymbolUndefined,
SymbolSequence,
from_mpmath,
from_python,
)
from mathics.core.numbers import min_prec, dps, SpecialValueError

from mathics.builtin.lists import _IterationFunction
from mathics.core.convert import from_sympy, SympyExpression
from mathics.core.convert import from_sympy, SympyExpression, sympy_symbol_prefix


@lru_cache(maxsize=1024)
Expand Down Expand Up @@ -675,7 +676,9 @@ def apply(self, items, evaluation):
Expression("Plus", item.leaves[1], leaves[-1].leaves[1]),
)
elif (
leaves and item.has_form("Power", 2) and item.leaves[0].sameQ(leaves[-1])
leaves
and item.has_form("Power", 2)
and item.leaves[0].sameQ(leaves[-1])
):
leaves[-1] = Expression(
"Power", leaves[-1], Expression("Plus", item.leaves[1], Integer(1))
Expand Down Expand Up @@ -1135,12 +1138,16 @@ class DirectedInfinity(SympyFunction):
}

def to_sympy(self, expr, **kwargs):
if len(expr.leaves) == 1:
if len(expr._leaves) == 1:
dir = expr.leaves[0].get_int_value()
if dir == 1:
return sympy.oo
elif dir == -1:
return -sympy.oo
else:
return sympy.Mul((expr._leaves[0].to_sympy()), sympy.zoo)
else:
return sympy.zoo


class Re(SympyFunction):
Expand Down Expand Up @@ -1833,6 +1840,9 @@ class Gamma(_MPMathMultiFunction):
rules = {
"Gamma[z_, x0_, x1_]": "Gamma[z, x0] - Gamma[z, x1]",
"Gamma[1 + z_]": "z!",
"Derivative[1][Gamma]": "(Gamma[#1]*PolyGamma[0, #1])&",
"Derivative[1, 0][Gamma]": "(Gamma[#1, #2]*Log[#2] + MeijerG[{{}, {1, 1}}, {{0, 0, #1}, {}}, #2])&",
"Derivative[0, 1][Gamma]": "(-(#2^(-1 + #1)/E^#2))&",
}

def get_sympy_names(self):
Expand Down Expand Up @@ -1862,6 +1872,8 @@ class Pochhammer(SympyFunction):

rules = {
"Pochhammer[a_, n_]": "Gamma[a + n] / Gamma[a]",
"Derivative[1,0][Pochhammer]": "(Pochhammer[#1, #2]*(-PolyGamma[0, #1] + PolyGamma[0, #1 + #2]))&",
"Derivative[0,1][Pochhammer]": "(Pochhammer[#1, #2]*PolyGamma[0, #1 + #2])&",
}


Expand Down Expand Up @@ -2205,3 +2217,131 @@ def apply(self, expr, evaluation):
elif expr == SymbolFalse:
return Integer(0)
return None


class Assumptions(Predefined):
"""
<dl>
<dt>'$Assumptions'
<dd>is the default setting for the Assumptions option used in such
functions as Simplify, Refine, and Integrate.
</dl>
"""

name = "$Assumptions"
attributes = ("Unprotected",)
rules = {
"$Assumptions": "True",
}


class Assuming(Builtin):
"""
<dl>
<dt>'Assuming[$cond$, $expr$]'
<dd>Evaluates $expr$ assuming the conditions $cond$
</dl>
>> $Assumptions = { x > 0 }
= {x > 0}
>> Assuming[y>0, $Assumptions]
= {x > 0, y > 0}
"""

attributes = ("HoldRest",)

def apply_assuming(self, cond, expr, evaluation):
"Assuming[cond_, expr_]"
cond = cond.evaluate(evaluation)
if cond.is_true():
cond = []
elif cond.is_symbol() or not cond.has_form("List", None):
cond = [cond]
else:
cond = cond.leaves
assumptions = evaluation.definitions.get_definition(
"System`$Assumptions", only_if_exists=True
)

if assumptions:
assumptions = assumptions.ownvalues
if len(assumptions) > 0:
assumptions = assumptions[0].replace
else:
assumptions = None
if assumptions:
if assumptions.is_symbol() or not assumptions.has_form("List", None):
assumptions = [assumptions]
else:
assumptions = assumptions.leaves
cond = assumptions + tuple(cond)
Expression(
"Set", Symbol("System`$Assumptions"), Expression("List", *cond)
).evaluate(evaluation)
ret = expr.evaluate(evaluation)
if assumptions:
Expression(
"Set", Symbol("System`$Assumptions"), Expression("List", *assumptions)
).evaluate(evaluation)
else:
Expression(
"Set", Symbol("System`$Assumptions"), Expression("List", SymbolTrue)
).evaluate(evaluation)
return ret


class ConditionalExpression(SympyFunction):
"""
<dl>
<dt>'ConditionalExpression[$expr$, $cond$]'
<dd>returns $expr$ if $cond$ evaluates to $True$, $Undefined$ if
$cond$ evaluates to $False$.
</dl>

>> f = ConditionalExpression[x^2, x>0]
= ConditionalExpression[x ^ 2, x > 0]
>> f /. x -> 2
= 4
>> f /. x -> -2
= Undefined
"""

sympy_name = "Piecewise"

rules = {
"ConditionalExpression[expr_, True]": "expr",
"ConditionalExpression[expr_, False]": "Undefined",
}

def apply_generic(self, expr, cond, evaluation):
"ConditionalExpression[expr_, cond_]"
cond = cond.evaluate(evaluation)
if cond is None:
return
if cond.is_true():
return expr
if cond == SymbolFalse:
return SymbolUndefined
return

def to_sympy(self, expr, **kwargs):
leaves = expr.leaves
if len(leaves) != 2:
return
expr, cond = leaves

sympy_cond = None
if isinstance(cond, Symbol):
if cond == SymbolTrue:
sympy_cond = True
elif cond == SymbolFalse:
sympy_cond = False
if sympy_cond is None:
sympy_cond = cond.to_sympy(**kwargs)
if not (sympy_cond.is_Relational or sympy_cond.is_Boolean):
return

sympy_cases = (
(expr.to_sympy(**kwargs), sympy_cond),
(sympy.Symbol(sympy_symbol_prefix + "System`Undefined"), True),
)
return sympy.Piecewise(*sympy_cases)
19 changes: 17 additions & 2 deletions mathics/builtin/assignment.py
Original file line number Diff line number Diff line change
Expand Up @@ -366,19 +366,34 @@ def assign_elementary(self, lhs, rhs, evaluation, tags=None, upset=False):
evaluation.message(lhs_name, "precset", lhs, rhs)
return False

# To Handle `OptionValue` in `Condition`
rulopc = Rule(
Expression(
"OptionValue",
Expression("Pattern", Symbol("$cond$"), Expression("Blank")),
),
Expression("OptionValue", lhs.get_head(), Symbol("$cond$")),
)

rhs_name = rhs.get_head_name()
while rhs_name == "System`Condition":
if len(rhs.leaves) != 2:
evaluation.message_args("Condition", len(rhs.leaves), 2)
return False
else:
lhs = Expression("Condition", lhs, rhs.leaves[1])
lhs = Expression(
"Condition", lhs, rhs.leaves[1].apply_rules([rulopc], evaluation)[0]
)
rhs = rhs.leaves[0]
rhs_name = rhs.get_head_name()

# Now, let's add the conditions on the LHS
if condition:
lhs = Expression("Condition", lhs, condition.leaves[1])
lhs = Expression(
"Condition",
lhs,
condition.leaves[1].apply_rules([rulopc], evaluation)[0],
)

rule = Rule(lhs, rhs)
count = 0
Expand Down
Loading