Sympy function evaluation - python

I have a little question about sympy.
I did load the library with :
from sympy import *
At some point of my program I would like to evaluate a function.
x=Symbol('x', real=True)
sqrt(1-x).subs(x, 9).evalf()
>>> 2.82842712474619*I
Sympy answer me complex value but i would like an error as in basic python :
sqrt(-1)
>>> ValueError: math domain error
Someone know how to do that using sympy?

I may be wrong, but I don't think you can make it yell that way, because that's a scientific library so it is made for supporting imaginary numbers, but you can change it a bit:
x=Symbol('x', real=True)
v = sqrt(1-x).subs(x, 9).evalf()
if not v.is_real:
raise ValueError, "math domain error"
or you can create a function:
def assert_real(v):
if not v.is_real:
raise ValueError, "math domain error"
return v
so you can do:
x = Symbol('x', real=True)
v = assert_real(sqrt(1-x).subs(x, 9).evalf())

Related

TypeError: object is not callable when putting ICS in SymPy

I am currently learning how to do differential equations on Python using SymPy.
def problem():
alpha, beta, t = symbols('alpha beta t', real=True)
s = Function('s')(t)
expr = Eq(s.diff(t), alpha*s**2 + beta*s)
print(expr)
print(sympy.dsolve(expr, simplify=True, ics={s(0): 1000}))
It always gives me TypeError: object 's' is not callable when putting the initial condition (it works and give me general solution with C1 when I remove ics)
Anyone can help with this?

conversion of function from Matlab to python

I have a MATLAB function :
Bits=30
NBits= ceil(fzero(#(x)2^(x) - x -1 - Bits, max(log2(Bits),1)))
I want to convert it to python, I wrote something like this so far:
from numpy import log, log2
from scipy.optimize import root_scalar
def func(x,Bits):
return ((x)2^(x)-x-1-Bits, max(log2(Bits)))
However it says that it need to be (x)*2^
Does anybody know first, if the conversion from Matlab to python is correct? and second if * has to be added?
Upon suggestion I wrote this lambda function:
lambda x: (2^(x) -x -1 -Bits) , max(log2(Bits))
but I get this error:
TypeError: 'numpy.float64' object is not iterable
I don't have numpy or scipy on this computer so here is my best attempt at an answer.
def YourFunc(Bits):
return math.ceil(root_scalar(lambda x: (2**x)-x-1-Bits, x0 = max(log2(Bits),1)))
Bits = 30
NBits = YourFunc(30)
print(NBits)
I used this function for log2 rather than the one from numpy. Try it
def log2(x):
return math.log(x,2)

Sympy simplification of maximum

I don't understand why Sympy won't return to me the expression below simplified (not sure its a bug in my code or a feature of Sympy).
import sympy as sp
a = sp.Symbol('a',finite = True, real = True)
b = sp.Symbol('b',finite = True, real = True)
sp.assumptions.assume.global_assumptions.add(sp.Q.positive(b))
sp.assumptions.assume.global_assumptions.add(sp.Q.negative(a))
sp.simplify(sp.Max(a-b,a+b))
I would expect the output to be $a+b$, but Sympy still gives me $Max(a-b,a+b)$.
Thanks; as you can see I am a beginner in Sympy so any hints/help are appreciated.
Surely the result should be a + b...
You can do this by setting the assumptions on the symbol as in:
In [2]: a = Symbol('a', negative=True)
In [3]: b = Symbol('b', positive=True)
In [4]: Max(a - b, a + b)
Out[4]: a + b
You are trying to use the new assumptions system but that system is still experimental and is not widely used within sympy. The new assumptions are not used in core evaluation so e.g. the Max function has no idea that you have declared global assumptions on a and b unless those assumptions are declared on the symbols as I show above.

find out if trigonometric is been used and track symbol variable

I will have data which uses degrees for the trigonometric functions.
I will use sympy and since it uses radians for the trigonometric functions, I want to be able to convert and use degrees.
But, I will not know which symbol variable is been used as input to the trigonometric function.
So , I will have something like:
import sympy
from sympy import mpmath
a = 2
b = 30
a,b = sympy.symbols('a b')
expr = 'sqrt(a + cos(b))'
expres = sympy.sympify(expr)
print(expres.atoms(sympy.cos))
The b is 30 and it is in degrees (so, in the cos(b) computations it must be degrees, not radians as sympy expects).
But, as I said, another time the program runs, it will use another symbol variable for trigonometric.Or, more than one trigonometric functions.
I thought if using atoms in order to find if in the expression I have trigonometric functions.And then , somehow , use degrees instead of radians wherever the corresponding symbol variables is been used.
Is there a way to do this?
Arguably the most clean way to avoid this problem is to tell sympify to use custom definitions for selected symbols/strings, e.g., like this:
from sympy.abc import *
from sympy import sin, pi, Lambda, sympify
sin_degree = Lambda(x, sin(x*pi/180))
degree_trigs = {"sin": sin_degree}
expr_string = "sin(a) + sin(b**d + exp(c))"
expr = sympify(expr_string, locals=degree_trigs)
print(expr)
This returns:
sin(pi*a/180) + sin(pi*(b**d/180 + exp(c)/180))
You can use subs with functions, e.g., like this:
from sympy.abc import *
from sympy import sin, exp, pi, Lambda
sin_degree = Lambda(x, sin(x*pi/180))
expr = sin(a) + sin(b**d + exp(c))
print( expr.subs(sin,sin_degree) )
This returns:
sin(pi*a/180) + sin(pi*(b**d/180 + exp(c)/180))

How do you do natural logs (e.g. "ln()") with numpy in Python?

Using numpy, how can I do the following:
ln(x)
Is it equivalent to:
np.log(x)
I apologise for such a seemingly trivial question, but my understanding of the difference between log and ln is that ln is logspace e?
np.log is ln, whereas np.log10 is your standard base 10 log.
Correct, np.log(x) is the Natural Log (base e log) of x.
For other bases, remember this law of logs: log-b(x) = log-k(x) / log-k(b) where log-b is the log in some arbitrary base b, and log-k is the log in base k, e.g.
here k = e
l = np.log(x) / np.log(100)
and l is the log-base-100 of x
I usually do like this:
from numpy import log as ln
Perhaps this can make you more comfortable.
Numpy seems to take a cue from MATLAB/Octave and uses log to be "log base e" or ln. Also like MATLAB/Octave, Numpy does not offer a logarithmic function for an arbitrary base.
If you find log confusing you can create your own object ln that refers to the numpy.log function:
>>> import numpy as np
>>> from math import e
>>> ln = np.log # assign the numpy log function to a new function called ln
>>> ln(e)
1.0
from numpy.lib.scimath import logn
from math import e
#using: x - var
logn(e, x)
You could simple just do the reverse by making the base of log to e.
import math
e = 2.718281
math.log(e, 10) = 2.302585093
ln(10) = 2.30258093

Categories