Unpack sympy lambdify function - python

Below code I have.
from sympy import *
x = symbols('x')
expr = sin(x)
# Use sympy.lambdify() method
f = lambdify(x, expr, "math")
If print(f) its giving '<function _lambdifygenerated at 0x100d643a0>', is there any way to get back the expression(sin(x)) from f?

help(f) displays:
Help on function _lambdifygenerated:
_lambdifygenerated(x)
Created with lambdify. Signature:
func(x)
Expression:
sin(x)
Source code:
def _lambdifygenerated(x):
return sin(x)
f.__doc__ is the same string.
Since we specified 'math', scalars work, but not arrays:
In [12]: f(1.23)
Out[12]: 0.9424888019316975
In [13]: f(np.arange(3))
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
Input In [13], in <module>
----> 1 f(np.arange(3))
File <lambdifygenerated-2>:2, in _lambdifygenerated(x)
1 def _lambdifygenerated(x):
----> 2 return sin(x)
TypeError: only size-1 arrays can be converted to Python scalars

I have gone into the source code of Sympy and found this line where the content of the lambdified function is defined in the variable funcstr:
https://github.com/sympy/sympy/blob/88b9cba9d7e633ec769baf1fc5267acfd7f54788/sympy/utilities/lambdify.py#L863
# Create the function definition code and execute it
funcname = '_lambdifygenerated'
if _module_present('tensorflow', namespaces):
funcprinter = _TensorflowEvaluatorPrinter(printer, dummify) # type: _EvaluatorPrinter
else:
funcprinter = _EvaluatorPrinter(printer, dummify)
if cse == True:
from sympy.simplify.cse_main import cse as _cse
cses, _expr = _cse(expr, list=False)
elif callable(cse):
cses, _expr = cse(expr)
else:
cses, _expr = (), expr
funcstr = funcprinter.doprint(funcname, iterable_args, _expr, cses=cses)
Currently Sympy does not return funcstr, but I modified it in my local installation so that it does, and it seems to be what you are after.
import sympy as sy
x = sy.symbols('x')
expr = sy.sin(x)
# Use sympy.lambdify() method
f, funcstr = sy.lambdify(x, expr, "math")
funcstr.split(":")[-1].split("return")[-1].strip()
>>> 'sin(x)'
The way I got the content out is a bit dodgy, and not necessarily robust, but I hope it gives you a starting point to work with.
Beware that if you used the argument cse, this extraction will not be accurate, since it will miss out on the previous simplifications.

Related

Python- np.random.choice

I am using the numpy.random.choice module to generate an 'array' of choices based on an array of functions:
def f(x):
return np.sin(x)
def g(x):
return np.cos(x)
base=[f, g]
funcs=np.random.choice(base,size=2)
This code will produce an 'array' of 2 items referencing a function from the base array.
The reason for this post is, I have printed the outcome of funcs and recieved:
[<function f at 0x00000225AC94F0D0> <function f at 0x00000225AC94F0D0>]
Clearly this returns a reference to the functions in some form, not that I understand what that form is or how to manipulate it, this is where the problem comes in. I want to change the choice of function, so that it is no longer random and instead depends on some conditions, so it might be:
for i in range(2):
if testvar=='true':
choice[i] = 0
if testvar== 'false':
choice[i] = 1
This would return an array of indicies to be put in later function
The problem is, the further operations of the code (I think) require this previous form of function reference: [ ] as an input, instead of a simple array of 0,1 Indicies and I don't know how I can get an array of form [ ] by using if statements.
I could be completely wrong about the rest of the code requiring this input, but I don't know how I can amend it, so am hence posting it here. The full code is as follows: (it is a slight variation of code provided by #Attack68 on Evolving functions in python) It aims to store a function that is multiplied by a random function on each iteration and integrates accordingly. (I have put a comment on the code above the function that is causing the problem)
import numpy as np
import scipy.integrate as int
def f(x):
return np.sin(x)
def g(x):
return np.cos(x)
base = [f, g]
funcs = np.random.choice(base, size=2)
print(funcs)
#The below function is where I believe the [<function...>] input to be required
def apply(x, funcs):
y = 1
for func in funcs:
y *= func(x)
return y
print('function value at 1.5 ', apply(1.5, funcs))
answer = int.quad(apply, 1, 2, args=(funcs,))
print('integration over [1,2]: ', answer)
Here is my attempt of implementing a non-random event:
import numpy as np
import scipy.integrate as int
import random
def f(x):
return np.sin(x)
def g(x):
return np.cos(x)
base = [f, g]
funcs = list()
for i in range(2):
testvar=random.randint(0,100) #In my actual code, this would not be random but dependent on some other situation I have not accounted for here
if testvar>50:
func_idx = 0 # choose a np.random operation: 0=f, 1=g
else:
func_idx= 1
funcs.append(func_idx)
#funcs = np.random.choice(base, size=10)
print(funcs)
def apply(x, funcs):
y = 1
for func in funcs:
y *= func(x)
return y
print('function value at 1.5 ', apply(1.5, funcs))
answer = int.quad(apply, 1, 2, args=(funcs,))
print('integration over [1,2]: ', answer)
This returns the following error:
TypeError: 'int' object is not callable
If: You are trying to refactor your original code that operates on a list of randomly chosen functions to a version that operates with random indices which correspond to items in a list of functions. Refactor apply.
def apply(x,indices,base=base):
y = 1
for i in indices:
f = base[i]
y *= f(x)
return y
...this returns a reference to the functions in some form, not that I understand what that form is or how to manipulate it...
Functions are objects, the list contains a reference to the objects themselves. They can be used by either assigning them to a name then calling them or indexing the list and calling the object:
>>> def f():
... return 'f'
>>> def g():
... return 'g'
>>> a = [f,g]
>>> q = a[0]
>>> q()
'f'
>>> a[1]()
'g'
>>> for thing in a:
print(thing())
f
g
Or you can pass them around:
>>> def h(thing):
... return thing()
>>> h(a[1])
'g'
>>>
If you still want to use your function apply as-is, you need to keep your input a list of functions. Instead of providing a list of indices, you can use those indices to create your list of functions.
Instead of apply(1.5, funcs), try:
apply(1.5, [base(n) for n in funcs])

trying to do math, int object is not callable

def square(x):
int(x)
return 2(x * x)
def my_map(func, arg_list):
result = []
for i in arg_list:
result.append(func(i))
return result
squares = my_map(square, [1,2,3,4,5])
print(squares)
i'm trying to pass a number to a function and have it print the result, i have a function for the equation def square(), and a function that receives the numbers and the function
I keep on getting this error:
"TypeError: 'int' object is not callable"
I'm new to programming and was watching corey shaffer in YouTube and he wrote a program similar to this one. I started to play around with it, and now I'm stuck.
I would like the print statement to print out arg_list(i) and have I go through def square(x) and have that answer stored in result
here's a fix to your square function (you were missing a * operator)
def square(x):
int(x)
return 2*(x * x)
however, according to your function name I'm guessing you wanted the function to return the square of x:
2 --> 4
3 --> 9
4 --> 16
in that case, here's also a bug fix:
def square(x):
return x**2
The line 2(x * x) is causing python to treat the integer 2 as a function with arguments x*x, and hence the error "TypeError: 'int' object is not callable"
In [16]: x = 1
In [17]: 2(x*x)
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
<ipython-input-17-14e610e542ba> in <module>
----> 1 2(x*x)
TypeError: 'int' object is not callable
To square a number, you need x**2 instead, or perhaps pow(x, 2)using the pow builtin
def square(x):
int(x)
return x**2
The problem is with 2(x * x) statement. In the Python programming language, we need to explicitly mention all the operators in expressions. Like, the statement should be 2*(x*x) and when you use rounded brackets, you are actually calling the function.
Also, the above program can be reduced to,
In [54]: list(map(lambda no: int(no)**2, [1, 2, 3, 4, 5]))
Out[54]: [1, 4, 9, 16, 25]

Writing a python function that takes mean of array

I am trying to answer the questions below but I don't understand the error code when I run it (Required argument 'object' (pos 1) not found). Any help will be appreciated.
Write a python function that takes in two arrays and returns:
a) the mean of the first array
def first_mean(a,b):
a = np.array()
b = np.array()
return np.mean(a)
first_mean([2,3,4],[4,5,6])
b) the mean of the second array
def second_mean(a,b):
a = np.array()
b = np.array()
return np.mean(b)
second_mean([2,3,4],[4,5,6])
c) the Mann-Whitney U-statistic and associated p-value of the two arrays?
def mantest(a,b):
a = np.array()
b = np.array()
return scipy.stats.mannwhitneyu(a,b)
mantest([2,3,4],[4,5,6])
You are creating new, empty arrays in your functions for no reason. You are also giving them the same name as your input parameters, thus discarding your original input arrays.
What you are doing boils down to
>>> np.mean(np.array())
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Required argument 'object' (pos 1) not found
All you need to do is delete the useless lines
a = np.array()
b = np.array()
from your functions.
Demo:
>>> def first_mean_nobody_knows_why_this_has_two_arguments(a, b):
... return np.mean(a)
...
>>> a = np.array([1,2,3])
>>> b = np.array([4,5,6])
>>> first_mean_nobody_knows_why_this_has_two_arguments(a, b)
2.0

scipy.optimize.newton gives TypeError: 'float' object is not callable

Im new to python and I was writing this simply code for finding the roots of the function:
from scipy import optimize
x = eval(raw_input()) #Initial guess
f = eval(raw_input()) # function to be evaluated
F = eval(raw_input()) #derivative of function f
round(optimize.newton(f, x, F, tol = 1.0e-9), 4)
But the interpreter returns:
TypeError: 'float' object is not callable
I'm really not sure what im missing out from this code. Can someone help me out..thank you in advance
optimize.newton expects a reference to a callable object (for example a function). That does not mean that you give a function as a string like 'x*x' but you have to define one first, like:
def my_func (x):
return x*x
Then you can plug my_func into optimize.newton (besides the other required parameters).
This will depend on what you are inputting for f. If you enter something like
lambda x: x ** 2
then it will be interpreted as a function, for example
In [83]: f = eval('lambda x: x ** 2')
In [84]: f(5)
Out[84]: 25

TypeError: 'numpy.float64' object is not callable

So, what im trying to do is get certain numbers from certain positions in a array of a given > range and put them into an equation
yy = arange(4)
xx = arange(5)
Area = ((xx[2] - xx[1])(yy[2] + yy[1])) / 2
I try to run it and I get this..
----> ((xx[2] - xx[1])(yy[2] + yy[1])) / 2
TypeError: 'numpy.int64' object is not callable
I get error.. how can I use certain numbers in an array and put them into an equation?
Python does not follow the same rules as written math. You must explicitly indicate multiplication.
Bad:
(a)(b)
(unless a is a function)
Good:
(a) * (b)
This error also occurs when your function has the same name as your return value
def samename(a, b):
samename = a*b
return samename
This might be a super rookie mistake, I am curious how often this answer will be helpful.
You are missing * when multiplying, try:
import numpy as np
yy = np.arange(4)
xx = np.arange(5)
Area = ((xx[2] - xx[1])*(yy[2] + yy[1])) / 2
This could happen because you have overwritten the name of the function that you attempt to call.
For example:
def x():
print("hello world")
...
x = 10.5
...
x()
---------------------------------------------------------------------------
TypeError Traceback (most recent call last)
in
2 print("hello world")
3 x = 10.5
----> 4 x()
TypeError: 'float' object is not callable

Categories

Resources