Lambdifying a function with conditon statements using sympy - sympy

Im trying to lambdify this function
def f(x):
if ceil(x)%2 == 0:
return -1
else :
return +1
a = sympy.lambdify(x,f(x))
Im getting an error when i try to do that.
I also tried piecewise , but it is not giving me the desired outcome
y = lambdify(x,(Piecewise((1, ceil(x)%2 == 0), (-1,True))))
Please help
Thanks in advance

You need to pass a symbolic expression to lambdify so a Python function is no good. Also you need to use symbolic sympy functions and sympy's ceil function is actually called ceiling. Finally == compares if two expressions are the same which is not the same as constructing a symbolic Boolean. For that you need Eq:
That gives
In [19]: p = Piecewise((1, Eq(ceiling(x)%2, 0)), (-1,True))
In [20]: p
Out[20]:
⎧1 for ⌈x⌉ mod 2 = 0
⎨
⎩-1 otherwise
In [21]: y = lambdify(x, p)
In [22]: y([1, 2, 3])
Out[22]: array([-1., 1., -1.])
References:
https://docs.sympy.org/latest/modules/functions/elementary.html#ceiling
https://docs.sympy.org/latest/tutorial/gotchas.html#equals-signs

Related

Sympy: Is it possible use function collect() to IndexedBase variables?

I'm trying to use the function collect() to simplify mi expression . My desired result is
My code:
from sympy import *
#index
i = symbols('i' , integer = True )
#constants
a = symbols( 'a' )
#variables
alpha = IndexedBase('alpha', positive=True, domain=QQ)
index = (i, 1, 3)
rho = symbols( 'rho')
U = product( alpha[i]**(1/(rho-1)) , index )
U
:
My solution attempt:
U = U.subs(1/(rho-1),a)
collect(U,rho, evaluate=False)[1]
:
What I'm doing wrong?
You must be using a fairly old version of SymPy because in recent versions the form that you wanted arises automatically. In any case you should be able to use powsimp:
In [9]: U
Out[9]:
a a a
alpha[1] ⋅alpha[2] ⋅alpha[3]
In [10]: powsimp(U, force=True)
Out[10]:
a
(alpha[1]⋅alpha[2]⋅alpha[3])
https://docs.sympy.org/latest/tutorials/intro-tutorial/simplification.html#powsimp

How to solve this differential equation in sympy?

I want to solve this differential equation in sympy:
f'(x) = f(x+1)
I try this:
from sympy import *
x = symbols("x")
f = Function("f")
f_ = Derivative(f,x)
dsolve(f_(x) - f(x+1), f(x))
but get an error: "'Derivative' object is not callable".
When I replace "f_(x)" by "f_", I get a different error: "TypeError: doit() missing 1 required positional argument: 'self'".
What is the correct syntax for this?
You have to differentiate after providing an argument.
The following works for me:
from sympy import *
x = symbols("x")
f = Function("f")
f_ = Derivative(f(x),x)
dsolve(f_ - f(x+1), f(x))
Sidenote: Solution to your actual problem
What you have is essentially a DDE, just with the time pointing in the wrong direction. The typical form of the DDE would be g'(t) = −g(t−1). With this module of mine, we can solve this numerically:
from jitcdde import y, t, jitcdde
from numpy import arange
f = [-y(0,t-1)]
DDE = jitcdde(f)
DDE.constant_past([1.0])
DDE.step_on_discontinuities()
times = arange(0,1000,0.1) + DDE.t
solution = [(time,DDE.integrate(time)[0]) for time in times]
It seems that no matter how we initialise the past, the solutions eventually converge to something of the form exp(a·t)·sin(b·t) with some constants a and b specified below. In fact if instead of DDE.constant_past([1.0]) we use
a = -0.318131477176434
b = 1.33723563936212
DDE.past_from_function([exp(a*t)*sin(b*t)])
the solution matches exp(a·t)·sin(b·t) extremely well.
Something tells me we're on a hiding to nowhere. This is not a useful answer.
>>> from sympy import *
>>> f = Function('f')
>>> var('x')
x
>>> Eq(f(x).diff(x,x)-f(x+1))
Eq(-f(x + 1) + Derivative(f(x), x, x), 0)
>>> dsolve(_,f(x))
Eq(f(x), C1 + x*(C2 + Integral(f(x + 1), x)) - Integral(x*f(x + 1), x))
>>> latex(_)
'f{\\left (x \\right )} = C_{1} + x \\left(C_{2} + \\int f{\\left (x + 1 \\right )}\\, dx\\right) - \\int x f{\\left (x + 1 \\right )}\\, dx'
As a graphic (having tried various ways of putting the mathematical representation here.)

Python - Assign None or value

Is there a short way to assign None or value in a variable, depending on the value?
x= value if value!= 999 else None
result = (on_false, on_true)[condition]
>>> value = 10
>>> x = (None,value)[value != 999]
>>> print x
10
>>> value = 999
>>> x = (None,value)[value != 999]
>>> print x
None
You are using the correct way to do it.
but if you insist on shorten way to figure it out you can use this method:
first way:
{0:value}.get(value==999)
using the trick python saving same hash for False and 0 (hash = 0).
second way:
{999:None}.get(value,value)
using get method and default value to bring this.
third way:
[None, value][value != 999]
when first part stand for value declaration and the second as boolean condition.

Defining a range for a symbol in Sympy

In Sympy it is possible to define constraints on what values a symbol may take
x = symbols('x', real=True)
Is it possible to say that a symbol should take values only in a certain range, say -1 < x < 1? The reason why I am interested in this is because I am trying to get sympy to automatically simplify expressions like the one below
expr = sqrt(1+x) * sqrt((1-x)*(1+x)) / sqrt(1-x)
Running simplify(expr) yields no simplification, whereas when -1<x<1 the simplified result should be 1+x. How do I get sympy to simplify expressions like the one above?
Although a single symbol can't hold that assumption, an expression can. Let's define an expression that has the desired range:
>>> p = Symbol('p', positive=True)
>>> neg1to1 = (p - 1)/(p + 1)
Now replace x with that value and simplify
>>> asp = expr.subs(x, neg1to1).simplify(); asp
2*p/(p + 1)
Now restore x from the relationship between it and neg1to1:
>>> p_as_x = solve(neg1to1 - x, p)[0]
>>> asp.subs(p, p_as_x).simplify()
x + 1
You could turn this into a function to allow for any range for x:
>>> def simplify_assuming_range(expr, x, lo, hi):
... from sympy import Dummy, solve
... p = Dummy(positive=True)
... xr = (p - 1)/(p + 1)*(hi - lo) + lo
... rx = solve(xr - x, p)[0]
... return expr.subs(x, xr).simplify().subs(p, rx).simplify()
...
>>> simplify_assuming_range(expr,x,-1,1)
x + 1
Using targeted expansion with force can help:
>>> expand(expr, power=True, force=True, mul=False)
x + 1
The expand docstring will tell about each of those options.

Error in exponential PDF

I need to complete the function exponentialPDF but get an error:
'IndexError: index 0 is out of bounds for axis 0 with size 0'
The function looks like this:
def uniformPDF(x,a=0.0,b=4.0):
p = 1.0/(b-a)*ones((len(x),))
p[x<a] = 0.0
p[x>b] = 0.0
return(p)
def exponentialPDF(x,a=1.0):
"""
Call:
p = exponentialPDF(x,a)
Input argument:
vals: float (array)
Output argument:
p: float (array)
Examples:
In[1]: exponentialPDF([1,2],3)
Out[1]: array([ 0.14936121, 0.03332699])
"""
p = a * exp(-a*x)
p[x<0] = 0.0
return(p)
Can someone help me with the error?
Sounds like the list you are passing in to your function is empty. Read about python lists and see the following post:
IndexError: list assignment index out of range
I found the function works using numpy array, e.g. p = exponentialPDF(np.array([1,2]),3). Hope this help, you should check out the SO homework post and ask again if you're still stuck.
EDIT: As you are using numpy, I would add an explicit convert to numpy array in the function as follows:
def exponentialPDF(x,a=1.0):
"""
Call:
p = exponentialPDF(x,a)
Input argument:
vals: float (array)
Output argument:
p: float (array)
Examples:
In[1]: exponentialPDF([1,2],3)
Out[1]: array([ 0.14936121, 0.03332699])
"""
if type(x) is list:
x = array(x)
p = a * exp(-a*x)
p[x<0] = 0.0
return(p)
Hopefully this will fix your problem and you can use the function as needed (assuming returning a numpy array from the function is okay).