scipy -- how to convert a function result to array - python

Hello i have the function Walk1d which then i want to calculate the cumsum.
I use Walk1d=lambda n: sc.cumsum(steps(n)) .The result is an array but when i am trying Walk1d.cumsum() it doesn't work because type(Walk1d) is a function.
If i try sc.array(Walk1d).cumsum() it gives me : at 0x3798488>
How can i handle this?
import matplotlib.pyplot as plt
import scipy as sc
steps=lambda m: 2*sc.random.random_integers(0,1,size=m)-1
Walk1d=lambda n: sc.cumsum(steps(n))
print(sc.array(Walk1d).cumsum())
Thanks!

Walk1d is a function taking an argument. You have to call the function and pass in an argument to get a result, for example
print(Walk1d(10).cumsum())

The function Walk1d needs to be called with a parameter n:
print(sc.array(Walk1d(10)).cumsum())

Related

How to solve the 'mul objective has no attribute 'cos' '

How to solve the multi object problem?
import sympy as sym
from sympy import lambdify
x = sym.Symbol('x')
n = sym.Symbol('n')
f = sym.sin(n*x)
derivative_f = f.diff(x)
derivative_f = lambdify(x, derivative_f)
x = float(input('x:'))
print(derivative_f(x))
print(derivative_f)
If I input 2, the expected result should be 2*cos(2*x).
Your code contains a few misconceptions. One problem is an important general programming rule: try to use different variable names for variables with different meanings. So, x shouldn't be assigned a float, as it was a symbolic variable before. And derivative_f being a symbolic expression, shouldn't be assigned the result of lambdify.
Note that sympy's symbolic world doesn't mix well with the numeric world of non-sympy functions. lambdify forms a bridge between these worlds, from completely symbolic to completely numeric. E.g. the function created with lambdify doesn't have access to the symbolic n anymore.
The code lambdify(x, derivative_f) contains an error. derivative_f is a symbolic expression containing two symbolic variables (x and n), so it needs to be called as derivative_f_x_n = lambdify((x, n), derivative_f) (also giving the result a different name). Afterwards, you can use numeric expressions as derivative_f_x_n(7, 8), but you can't use symbolic parameters anymore.
For what you seem to be trying to do, lambdify isn't adequate. To get the derivative with x substituted, you call .subs(x, new_value) directly on the symbolic version of derivative_f:
import sympy as sym
from sympy import lambdify
x = sym.Symbol('x')
n = sym.Symbol('n')
f = sym.sin(n * x)
derivative_f_x = f.diff(x)
x_float = 2.0
print(derivative_f_x.subs(x, x_float))
Output: n*cos(2.0*n)
Also note that sympy strongly prefers to work with exact symbolic expressions, and using floats inevitably brings in approximations. Whenever possible, integers, sympy fractions (sym.S(1)/2) or symbolic expressions (sym.sqrt(5)) are recommended.
You call also use the derivative with respect to x and then substitute n:
print(f.diff(x).subs(n, 2))
Output: 2*cos(2*x)
To use that function later on in numeric calculations, after substitution you only have one symbolic variable left(x):
g = lambdify(x, f.diff(x).subs(n, 2))
You can type help(g) to see its generated source code:
Source code:
def _lambdifygenerated(x):
return (2*cos(2*x))
Then you can use g e.g. to create matplotlib plot. After lambdify nothing is symbolic anymore.
import matplotlib.pyplot as plt
import numpy as np
xs = np.linspace(0, 10)
plt.plot(xs, g(xs))
The other answer hit the key point, that you needed to account for the symbolic n when lambdifying.
Look at the help of your function:
In [2]: help(derivative_f)
Help on function _lambdifygenerated:
_lambdifygenerated(x)
Created with lambdify. Signature:
....
Source code:
def _lambdifygenerated(x):
return (n*cos(n*x))
It's a function of x, drawing n from the global environment, here a symbol.
The full error message when given an array argument:
In [5]: derivative_f(np.array([.1,.2,.3]))
AttributeError: 'Mul' object has no attribute 'cos'
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "<ipython-input-5-e04e9f3c0a8e>", line 1, in <module>
derivative_f(np.array([.1,.2,.3]))
File "<lambdifygenerated-1>", line 2, in _lambdifygenerated
return (n*cos(n*x))
TypeError: loop of ufunc does not support argument 0 of type Mul which has no callable cos method
See the return line in the traceback. That's the 'source code' in the help, and tells you what numpy is trying to execute.
test the inner expression of that line:
In [6]: n*np.array([.1,.2,.3])
Out[6]: array([0.1*n, 0.2*n, 0.3*n], dtype=object)
This is an object dtype array. Math on such an array delegates the calculation to each of the elements. Specifically it tries
(0.1*n).cos()
0.1*n is a sympy mul expression, hence the error. symbols often don't work in numpy expressions.
lambdify is a handy way of creating numpy functions from sympy expressions, but it needs to be used with care, and full awareness of what it does, and does not, do.

Is it possible to turn a string into a function object?

I'm using Tkinter and matplotlib to create a small sorting array project. My Tkinter GUI has a listbox that I want to use to choose the desired sorting algorithm. I'm using matplotlib's FuncAnimation() to iterate repeatedly through my chosen sorting function and animate them. FuncAnimation() takes the name of the function that you decide to use as an argument. I wanted to assign the argument a variable that I could reassign to the name of any function that I wanted to use.
I believe the problem is that listbox.get(ANCHOR) gives me a string and FuncAnimation wants some sort of function object. I've looked into possible ways to a string into a function object or callable function but I'm either not understanding or not finding anything.
import matplotlib.pyplot as plt
import matplotlib.animation as animation
from Tkinter import *
import Tkinter as tk
#example of one of the sorting functions.
def Quick_Sort(i):
global arr # I don't know why I have to use a globalized variable. Wouldn't let me pass it arr
n=len(arr)
less_than=[]
equal_to=[]
greater_than=[]
if i in range(1,n-1):
if arr[i-1]>arr[i] or arr[i]>arr[i+1]:
#break into sub arrays
pivot=arr[i]
del arr[i]
for y in range(0,n-1):
plt.clf()
if arr[y]< pivot:
less_than.append(arr[y])
if arr[y]==pivot:
equal_to.append(arr[y])
elif arr[y]>pivot:
greater_than.append(arr[y])
del arr[:]
less_than.append(pivot)
arr=less_than + equal_to + greater_than
del less_than[:], greater_than[:], equal_to[:]
plt.bar(arr_ind,arr)
fig.canvas.draw()
elif i>n-1:
print("'i' is out of range. Exiting program.")
print ("Final array is ", arr)
sys.exit()
return i
def choose_and_run():
choice=listbox.get(ANCHOR)
fig=plt.figure()
ax=fig.add_axes([0,0,1,1])
fill_array(arr,arr_ind,arr_size)
fig.canvas.draw()
anim=animation.FuncAnimation(fig,choice,interval=50)
plt.show()
#---TKINTER STUFF-------
window=tk.Tk()
window.title("Sorting Arrays")
window.geometry("150x00")
listbox=tk.Listbox(window)
# Algorithm Options
listbox.insert(1,"Bubble_Sort")
listbox.insert(2,"Insertion_Sort")
listbox.insert(3,"Quick_Sort")
listbox.insert(4,"Selection_Sort")
listbox.pack()
# Select and run button
button1=tk.Button(window,text="Get and Go",command=choose_and_run).pack()
window.mainloop()
Hope this was enough information. Any help is appreciated.
You wouldn't normally convert a string to a function name directly, even if with Python just about anything's possible. However, functions are just objects so just use a dict:
chosenfunc = {"Bubble_Sort":Bubble_Sort, "Insertion_Sort":Insertion_Sort,
"Quick_Sort":Quick_Sort, "Selection_Sort":Selection_Sort}
selection=listbox.get(ANCHOR)
choice = chosenfunc[selection]
You could use locals() or globals() to get access to a dictionary with the local or global symbol table, respectively. You can use this if your functions are declared in the same module.
If not, you can use getattr on a module object:
import module
dynamically_imported_method = getattr(module, 'bar')
dynamically_import_method()

Pass Python function from outside to another function

I have a function, which calculate features from my data.
Here is a dummy sample of it
import numpy as np
val1=[1,2,3,4,5,6,7,8,9]
val2=[2,4,6,8,10,12,14,16]
data=[]
def feature_cal(val):
val=np.array(val)
value=val*2
data.append(np.mean(value))
feature_cal(val1)
feature_cal(val2)
What i want is to define the function np.mean() out of my function feature_cal.
Pseudo code
def feature_cal(val,method):
val=np.array(val)
value=val*2
data.append(method(value))
feature_cal(val1,method=np.mean())
feature_cal(val2,method=np.mean())
This will help me to calculate other features such as np.std(), np.var() without changing the original function
To pass the function you need to remove the parentheses after np.mean:
import numpy as np
def feature_cal(val, method):
val = np.array(val)
value = val*2
data.append(method(value))
feature_cal(val1, method=np.mean)
feature_cal(val2, method=np.mean)
EDIT
If you need to pass arguments to np.mean you can use functools.partial:
import numpy as np
import functools
def feature_cal(val, method):
val = np.array(val)
value = val*2
data.append(method(value))
bound_function = functools.partial(np.mean, axis=1)
feature_cal(val1, method=bound_function)
feature_cal(val2, method=bound_function)
If I got you correctly you need to pass callable and not result of function invocation as you do now. So this line
feature_cal(val1,method=np.mean())
Shouls read
feature_cal(val1,method=np.mean)
You can simply insert a method as a parameter into a function by entering the name of the method (without parentheses) and by reading the function you will call(with parentheses) the inserted parameter
def feature_cal(val,method):
val=np.array(val)
value=val*2
data.append(method(value))
feature_cal(val1,method=np.mean)

Sympy Lambdify with array inputs

I am trying to give an array as input and expect an array as output for the following code.
from sympy import symbols
from sympy.utilities.lambdify import lambdify
import os
from sympy import *
import numpy as np
text=open('expr.txt','r')
expr=text.read()
x,param1,param2=symbols('x param1 param2')
params=np.array([param1,param2])
T=lambdify((x,params),expr,modules='numpy')
data=np.genfromtxt('datafile.csv',delimiter=',')
print T(data[0],[0.29,4.5])
text.close()
But get the following error.
TypeError: <lambda>() takes exactly 3 arguments (13 given)
How do i tell sympy that its a single array? Thanks in advance.
1. Solution:
Your problem is, that the function T expects a value, but you are handing out a list. Try this instead of print T(data[0],[0.29,4.5])to get a list of results:
print [T(val,[0.29,4.5]) for val in data[0]]
Or use a wrapper function:
def arrayT(array, params):
return [T(val, params) for val in array]
print arrayT(data[0], [0.29, 4.5])
2. Solution: You have to change your mathematical expression. Somehow sympy doesn't work with list of lists, so try this:
expr = "2*y/z*(x**(z-1)-x**(-1-z/2))"
T=lambdify((x,y,z),expr,'numpy')
print T(data[0], 0.29, 4.5)

Why does my 'instance' turn into an 'ndarray' when I use Scipy optimize?

I have written a function using a quantum simulation class QuTIP that returns a float. Next, I called scipy.optimize.fmin_cg on the function. I keep getting the error:
AttributeError: 'numpy.ndarray' object has no attribute 'expm'
on the line:
U_sq = H_sq.expm
But H_sq is an instance of Qobj, not an ndarray. If I run the function outside of scipy.optimize.fmin_cg, it returns the type as 'instance'; when it runs inside of fmin_cg it returns the type as 'ndarray'.
Why does it do this? Is there a optimization function in python that will respect using instances like this?
Here is the code:
from qutip import *
from numpy import *
import scipy.optimize
def sq_fidelity(eps,N=7):
H_sq = squeez(N,eps);
print type(H_sq);
one_ph = basis(N,1);
U_sq = H_sq.expm();
squ = U_sq*one_ph;
fidelity = expect(fock_dm(N,1),squ);
return float(fidelity)
if __name__=='__main__':
print sq_fidelity(0.2);
eps = scipy.optimize.fmin_cg(sq_fidelity, x0=0.2, args=(7,));
The issue here is that fmin_cg is passing an ndarray (of length 1) to your objective function. You can extract the scalar value by just changing the first line of sq_fidelity to:
H_sq = squeez(N, float(eps))

Categories