Using a string in a function in python - python

I wrote a code to solve a differential problem (here I used a euler method just to check if it works, later I will use RK4 method). But I would like to turn it into a programm where the user input the function fun (defined as dx/dt=fun). Here my code :
from math import*
from pylab import*
import numpy as np
import matplotlib
import numpy as np
import matplotlib.pyplot as plt
t0=0.0;
x0=1.0; #conditions initiales
tmax=1.0; #temps max
h=0.01; #pas d'integration
N=int(abs(tmax-t0)/h)+1; #+1 pour arriver a T[N]=Tmax
X=np.zeros(N) #indice de n=0 -> N-1 (il y en a N)
T=np.zeros(N)
fun="-6.0*x";
def F(x1,t1):
x=x1;
t=t1;
F=eval(fun);
return F;
T[0]=t0;
X[0]=x0;
for i in range(1,N):
T[i]=T[i-1]+h;
X[i]=X[i-1]+F(X[i],T[i])*h;
plt.plot(T,X,label="Solution");
plt.title('RĂ©solution EDO ordre 1');
plt.xlabel('t');
plt.ylabel('x(t)');
plt.show();
legend()
My question is : the function F is defined with a eval function, and I read it is bad to use that. Have you other propositions ? Thanks !

Related

Optimize with another variable

sorry i am a real beginner in Python and I really need help to understand this:
So basically I have a function who takes 4 arguments:
def expected_utility(p,y,x,q):
return p*u(y-x+q-premium(p,q), theta)+(1-p)*u(y-premium(p,q))
(premium and u are function already defined)
I already have the value of p(=0.2) and y(=1) and I need to find the optimal q's* for several x between 0.01 and 0.9.
This is my entire code I have done so far:
import numpy as np
from scipy.optimize import minimize
import matplotlib.pyplot as plt
def premium(p,q):
return p*q
def u(z,theta):
return (z**(1+theta))/(1+theta)
def expected_utility(p,y,x,q):
return p*u(y-x+q-premium(p,q), theta)+(1-p)*u(y-premium(p,q))
theta=-2
y=1
p=0.2
N=100
x_array=np.linspace(0.01,0.9,N)
qs_optimal=np.empty(N)
And now I should create a loop for all x's in the x_array and use scipy.optimize.minimize_scalar to find all the optimals q's and store them in the qs_optimal array. How can I proceed? Thank you very very much for your help.

Python: ValueError: setting an array element with a sequence. Error while solving simple ode

I have written a simple python code to simulate adaptive fuzzy sliding mode control. My problem is no matter what I do, I get this error. I tried converting list to arrays etc. But to no effect. Kindly help me iron out this issue. What I am trying to do, is, I have created a function that returns 53 elements and then the ode method of scipy integrates it.
Here is my code. PFA-
import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import ode
from numpy import exp,sin,cos,concatenate,transpose,pi,tanh
from mpl_toolkits.mplot3d import Axes3D
c,eta,k,gamma1,gamma2,gamma3,gamma4,gamma5,gamma21,gamma22,gamma23,gamma24,gamma25=2,1.5,2,1,2,3,4,5,6,7,8,9,10
x=np.linspace(0,10,100)
xdot=np.linspace(0,10,100)
def member(x,z):
return exp(-((x+z)/(pi/24))**2)
m=[]
b=[pi/6,pi/12,0,-pi/12,-pi/6]
def f(t,Y):
x1,x2,x3,eta1,eta2,eta3,eta4,eta5,eta6,eta7,eta8,eta9,eta10,eta11,eta12,eta13,eta14,eta15,eta16,eta17,eta18,eta19,eta20,eta21,eta22,eta23,eta24,eta25,geta1,geta2,geta3,geta4,geta5,geta6,geta7,geta8,geta9,geta10,geta11,geta12,geta13,geta14,geta15,geta16,geta17,geta18,geta19,geta20,geta21,geta22,geta23,geta24,geta25=Y
eta=np.array([eta1,eta2,eta3,eta4,eta5,eta6,eta7,eta8,eta9,eta10,eta11,eta12,eta13,eta14,eta15,eta16,eta17,eta18,eta19,eta20,eta21,eta22,eta23,eta24,eta25])
geta=np.array([geta1,geta2,geta3,geta4,geta5,geta6,geta7,geta8,geta9,geta10,geta11,geta12,geta13,geta14,geta15,geta16,geta17,geta18,geta19,geta20,geta21,geta22,geta23,geta24,geta25])
m,z=[],[]
for i in range(5):
for j in range(5):
m.append(member(x1,b[i])*member(x2,b[j]))
for i in range(25):
z.append(m[i]/sum(m))
z=np.array(z)
e,de=x1-sin(t),x2-cos(t)
s=de+c**2*x3+2*c*e
f=np.dot(eta,z)
g=np.dot(geta,z)
u=(1./g)*(-f-c**2*e-2*c*de-sin(t)-eta*tanh(s)-k*s)
x1dot=x2
x2dot=f+g*u
x3dot=e
eta1dot,eta2dot,eta3dot,eta4dot,eta5dot,eta6dot,eta7dot,eta8dot,eta9dot,eta10dot,eta11dot,eta12dot,eta13dot,eta14dot,eta15dot,eta16dot,eta17dot,eta18dot,eta19dot,eta20dot,eta21dot,eta22dot,eta23dot,eta24dot,eta25dot,geta1dot,geta2dot,geta3dot,geta4dot,geta5dot,geta6dot,geta7dot,geta8dot,geta9dot,geta10dot,geta11dot,geta12dot,geta13dot,geta14dot,geta15dot,geta16dot,geta17dot,geta18dot,geta19dot,geta20dot,geta21dot,geta22dot,geta23dot,geta24dot,geta25dot=-2*s*z[0],-2*s*z[1],-2*s*z[2],-2*s*z[3],-2*s*z[4],-2*s*z[5],-2*s*z[6],-2*s*z[7],-2*s*z[8],-2*s*z[9],-2*s*z[10],-2*s*z[11],-2*s*z[12],-2*s*z[13],-2*s*z[14],-2*s*z[15],-2*s*z[16],-2*s*z[17],-2*s*z[18],-2*s*z[19],-2*s*z[20],-2*s*z[21],-2*s*z[22],-2*s*z[23],-2*s*z[24],-3*s*z[0]*u,-3*s*z[1]*u,-3*s*z[2]*u,-3*s*z[3]*u,-3*s*z[4]*u,-3*s*z[5]*u,-3*s*z[6]*u,-3*s*z[7]*u,-3*s*z[8]*u,-3*s*z[9]*u,-3*s*z[10]*u,-3*s*z[11]*u,-3*s*z[12]*u,-3*s*z[13]*u,-3*s*z[14]*u,-3*s*z[15]*u,-3*s*z[16]*u,-3*s*z[17]*u,-3*s*z[18]*u,-3*s*z[19]*u,-3*s*z[20]*u,-3*s*z[21]*u,-3*s*z[22]*u,-3*s*z[23]*u,-3*s*z[24]*u
return[x1dot,x2dot,x3dot,eta1dot,eta2dot,eta3dot,eta4dot,eta5dot,eta6dot,eta7dot,eta8dot,eta9dot,eta10dot,eta11dot,eta12dot,eta13dot,eta14dot,eta15dot,eta16dot,eta17dot,eta18dot,eta19dot,eta20dot,eta21dot,eta22dot,eta23dot,eta24dot,eta25dot,geta1dot,geta2dot,geta3dot,geta4dot,geta5dot,geta6dot,geta7dot,geta8dot,geta9dot,geta10dot,geta11dot,geta12dot,geta13dot,geta14dot,geta15dot,geta16dot,geta17dot,geta18dot,geta19dot,geta20dot,geta21dot,geta22dot,geta23dot,geta24dot,geta25dot]
Y,t=[],[]
for i in range(50):
Y.append(0.1)
#Y=np.array(Y)
y0=[0,0,0]
y0=y0+Y
t0=0
def int_amar():
t1,dt=10,.01
x=[]
for i in range(53):
x.append([])
#import pdb; pdb.set_trace()
odee=ode(f).set_integrator('dopri5',method='bdf',nsteps=1e6)
odee.set_initial_value(y0,t0)
while odee.successful() and odee.t<t1:
odee.integrate(odee.t+dt)
for i in range(53):
x[i].append(odee.y[i])
t.append(odee.t)
#for i in range(53):
# x[i]=np.array(x[i])
print(x1.shape)
return x
def main():
fun=int_amar()
Z,f,g,m=[[],[],[],[],[]],[],[],[]
for i in range(5):
for j in range(5):
m.append(member(fun[0],b[i])*member(fun[1],b[j]))
for i in range(25):
Z[i].append(m[i]/sum(m))
zetta1,zetta2,zetta3,zetta4,zetta5,zetta6,zetta7,zetta8,zetta9,zetta10,zetta11,zetta12,zetta13,zetta14,zetta15,zetta16,zetta17,zetta18,zetta19,zetta20,zetta21,zetta22,zetta23,zetta24,zetta25=Z[0],Z[1],Z[2],Z[3],Z[4],Z[5],Z[6],Z[7],Z[8],Z[9],Z[10],Z[11],Z[12],Z[13],Z[14],Z[15],Z[16],Z[17],Z[18],Z[19],Z[20],Z[21],Z[22],Z[23],Z[24],Z[25]
e=fun[0]-sin(t)
s=fun[1]+c**2*fun[2]+2*c*e
for i in range(len(fun[2])):
f.append(np.dot(np.array([[fun[3][i],fun[4][i],fun[5][i],fun[6][i],fun[7][i],fun[8][i],fun[9][i],fun[10][i],fun[11][i],fun[12][i],fun[13][i],fun[14][i],fun[15][i],fun[16][i],fun[17][i],fun[18][i],fun[19][i],fun[20][i],fun[21][i],fun[22][i],fun[23][i],fun[24][i],fun[25][i],fun[26][i],fun[27][i]]]),np.array([[zetta1[i]],[zetta2[i]],[zetta3[i]],[zetta4[i]],[zetta5[i]],[zetta6[i]],[zetta7[i]],[zetta8[i]],[zetta9[i]],[zetta10[i]],[zetta11[i]],[zetta12[i]],[zetta13[i]],[zetta14[i]],[zetta15[i]],[zetta16[i]],[zetta17[i]],[zetta18[i]],[zetta19[i]],[zetta20[i]],[zetta21[i]],[zetta22[i]],[zetta23[i]],[zetta24[i]],[zetta25[i]]])))
g.append(np.dot(np.array([[fun[28][i],fun[29][i],fun[30][i],fun[31][i],fun[32][i],fun[33][i],fun[34][i],fun[35][i],fun[36][i],fun[37][i],fun[38][i],fun[39][i],fun[40][i],fun[41][i],fun[42][i],fun[43][i],fun[44][i],fun[45][i],fun[46][i],fun[47][i],fun[48][i],fun[49][i],fun[50][i],fun[51][i],fun[52][i]]]),np.array([[zetta1[i]],[zetta2[i]],[zetta3[i]],[zetta4[i]],[zetta5[i]],[zetta6[i]],[zetta7[i]],[zetta8[i]],[zetta9[i]],[zetta10[i]],[zetta11[i]],[zetta12[i]],[zetta13[i]],[zetta14[i]],[zetta15[i]],[zetta16[i]],[zetta17[i]],[zetta18[i]],[zetta19[i]],[zetta20[i]],[zetta21[i]],[zetta22[i]],[zetta23[i]],[zetta24[i]],[zetta25[i]]])))
f,g=np.array(f),np.array(g)
u=(1./g)*(-f-c*e-sin(t)-eta*tanh(s)-k*s)
print(u.shape)
for i in range(12):
plt.subplot(3,4,i+1)
plt.plot(t,fun[i])
#plt.figure(2)
#plt.plot(t,u)
plt.show()
if __name__=='__main__':
main()
The issue is on line 30:
u=(1./g)*(-f-c**2*e-2*c*de-sin(t)-eta*tanh(s)-k*s)
eta is an array but the rest of the terms are scalars. This causes u to be an array and the resulting return list has a mix of scalars and arrays.
You probably mistyped the equation here.

Plotting in python using matplotlib?

I have been trying to simulate the first order differential equation using the fourth order Runge-Kutta method, but I am having problems plotting it.
#simulation of ode using 4th order rk method dy/dx=-2y+1.3e^-x,y(0)=5,h=0.01 from sympy import*
import math
import numpy as np
import matplotlib.pyplot as plt
h=0.01;
ti=0;
x=0;
n=0;
y=5;
def f(x,y):
return 1.3*math.exp(-x)-2*y
while x < 10:
k1=f(x,5);
k2=f(x+h/2,y+(h/2)* k1);
k3=f(x+h/2,y+(h/2)* k2);
k4=f(x+h,y+h*k3);
y=y+h/6*(k1+2*(k2+k3)+k4);
x=x+h;
plt.plot(x,y);
I know that the problem is because of updating the x,y values every time the loop runs, but can somebody explain how to plot all the values of (x,y)?
As suggested in the comment, you can create two lists to store x and y values and plot it after the while loop:
import math
import numpy as np
import matplotlib.pyplot as plt
h=0.01;
ti=0;
x=0;
n=0;
y=5;
def f(x,y):
return 1.3*math.exp(-x)-2*y
xs = [x] # <<<
ys = [y] # <<<
while x < 10:
k1=f(x,5);
k2=f(x+h/2,y+(h/2)* k1);
k3=f(x+h/2,y+(h/2)* k2);
k4=f(x+h,y+h*k3);
y=y+h/6*(k1+2*(k2+k3)+k4);
x=x+h;
xs.append(x) # <<<
ys.append(y) # <<<
plt.plot(xs,ys);
Another source for wrong results is the first line in the RK4 loop. Instead of
k1=f(x,5);
use
k1=f(x,y);
since the value of y does not stay constant at the initial value.

Plotting 2D integral function in python

Here is my first steps within the NumPy world.
As a matter of fact the target is plotting below 2-D function as a 3-D mesh:
N = \frac{n}{2\sigma\sqrt{\pi}}\exp^{-\frac{n^{2}x^{2}}{4\sigma^{2}}}
That could been done as a piece a cake in Matlab with below snippet:
[x,n] = meshgrid(0:0.1:20, 1:1:100);
mu = 0;
sigma = sqrt(2)./n;
f = normcdf(x,mu,sigma);
mesh(x,n,f);
But the bloody result is ugly enough to drive me trying Python capabilities to generate scientific plots.
I searched something and found that the primary steps to hit above mark in Pyhton might be acquired by below snippet:
from matplotlib.patches import Polygon
import numpy as np
from scipy.integrate import quad
import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
sigma = 1
def integrand(x,n):
return (n/(2*sigma*np.sqrt(np.pi)))*np.exp(-(n**2*x**2)/(4*sigma**2))
t = np.linespace(0, 20, 0.01)
n = np.linespace(1, 100, 1)
lower_bound = -100000000000000000000 #-inf
upper_bound = t
tt, nn = np.meshgrid(t,n)
real_integral = quad(integrand(tt,nn), lower_bound, upper_bound)
Axes3D.plot_trisurf(real_integral, tt,nn)
Edit: With due attention to more investigations on Greg's advices, above code is the most updated snippet.
Here is the generated exception:
RuntimeError: infinity comparisons don't work for you
It is seemingly referring to the quad call...
Would you please helping me to handle this integrating-plotting problem?!...
Best
Just a few hints to get you in the right direction.
numpy.meshgrid can do the same as MatLABs function:
http://docs.scipy.org/doc/numpy/reference/generated/numpy.meshgrid.html
When you have x and n you can do math just like in matlab:
sigma = numpy.sqrt(2)/n
(in python multiplication/division is default index by index - no dot needed)
scipy has a lot more advanced functions, see for example How to calculate cumulative normal distribution in Python for a 1D case.
For plotting you can use matplotlibs pcolormesh:
import matplotlib.pyplot as plt
plt.pcolormesh(x,n,real_integral)
Hope this helps until someone can give you a more detailed answer.

Plotting a signal in Python

I'm trying to plot a simple signal in python, and when i run this it doesn't show any error only 'Restart' and a blank space
from pymatlab import*
import numpy as np
from numpy import sqrt
import matplotlib.pyplot as plt
import scipy as sp
import math
(hashtags) n, coef, freq, phase
def sinyal(N,c,f,p):
y=np.zeros(N)
t=np.linspace(0,2*pi,N)
Nf=len(c)
for i in range(Nf):
y+=c[i]*np.sin(f[i]*t)
return y;
# Signal Generator
c=[2,5,10]
f=[50, 150, 300]
p=[0,0]
N=2000
x=np.linspace(0,2.0*math.pi,N)
y=sinyal(N,c,f,p)
plt.plot(x[:100],y[:100])
plt.show()
The code you posted has a logical indentation error. The call to sinyal is indented one level, placing it inside the definition of sinyal itself. So although sinyal gets defined, it never gets called.
Using 4 spaces for indentation may help you avoid this error in the future.
Your code basically works (apart from some formatting errors and other oddities). I don't have pymatlab but it isn't necessary for this.
import numpy as np
from numpy import sqrt
import matplotlib.pyplot as plt
import scipy as sp
import math
def sinyal(N,c,f,p):
y=np.zeros(N)
t=np.linspace(0,2*np.pi,N)
Nf=len(c)
for i in range(Nf):
y+=c[i]*np.sin(f[i]*t)
return y;
# Signal Generator
c=[2,5,10]
f=[50, 150, 300]
p=[0,0]
N=2000
x=np.linspace(0,2.0*math.pi,N)
y=sinyal(N,c,f,p)
plt.plot(x[:100],y[:100])
plt.show()

Categories