|
33 | 33 | Symbol, |
34 | 34 | SymbolComplexInfinity, |
35 | 35 | SymbolDirectedInfinity, |
36 | | - SymbolFalse, |
37 | 36 | SymbolInfinity, |
38 | 37 | SymbolN, |
39 | 38 | SymbolNull, |
40 | | - SymbolSequence, |
41 | 39 | SymbolTrue, |
| 40 | + SymbolFalse, |
| 41 | + SymbolUndefined, |
| 42 | + SymbolSequence, |
42 | 43 | from_mpmath, |
43 | 44 | from_python, |
44 | 45 | ) |
45 | 46 | from mathics.core.numbers import min_prec, dps, SpecialValueError |
46 | 47 |
|
47 | 48 | from mathics.builtin.lists import _IterationFunction |
48 | | -from mathics.core.convert import from_sympy, SympyExpression |
| 49 | +from mathics.core.convert import from_sympy, SympyExpression, sympy_symbol_prefix |
49 | 50 |
|
50 | 51 |
|
51 | 52 | @lru_cache(maxsize=1024) |
@@ -675,7 +676,9 @@ def apply(self, items, evaluation): |
675 | 676 | Expression("Plus", item.leaves[1], leaves[-1].leaves[1]), |
676 | 677 | ) |
677 | 678 | elif ( |
678 | | - leaves and item.has_form("Power", 2) and item.leaves[0].sameQ(leaves[-1]) |
| 679 | + leaves |
| 680 | + and item.has_form("Power", 2) |
| 681 | + and item.leaves[0].sameQ(leaves[-1]) |
679 | 682 | ): |
680 | 683 | leaves[-1] = Expression( |
681 | 684 | "Power", leaves[-1], Expression("Plus", item.leaves[1], Integer(1)) |
@@ -1135,12 +1138,16 @@ class DirectedInfinity(SympyFunction): |
1135 | 1138 | } |
1136 | 1139 |
|
1137 | 1140 | def to_sympy(self, expr, **kwargs): |
1138 | | - if len(expr.leaves) == 1: |
| 1141 | + if len(expr._leaves) == 1: |
1139 | 1142 | dir = expr.leaves[0].get_int_value() |
1140 | 1143 | if dir == 1: |
1141 | 1144 | return sympy.oo |
1142 | 1145 | elif dir == -1: |
1143 | 1146 | return -sympy.oo |
| 1147 | + else: |
| 1148 | + return sympy.Mul((expr._leaves[0].to_sympy()), sympy.zoo) |
| 1149 | + else: |
| 1150 | + return sympy.zoo |
1144 | 1151 |
|
1145 | 1152 |
|
1146 | 1153 | class Re(SympyFunction): |
@@ -1833,6 +1840,9 @@ class Gamma(_MPMathMultiFunction): |
1833 | 1840 | rules = { |
1834 | 1841 | "Gamma[z_, x0_, x1_]": "Gamma[z, x0] - Gamma[z, x1]", |
1835 | 1842 | "Gamma[1 + z_]": "z!", |
| 1843 | + "Derivative[1][Gamma]": "(Gamma[#1]*PolyGamma[0, #1])&", |
| 1844 | + "Derivative[1, 0][Gamma]": "(Gamma[#1, #2]*Log[#2] + MeijerG[{{}, {1, 1}}, {{0, 0, #1}, {}}, #2])&", |
| 1845 | + "Derivative[0, 1][Gamma]": "(-(#2^(-1 + #1)/E^#2))&", |
1836 | 1846 | } |
1837 | 1847 |
|
1838 | 1848 | def get_sympy_names(self): |
@@ -1862,6 +1872,8 @@ class Pochhammer(SympyFunction): |
1862 | 1872 |
|
1863 | 1873 | rules = { |
1864 | 1874 | "Pochhammer[a_, n_]": "Gamma[a + n] / Gamma[a]", |
| 1875 | + "Derivative[1,0][Pochhammer]": "(Pochhammer[#1, #2]*(-PolyGamma[0, #1] + PolyGamma[0, #1 + #2]))&", |
| 1876 | + "Derivative[0,1][Pochhammer]": "(Pochhammer[#1, #2]*PolyGamma[0, #1 + #2])&", |
1865 | 1877 | } |
1866 | 1878 |
|
1867 | 1879 |
|
@@ -2205,3 +2217,131 @@ def apply(self, expr, evaluation): |
2205 | 2217 | elif expr == SymbolFalse: |
2206 | 2218 | return Integer(0) |
2207 | 2219 | return None |
| 2220 | + |
| 2221 | + |
| 2222 | +class Assumptions(Predefined): |
| 2223 | + """ |
| 2224 | + <dl> |
| 2225 | + <dt>'$Assumptions' |
| 2226 | + <dd>is the default setting for the Assumptions option used in such |
| 2227 | + functions as Simplify, Refine, and Integrate. |
| 2228 | + </dl> |
| 2229 | + """ |
| 2230 | + |
| 2231 | + name = "$Assumptions" |
| 2232 | + attributes = ("Unprotected",) |
| 2233 | + rules = { |
| 2234 | + "$Assumptions": "True", |
| 2235 | + } |
| 2236 | + |
| 2237 | + |
| 2238 | +class Assuming(Builtin): |
| 2239 | + """ |
| 2240 | + <dl> |
| 2241 | + <dt>'Assuming[$cond$, $expr$]' |
| 2242 | + <dd>Evaluates $expr$ assuming the conditions $cond$ |
| 2243 | + </dl> |
| 2244 | + >> $Assumptions = { x > 0 } |
| 2245 | + = {x > 0} |
| 2246 | + >> Assuming[y>0, $Assumptions] |
| 2247 | + = {x > 0, y > 0} |
| 2248 | + """ |
| 2249 | + |
| 2250 | + attributes = ("HoldRest",) |
| 2251 | + |
| 2252 | + def apply_assuming(self, cond, expr, evaluation): |
| 2253 | + "Assuming[cond_, expr_]" |
| 2254 | + cond = cond.evaluate(evaluation) |
| 2255 | + if cond.is_true(): |
| 2256 | + cond = [] |
| 2257 | + elif cond.is_symbol() or not cond.has_form("List", None): |
| 2258 | + cond = [cond] |
| 2259 | + else: |
| 2260 | + cond = cond.leaves |
| 2261 | + assumptions = evaluation.definitions.get_definition( |
| 2262 | + "System`$Assumptions", only_if_exists=True |
| 2263 | + ) |
| 2264 | + |
| 2265 | + if assumptions: |
| 2266 | + assumptions = assumptions.ownvalues |
| 2267 | + if len(assumptions) > 0: |
| 2268 | + assumptions = assumptions[0].replace |
| 2269 | + else: |
| 2270 | + assumptions = None |
| 2271 | + if assumptions: |
| 2272 | + if assumptions.is_symbol() or not assumptions.has_form("List", None): |
| 2273 | + assumptions = [assumptions] |
| 2274 | + else: |
| 2275 | + assumptions = assumptions.leaves |
| 2276 | + cond = assumptions + tuple(cond) |
| 2277 | + Expression( |
| 2278 | + "Set", Symbol("System`$Assumptions"), Expression("List", *cond) |
| 2279 | + ).evaluate(evaluation) |
| 2280 | + ret = expr.evaluate(evaluation) |
| 2281 | + if assumptions: |
| 2282 | + Expression( |
| 2283 | + "Set", Symbol("System`$Assumptions"), Expression("List", *assumptions) |
| 2284 | + ).evaluate(evaluation) |
| 2285 | + else: |
| 2286 | + Expression( |
| 2287 | + "Set", Symbol("System`$Assumptions"), Expression("List", SymbolTrue) |
| 2288 | + ).evaluate(evaluation) |
| 2289 | + return ret |
| 2290 | + |
| 2291 | + |
| 2292 | +class ConditionalExpression(SympyFunction): |
| 2293 | + """ |
| 2294 | + <dl> |
| 2295 | + <dt>'ConditionalExpression[$expr$, $cond$]' |
| 2296 | + <dd>returns $expr$ if $cond$ evaluates to $True$, $Undefined$ if |
| 2297 | + $cond$ evaluates to $False$. |
| 2298 | + </dl> |
| 2299 | +
|
| 2300 | + >> f = ConditionalExpression[x^2, x>0] |
| 2301 | + = ConditionalExpression[x ^ 2, x > 0] |
| 2302 | + >> f /. x -> 2 |
| 2303 | + = 4 |
| 2304 | + >> f /. x -> -2 |
| 2305 | + = Undefined |
| 2306 | + """ |
| 2307 | + |
| 2308 | + sympy_name = "Piecewise" |
| 2309 | + |
| 2310 | + rules = { |
| 2311 | + "ConditionalExpression[expr_, True]": "expr", |
| 2312 | + "ConditionalExpression[expr_, False]": "Undefined", |
| 2313 | + } |
| 2314 | + |
| 2315 | + def apply_generic(self, expr, cond, evaluation): |
| 2316 | + "ConditionalExpression[expr_, cond_]" |
| 2317 | + cond = cond.evaluate(evaluation) |
| 2318 | + if cond is None: |
| 2319 | + return |
| 2320 | + if cond.is_true(): |
| 2321 | + return expr |
| 2322 | + if cond == SymbolFalse: |
| 2323 | + return SymbolUndefined |
| 2324 | + return |
| 2325 | + |
| 2326 | + def to_sympy(self, expr, **kwargs): |
| 2327 | + leaves = expr.leaves |
| 2328 | + if len(leaves) != 2: |
| 2329 | + return |
| 2330 | + expr, cond = leaves |
| 2331 | + |
| 2332 | + sympy_cond = None |
| 2333 | + if isinstance(cond, Symbol): |
| 2334 | + if cond == SymbolTrue: |
| 2335 | + sympy_cond = True |
| 2336 | + elif cond == SymbolFalse: |
| 2337 | + sympy_cond = False |
| 2338 | + if sympy_cond is None: |
| 2339 | + sympy_cond = cond.to_sympy(**kwargs) |
| 2340 | + if not (sympy_cond.is_Relational or sympy_cond.is_Boolean): |
| 2341 | + return |
| 2342 | + |
| 2343 | + sympy_cases = ( |
| 2344 | + (expr.to_sympy(**kwargs), sympy_cond), |
| 2345 | + (sympy.Symbol(sympy_symbol_prefix + "System`Undefined"), True), |
| 2346 | + ) |
| 2347 | + return sympy.Piecewise(*sympy_cases) |
0 commit comments