How to symbolically write the hypergeometric function 1F1 in python? - sympy

I am trying to symbolically write the hypergeometric 1F1 function through the sympy. But I don't really understand what numbers should be in brackets to designate this particular hypergeometric function (1F1)?
import sympy as sp
y = sp.functions.special.hyper.hyper([...,...],[...],x)

Related

sympy: sympy function symbolic or non-symbolic

I am trying to understand about sympy's symbolic functions:
import sympy
from sympy.abc import x,y,z
with sympy.evaluate(False):
print(sympy.sympify("diff(x,x)").func)
print(sympy.parse_expr("diff(x, x)", local_dict={'diff':sympy.Derivative}).func)
print(sympy.sympify("Derivative(x,x)").func)
pass
This puts out:
Piecewise
<class 'sympy.core.function.Derivative'>
<class 'sympy.core.function.Derivative'>
This example should illustrate that diff is not a symbolic function yet Derivative is.
sympy.sympify("diff(x,x)").func results in Piecewise.
What exactly makes a function in sympy 'symbolic'?
Why don't both of the functions belong to <class 'sympy.core.function.Derivative'>?
I tried to test on a few examples if a function is symbolic using:
list_of_funcs = [sin, cos, tan, sec, csc, cot, sinh, cosh, tanh, sech, csch, coth, asin, acos, atan, asec, acsc, acot, asinh, acosh, atanh, asech, acsch, acoth, log, log, log, exp, <class 'sympy.concrete.summations.Sum'>, <class 'sympy.concrete.products.Product'>, Piecewise, jacobi, Piecewise]
with sympy.evaluate(False):
for f in list_of_funcs:
if issubclass(f, sympy.Basic):
print(f'{f}: True')
It returned True for all yet as far as I understood Piecewise is not symbolic.
Could you help me finding a way to test if a function is symbolic?
Answering this question without going too deep into coding concepts is not easy, but I can give it a try.
SymPy exposes many functions:
cos, sin, exp, Derivative, Integral... we can think of them as symbolic functions. Let's say you provide one or more arguments, then:
the function might evaluate to some symbolic numerical value. For example, cos(0) will return the symbolic number 1.
the function might return an "unevaluated" object. For example, cos(x) returns cos(x): this is a symbolic expression of type cos (as you have seen by running the func attribute). Similarly, you can create a derivative object Derivative(expr, x): this is a symbolic expression that represents a derivative, it doesn't actually compute the derivative!
Unevaluate functions, for example Function("f")(x), which will render as f(x): this is a symbolic expression of type f.
diff, integrate, series, limit, ... : those are ordinary python functions (for example, created with def diff(...)) that are going to apply some operation to a symbolic expression. When you call diff(expr, x) you are asking SymPy to compute the derivative of expr with respect to x. What if you wanted to represent the derivative without actually computing it? You write Derivative(expr, x).
So, going back to your example:
sympy.parse_expr("diff(x, x)", local_dict={'diff':sympy.Derivative})
this can be easily simplified to:
sympy.parse_expr("Derivative(x, x)")
A few more "relationships":
diff and Derivative
integrate and Integral
limit and Limit
Think of "symbolic" functions as nouns and "non symbolic" as verbs.
noun-like verb-like
---------- ---------
Integral integrate
Derivative diff
Sum summation
Product product
Those that are Python functions (I think what you mean by non-symbolic) emit some evaluated form of something that could also exist in an unevaluated form, e.g. prod(x, (x, 1, 5)) -> 120; Product(x, (x, 1, 5)) -> no change.
It would be better to refer to them in some other way. What I think you mean is "evaluated" vs "non-evaluated" (since almost all of SymPy's functions will return SymPy objects with "symbols", even if numeric).
If the type(thing) -> function it is not a class itself, it is a Python function. If you check the type of cos or Sum you will not get function as the result.
Whereas some of the evaluates and unevaluated forms may have different names (Sum vs summation) others, like Add are evaluative by default but you can use the evaluate=False arg to stop that: Add(x, x) = x + x != Add(x,x,evaluate=False). Those which are evaluative can be made non-evaluative by passing evaluate=True, e.g. Derivative(x, x, evaluate=True) -> 1.

Sympy lambdify array with shape (n,)

I have the following 'issue' with sympy at the moment:
I have a symbolic expression like M = matrix([pi*a, sin(1)*b]) which I want to lambdify and pass to a numerical optimizer. The issue is that the optimizer needs the function to input/output numpy arrays of shape (n,) and specifically NOT (n,1).
Now I have been able to achieve this with the following code (MWE):
import numpy as np
import sympy as sp
a, b = sp.symbols('a, b')
M = sp.Matrix([2*a, b])
f_tmp = sp.lambdify([[a,b]], M, 'numpy')
fun = lambda x: np.reshape( f_tmp(x), (2,))
Now, this is of course extremely ugly, since the reshape needs to be applied every time fun is evaluated (which might be LOTS of times). Is there a way to avoid this problem? The Matrix class is by definition always 2 dimensional. I tried using sympy's MutableDenseNDimArray-class, but they don't work in conjunction with lambdify. (symbolic variables don't get recognized)
One way is to convert a matrix to a nested list and take the first row:
fun = sp.lambdify([[a, b]], M.T.tolist()[0], 'numpy')
Now fun([2, 3]) is [4, 3]. This is a Python list, not a NumPy array, but optimizers (at least those in SciPy) should be okay with that.
One can also do
fun = sp.lambdify([[a, b]], np.squeeze(M), 'numpy')
which also returns a list.
In my test the above were equally fast, and faster than the version with a wrapping function (be it np.squeeze or np.reshape): about 6 µs vs 9 µs. It seems the gain is in eliminating one function call.

How to change printed representation of function's derivative in sympy

In a dynamic system my base values are all functions of time, d(t). I create the variable d using d = Function('d')(t) where t = S('t')
Obviously it's very common to have derivatives of d (rates of change like velocity etc.). However the default printing of diff(d(t)) gives:-
Derivative(d(t), t)
and using pretty printing in ipython (for e.g.) gives a better looking version of:-
d/dt (d(t))
The functions which include the derivatives of d(t) are fairly long in my problems however, and I'd like the printed representation to be something like d'(t) or \dot(d)(t) (Latex).
Is this possible in sympy? I can probably workaround this using subs but would prefer a generic sympy_print function or something I could tweak.
I do this by substitution. It is horribly stupid, but it works like a charm:
q = Function('q')(t)
q_d = Function('\\dot{q}')(t)
and then substitute with
alias = {q.diff(t):q_d, } # and higher derivatives etc..
hd = q.diff(t).subs(alias)
And the output hd has a pretty dot over it's head!
As I said: this is a work-around and works, but you have to be careful in order to substitute correctly (Also for q_d.diff(t), which must be q_d2 and so on! You can have one big list with all replacements for printing and just apply it after the relevant mathematical steps.)
The vector printing module that you already found is the only place where such printing is implemented in SymPy.
from sympy.physics.vector import dynamicsymbols
from sympy.physics.vector.printing import vpprint, vlatex
d = dynamicsymbols('d')
vpprint(d.diff()) # ḋ
vlatex(d.diff()) # '\\dot{d}'
The regular printers (pretty, LaTeX, etc) do not support either prime or dot notation for derivatives. Their _print_Derivative methods are written so that they also work for multivariable expressions, where one has to specify a variable by using some sort of d/dx notation.
It would be nice to have an option for shorter derivative notation in general.

Sympy: Howto to rewrite erf function

I have an expression in SymPy that involves the normal cumulative function, N(x) which is directly linked to the error function through the equation N(x)=0.5*erf(x/sqrt(2)) + 0.5.
When I use the Normal(0,1).cdf(x) function of SymPy, it is written using the error function. So, when I output latex string of some (complicated) expression, the seem more complicated when using erf (instead of N(x), it outputs the equation mentionned obove). I tried to define a symbol N=0.5*erf(x/sqrt(2)) + 0.5 and tried the command 'rewrite' the rewrite my expression in terms of N, but 'rewrite' seems to work only with internally defined functions.
Does any bodu know how to rewrite erf(some_expression) in terms of N(some_expression), given that I don't know some_expression in advance (can't use subs) ?
Thanks in advance
I take it from your question that you are using Normal from sympy.statistics. You should move to sympy.stats. sympy.statistics has been deprecated for some time, and will be removed in the next version of SymPy.
To answer your question more directly, you can replace functions with functions using replace, like expr.replace(erf, lambda x: (N(x) - 0.5)/0.5).
The problem here is that there is no function N. I would expect this to be done better in sympy.stats, where the distributions are represented symbolically. However, I didn't find a way to do it. I opened https://github.com/sympy/sympy/issues/7819 for this.

How can I enumerate the undefined functions in a SymPy expression?

I have a variety of SymPy expressions involving UndefinedFunction instances:
f = Function('f')
g = Function('g')
e = f(x) / g(x)
How can I obtain a list of the function invocations appearing in such expressions? In this example, I'd like to get [f(x), g(x)].
I'm aware of free_symbols but it kicks back set([x]) (as it should).
You are right that you want to use atoms, but be aware that all functions in SymPy subclass from Function, not just undefined functions. So you'll also get
>>> (sin(x) + f(x)).atoms(Function)
set([f(x), sin(x)])
So you'll want to further reduce your list to only those functions that are UndefinedFunctions. Note that UndefinedFunction is the metaclass of f, so do to this, you need something like
>>> [i for i in expr.atoms(Function) if isinstance(i.__class__, UndefinedFunction)]
[f(x)]
It turns out that the atoms member method can accept a type on which to filter. So
e.atoms(Function)
returns
set([f(x), g(x)])
as I'd wanted. And that fancier things like
e.diff(x).atoms(Derivative)
are possible.