"'numpy.ndarray' object is not callable" - python

I've got a problem with my code. I want to get a referential solution for a model that shall describe the populations of bears and trouts and their interconnection.
I can't find what I did wrong, but python calls three lines with problems and end with the error 'numpy.ndarray' object is not callable'. What am I doing wrong?
import matplotlib.pyplot as plt
import numpy as np
from scipy.interpolate import interp1d
def referenz_loesung(f, ref_loeser, x0, t0, T):
print "Berechne Referenzloesung..."
h_ref = 0.0001
#it mentions the following line as problematic
t_punkte, x_punkte = ref_loeser(f, x0, t0, T, h_ref) #it mentions this line as problematic
print "Erstelle Funktionen aus Referenzloesungen mit Hilfe von Splines."
a = interp1d(t_punkte, x_punkte[: , 0])
b = interp1d(t_punkte, x_punkte[: , 1])
return a, b
if __name__ == "__main__":
def f(x, t): # Funktion aus vorherigen Uebungen der DGL: x'(t) = f(x(t), t)
y = np.zeros(2)
y[0] = -2*x[0] + 10 * x[1]
y[1] = -x[0]
return y
x0 = np.array([1., 0.])
t0 = 0
T = 10
h = 0.5
from unsersolver import integriere
#it mentions the following line as problematic
t_punkte, x_werte = integriere (f, x0, t0, T, h)
from implEuler import integriere as ref_loeser
#it mentions the following line as problematic
x1_ref, x2_ref = referenz_loesung(f,ref_loeser, x0, t0, T)
ref_punkte = np.linspace(t0, T, 1000)
from woche1_1_m import auswerten_nx1
ref_werte1 = auswerten_nx1(x1_ref, ref_punkte)
ref_werte2 = auswerten_nx1(x2_ref, ref_punkte)
The things I import are from other files from earlier weeks that all work actually work properly.
Any idea what I could do? I'm at the very start of learning python, so I don't really have a clue.
Thanks!

It would be more helpful if you could post the code for integriere() or ref_loeser().
With the information I have let me ask you to try back-tracing to the root of the problem:
Start of the problem is t_punkte, x_werte = integriere(f, x0, t0, T, h) which you say gives a numpy error, and since the only numpy parameter you're passing to this is x0, i'd suggest checking the usage of x0 in your integriere() code.
Next, I'd suggest not passing a function as a parameter, I don't think that is a standard convention. You could define a def ref_loeser(parameters..) outside the refrenz_loesung() function call, and then call it like you did.
And since referenz_loesung() calls ref_loeser() which is the same as integriere() I highly recommend you to check the code in this function.
Good luck!

x_lsg = berechne_nullstelle(x_werte(n-1)) <--- error
x_lsg = berechne_nullstelle(x_werte[n-1]) works?
x_werte is an ND-array, you need to access the n-1 element, use x_werte[n-1] instead.
The ( ) is for function calls, so python interpreter assumed you were calling an numpy.ndarry and hence threw that error

You would get this error if e.g. you put x0() in your code. It's impossible for us to tell what the real error is without the source of the other modules.
My best guess: is it possible that you got the parameters to integriere in the wrong order? If so, perhaps that function tries to call the parameter, expecting it to be a function, but because you've put a numpy array in that parameter it gets "called" instead?

So, this is the code for the implEuler file. The 'unsersolver' should be correct as it was given to me by the teacher...
import matplotlib.pyplot as plt
import numpy as np
from newton import berechne_nullstelle
def integriere(f, x0, t0, T, h):
d = len(x0)
t_punkte = np.arange(t0, T, h)
N = len(t_punkte)
x_werte = np.zeros ((N, d))
x_werte[0] = x0
for n in range(1, N):
def f_implEuler(x):
x_werte^(n-1) + h * f(x_werte, t_punkte^(n)) - x_werte
x_lsg = berechne_nullstelle(x_werte(n-1))
x_werte[n] = x_lsg
print integriere
Does that help in any way?

Related

Python fmin using lambda expression

I have the following function for which I try to solve Vcr for given S,h,g:
Vcr/np.sqrt(g*h)=((2/3)*(1-S+ (Vcr**2)/(2*g*h)))**(3/2)
I do as follows:
from scipy.optimize import fsolve
import numpy as np
S = 0.06
h = 15.14
g = 9.8
def eqn(Vcr,g,h,S):
return (Vcr/np.sqrt(g*h)-((2/3)*(1-S+ (Vcr**2)/(2*g*h)))**(3/2))
ans = fsolve(lambda Vcr,g,h,S: eqn(Vcr,g,h,S), x0=5, args=(S,h,g))
print(eqn(ans,g,h,S))
The answer prints 4.9109. This answer is NOT correct. I checked this in Matlab:
fun = #(Vcr) Vcr./sqrt(g*h)-((2/3)*(1-S+ (Vcr.^2)./(2*g*h))).^(3/2);
sol = fzero(fun, 5); % solution critical speed;
# sol = 8.5970
The solution is then substituted in the Python equation and gives me: print(eqn(8.5970,g,h,S))=0
So indeed it should be 8.5970.
How can I solve this in Python with an expression close to the given matlab expression (with anonymous function)? If it is possible I don't want to define a function as def():
The extra arguments to the function must be passed in the order the function expects, you reversed them (args=(S,h,g) while your function declares them in the opposite order: lambda Vcr,g,h,S:).
Putting them in the right order gives you the expected solution:
from scipy.optimize import fsolve
import numpy as np
S = 0.06
h = 15.14
g = 9.8
def eqn(Vcr,g,h,S):
return (Vcr/np.sqrt(g*h)-((2/3)*(1-S+ (Vcr**2)/(2*g*h)))**(3/2))
ans = fsolve(lambda Vcr,g,h,S: eqn(Vcr,g,h,S), x0=5, args=(g, h, S))
print(ans, eqn(ans,g,h,S))
# [8.5970162] [1.11022302e-16]

How to properly implement scipy.integrate.Radau?

(I'll apreciate even a link to an example, so far I haven't found any.)
I am trying to use Radau from scipy.integrate to solve second order differential equation. For now I am trying just a simple example, so that I can uderstand how it works (unsuccessfully so far).
Let's say that I have following equation:
d^2y/dt^2 = C,
which means that y = (Ct^2)/2 + Bt.
Let's say, for example, y(1) = 1 and C = 2. Let's say that I want to find value of y for t = 10.
This is my code:
from scipy.integrate import Radau
import numpy as np
C = 2.0
y = np.zeros(2)
def fun(t, y):
#y[0] = C*t
y[1] = C
return y
t0 = 1.0
y0 = np.array([1., 1.])
t_bound = 10.0
eq = Radau(fun, t0, y0, t_bound)
print(eq.n)
while(True):
print(eq.t)
print(eq.y)
print(eq.status)
if eq.status == 'finished':
break
eq.step()
Outputs is wrong. (If I uncomment that one commented line in fun definition, it also gives wrong answer. But I think that I shouldn't even have to tell solver that, right? I don't know this value usually.)
I think my biggest problem is that I am not really sure what should be passed as fun. Documentation says it should be right-hand side of the system, so I thought that first derivation should be in y[0], second derivation in y[1] etc.
What am I doing wrong? How should this be implemented?
Atm you are solving
y0' = y0, y0(1)=1
y1' = 2, y1(1)=1
which has the solution y0(t)=exp(t-1) and y1(t)=2*t-1 which is certainly not what you want. You want the first order system
y0' = y1
y1' = C
so that you need
def fun(t,y): return [y[1], C]
Then the solution is y1(t)=C*t+B=2*t-1 and y0(t)=0.5*C*t^2+B*t+A=t^2-t+1 and the integration ends correctly with eq.y = [91. 19.].

Iteration for the definition of a function

I would like to make an iteration in order to get a function verifying an integral equation. The integral operator is hidden in the function lambdaop. However, I just cannot iterate on the process getting an error
File "blablabla/.spyder-py3/temp.py", line 11, in integrand
return -0.5*f(x)*scipy.special.expi(-abs(x-tau))
TypeError: can't multiply sequence by non-int of type 'float'
that I do not understand. I have done here for only two functions by my ultimate goal would be to make n iteration. I guess the error comes from the way of defining the function that is not suitable (maybe not use "lambda definitions" ... ) but I do not want to create a vector of size n in place of the function since I want to integrate it after. Anyone has an idea how to fix this problem ?
import numpy as np
import matplotlib.pyplot as plt
import math
import scipy.integrate
import scipy.special
def initial(x):
return x + 2/3
def integrand(f,x,tau):
return -0.5*f(x)*scipy.special.expi(-abs(x-tau))
def lambdaop(f,x,tau):
def step(x,tau):
return integrand(f,x,tau)
g = lambda tau: scipy.integrate.quad(step,0,np.inf,args=(tau,))
return g
g = lambdaop(initial,1,2)
h = lambdaop(g,1,2)
print(h(5))
x = np.linspace(0,3,101)
y = np.linspace(0,3,101)
for i in np.arange(101):
y[i] = h(x[i])[0]
plt.plot(x,y)
plt.show()
I have not seen any other topic like mine but in case it is a duplicate, please excuse me.
Add some print statements in your integrand function.
For example,
def integrand(f,x,tau):
print('-------')
print('args:', f, x, tau)
v = f(x)
print(f'f({x})={v}')
s = scipy.special.expi(-abs(x-tau))
print(f's={s}')
result = -0.5*v*s
print('=====')
return result
and you'll see that:
f(1.0)=(inf, inf)
s=-0.0037793524098489063
The (inf, inf) is where the error message is coming from.

How to put an integral in a function in python/matplotlib

So pretty much, I am aiming to achieve a function f(x)
My problem is that my function has an integral in it, and I only know how to construct definite integrals, so my question is how does one create an indefinite integral in a function (or there may be some other method I am currently unaware of)
My function is defined as :
(G is gravitational constant, although you can leave G out of your answer for simplicity, I'll add it in my code)
Here is the starting point, but I don't know how to do the integral portion
import numpy as np
def f(x):
rho = 5*(1/(1+((x**2)/(3**2))))
function_result = rho * 4 * np.pi * x**2
return function_result
Please let me know if I need to elaborate on something.
EDIT-----------------------------------------------------
I made some major progress, but I still have one little error.
Pretty much, I did this:
from sympy import *
x = Symbol('x')
rho = p0()*(1/(1+((x**2)/(rc()**2))))* 4 * np.pi * x**2
fooply = integrate(rho,x)
def f(rx):
function_result = fooply.subs({x:rx})
return function_result
Which works fine when I plug in one number for f; however, when I plug in an array (as I need to later), I get the error:
raise SympifyError(a)
sympy.core.sympify.SympifyError: SympifyError: [3, 3, 3, 3, 3]
(Here, I did print(f([3,3,3,3,3]))). Usually, the function returns an array of values. So if I did f([3,2]) it should return [f(3),f(2)]. Yet, for some reason, it doesn't for my function....
Thanks in advance
how about:
from sympy import *
x, p0, rc = symbols('x p0 rc', real=True, positive=True)
rho = p0*(1/(1+((x**2)/(rc))))* 4 * pi * x**2
fooply = integrate(rho,x)/x
rho, fooply
(4*pi*p0*x**2/(1 + x**2/rc),
4*pi*p0*rc*(-sqrt(rc)*atan(x/sqrt(rc)) + x)/x)
fooply = fooply.subs({p0: 2.0, rc: 3.0})
np_fooply = lambdify(x, fooply, 'numpy')
print(np_fooply(np.array([3,3,3,3,3])))
[ 29.81247362 29.81247362 29.81247362 29.81247362 29.81247362]
To plug in an array to a SymPy expression, you need to use lambdify to convert it to a NumPy function (f = lambdify(x, fooply)). Just using def and subs as you have done will not work.
Also, in general, when using symbolic computations, it's better to use sympy.pi instead of np.pi, as the former is symbolic and can simplify. It will automatically be converted to the numeric pi by lambdify.

How to define a one variable function from another multivariable function

I am trying to define a one variable g function from a multivariable function G:
def dG(thetaf,psi,gamma) :
return 0.35*(cos(psi))**2*(2*sin(3*thetaf/2+2*gamma)+(1+4*sin(gamma)**2)*sin(thetaf/2)-sin(3*thetaf/2))+sin(psi)**2*sin(thetaf/2)
g = lambda thetaf: dG(thetaf,psi,gamma)
unfortunately this is not working and the error i receive is that :
only length-1 arrays can be converted to Python scalars
You have to define some default values. If you do this by using keyword arguments, you don't even need to define a separate function.
from numpy import sin, cos, arange
def dG(thetaf,psi=0.5,gamma=1) :
return 0.35*(cos(psi))**2*(2*sin(3*thetaf/2+2*gamma)+(1+4*sin(gamma)**2)*sin(thetaf/2)-sin(3*thetaf/2))+sin(psi)**2*sin(thetaf/2)
thetaf = arange(10)
print dG(thetaf)
>>> [ 0.4902 0.1475 0.5077 1.6392 1.757 0.4624 -0.472 -0.2416 -0.2771 -1.3398]
You actually can define a separate function, but using keyword defaults is the cleaner alternative.
g = lambda tf: dG(tf, 0.5, 1)
g(thetaf)
array([ 0.4902, 0.1475, 0.5077, 1.6392, 1.757 , 0.4624, -0.472 ,
-0.2416, -0.2771, -1.3398])
Next time, please include the script in your original question in a nice format. It makes helping go faster.
I think it is just a simple mistake. You get theta and phi out of gamma and psi respectively, but then you never use them. Did you mean to use those as your parameters in g? If so, then it should look something like this
from numpy import sin, cos, arange, linspace, pi, zeros
import scipy.optimize as opt
def dG(thetaf, psi, gamma):
return 0.35*(cos(psi))**2*(2*sin(3*thetaf/2+2*gamma)+(1+4*sin(gamma)**2)*sin(thetaf/2)-sin(3*thetaf/2))+sin(psi)**2*sin(thetaf/2)
nt = 100
np = 100
gamma = linspace(0, pi/2, nt)
psi = linspace(0, pi/2, np)
x = zeros((nt, np))
for i, theta in enumerate(gamma):
for j, phi in enumerate(psi):
print('i = %d, j = %d') %(i, j)
g = lambda thetaf: dG(thetaf,phi,theta)
x[i,j] = opt.brenth(g,-pi/2,pi/2)

Categories