Python2 convert function output list to callable array - python

I have a program I've been working on all weekend and it contains the correct output, however it outputs a list that is not callable, and I need to be able to build a plot from it. How do I modify the list to make it callable?
Homework #3 - Convolution
import numpy as np
#import matplotlib.patches as mpatches
import matplotlib.pyplot as plt
np.set_printoptions(threshold=np.nan)
#04-01 Convolution
def conv395(x,h):
#Function to convolve x input signal and h impulse response
M = len(h)-1
L = len(x)
Ly = M+L
LOL = []
def ConV(x,h,n):
y = (h[m]*x[(n-1)-m])
return (y)
for n in range(0,Ly+1):
mx = n-L+1
if mx < 1:
n = n+1
#print("SPACE")
Y1 = 0
if n <= M+1:
L1 = []
for m in range(n):
#print(n)
y = ConV(x,h,n)
Y1 = y + Y1
L1.append(Y1)
LOL.append(str(L1))
#print Y,
###LOL = np.int32(LOL)
if n > M+1:
#print("Space")
L2 = []
N = n-1
n = M+1
Y2 = 0
for m in range(n):
y2 = h[m]*x[(N-m)]
Y2 = Y2 + y2
L2.append(Y2)
LOL.append(str(L2))
if mx > 1:
#print("space")
L3 = []
if n > M+1:
Y3 = 0
for m in range(n-L,M+1):
y3 = h[m]*x[m-(n-L)]
Y3 = Y3 + y3
L3.append(Y3)
LOL.append(str(L3))
return(LOL)
h = [1,2,-1,1]
x = [1,1,2,1,2,2,1,1]
Y = conv395(x,h)
print(callable(Y))
The OUTPUT shows that the list is not callable, and I the output looks like this ['[1]', '[3]', '[3]', '[5]', '[3]', '[7]', '[4]', '[3]', '[3]', '[0]', '[1]']
I've tried every form of conversion I could find on the internet and it won't budge. Suggestions?

Related

Trying to solve a system of 6 1st ODEs in python. Almost there but am getting errors

I just have place holders for the initial conditions. But it seems the u function is the main issue. In removing it and replacing it as a constant I get a float int error. I feel like I'm almost there and am just making a small mistake.
enter image description here
code:
import numpy as np
import matplotlib as mpl
import matplotlib.pyplot as plt
mpl.rc('text', usetex = True)
mpl.rc('font', family = 'serif', size=16)
from scipy.integrate import solve_ivp
%matplotlib inline
def EulerSys(F, y0, ti, tf, h):
t = np.arange(ti, tf+h, h)
n = len(t)
neq = len(y0)
x = np.zeros((neq, n))
x[:,0] = y0
for i in range(t.size - 1):
# [new value] = [old value] + [slope x step size]
x[:,i+1] = x[:,i] + h*F( t[i], x[:,i] )
return x
m1=55
m2=400
m3=100
k1=230000
k2=30000
k3=50000
k4=0
b2=1500
b3=4000
b4=700
L0=5
v=15
A=0.03
h = .05
ti =0
tf =3.2
t = np.arange(ti, tf+h, h)
# the initial conditions:
x0 = np.array([ 2.0, 0.0 , 1, 1,1,1])
n = len(t)
neq = len(x0)
# initialize the vector to store the solutions:
# the rows are the solutions, the columns are the time instances:
x = np.zeros((neq, n))
# store the initial conditions:
x[:,0] = x0
print(x)
def myFun(t,x):
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0)))
n = len(x)
dx = np.zeros((n))
dx[0] = x[1]
dx[1] = (-(b2 + b4)*x[1]+b2*x[3]+b4*x[5]-[k1+k2+k4]*x[0]+k2*x[2]+k4*x[4]+k1*u)/m1
dx[2] = x[3]
dx[3] = (b2*x[1]-(b2+b3)*x[3]+b3*x[5]+k2*x[0]-(k2+k3)*x[2]+k3*x[4])/m2
dx[4] = x[5]
dx[5] = (b4*x[1]+b3*x[3]-(b3+b4)*x[5]+k4*x[0]+k3*x[2]-(k3+k4)*x(4))/m3
return dx
xsol= EulerSys(myFun, x0, ti, tf, h)
you are simply missing one bracket at the end.
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0)))
should be:
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0)))) # one more bracket
here is the test code that is stripped from the original question:
import numpy as np
# define variables needed
A = 1
v = 1
L0 = 1
u = lambda t: (A/2)*(1-np.cos(2*(3.14*(v*t/L0))))
print(u(1))
the result (with test numbers) is this:
2.536543312392503e-06

Difference in numpy and sympy lambdify results for basic optimization

I wrote following code for basic optimization based on Newton's method by writing derivatives explicitly and by calculating them using sympy. Why are the results different?
Writing derivatives explicitly:
import numpy as np
def g(x):
return 1.95 - np.exp(-2/x) - 2*np.exp(-np.power(x,4))
# gd: Derivative of g
def gd(x):
return -2*np.power(x,-2)*np.exp(-2/x) + 8*np.power(x,3)*np.exp(-np.power(x,4))
def gdd(x):
return -4*np.power(x,-3)*np.exp(-2/x)-4*np.power(x,-4)*np.exp(-2/x)+24*np.power(x,2)*np.exp(-np.power(x,4))-32*np.power(x,6)*np.exp(-np.power(x,4))
# Newton's
def newton_update(x0,g,gd):
return x0 - g(x0)/gd(x0)
# Main func
x0 = 1.00
condition = True
loops = 1
max_iter = 20
while condition and loops<max_iter:
x1 = newton_update(x0,gd,gdd)
loops += 1
condition = np.abs(x0-x1) >= 0.001
x0 = x1
print('x =',x0)
if loops == max_iter:
print('Solution failed to converge. Try another starting value!')
Output:
x = 1.66382322329
x = 1.38056881356
x = 1.43948432592
x = 1.46207570893
x = 1.46847791968
x = 1.46995571549
x = 1.47027303095
Using sympy and lambdify:
import sympy as sp
x = sp.symbols('x',real=True)
f_expr = 1.95 - exp(-2/x) - 2*exp(-x**4)
dfdx_expr = sp.diff(f_expr, x)
ddfdx_expr = sp.diff(dfdx_expr, x)
# lambidify
f = sp.lambdify([x],f_expr,"numpy")
dfdx = sp.lambdify([x], dfdx_expr,"numpy")
ddfdx = sp.lambdify([x], ddfdx_expr,"numpy")
# Newton's
x0 = 1.0
condition = True
loops = 1
max_iter = 20
while condition and loops<max_iter:
x1 = newton_update(x0,dfdx,ddfdx)
loops += 1
condition = np.abs(x0-x1) >= 0.001
x0 = x1
print('x =',x0)
if loops == max_iter:
print('Solution failed to converge. Try another starting value!')
Output:
x = 1.90803013971
x = 3.96640484492
x = 6.6181614689
x = 10.5162392894
x = 16.3269006983
x = 25.0229734288
x = 38.0552735534
x = 57.5964036862
x = 86.9034400129
x = 130.860980508
x = 196.795321033
x = 295.695535237
x = 444.044999522
x = 666.568627836
x = 1000.35369299
x = 1501.03103981
x = 2252.04689304
x = 3378.57056168
x = 5068.35599056
Solution failed to converge. Try another starting value!
I made it to work by step halving in newton_update function whenever sign of derivative changes in the update. But I couldn't figure out why the results were so different with the same starting point. Also is it possible to get the same results from both?
There is a mistake in the second derivative formula in the function gdd. changing
def gdd(x):
return -4*np.power(x,-3)*np.exp(-2/x)-4*np.power(x,-4)*np.exp(-2/x)+24*np.power(x,2)*np.exp(-np.power(x,4))-32*np.power(x,6)*np.exp(-np.power(x,4))
to
def gdd(x):
return 4*np.power(x,-3)*np.exp(-2/x)-4*np.power(x,-4)*np.exp(-2/x)+24*np.power(x,2)*np.exp(-np.power(x,4))-32*np.power(x,6)*np.exp(-np.power(x,4))
should resolve the issue and produce the same result in both cases, which will be
x = 1.90803013971
x = 3.96640484492
x = 6.6181614689
x = 10.5162392894
x = 16.3269006983
x = 25.0229734288
x = 38.0552735534
x = 57.5964036862
x = 86.9034400129
x = 130.860980508
x = 196.795321033
x = 295.695535237
x = 444.044999522
x = 666.568627836
x = 1000.35369299
x = 1501.03103981
x = 2252.04689304
x = 3378.57056168
x = 5068.35599056
Solution failed to converge. Try another starting value!
This points to a problem with choosing the step size as per the comment

Numpy arange error with Lagrange Multiplier in Python

I try to use Lagrange multiplier to optimize a function, and I am trying to loop through the function to get a list of number, however I got the error
ValueError: setting an array element with a sequence.
Here is my code, where do I go wrong? If the n is not an array I can get the result correctly though
import numpy as np
from scipy.optimize import fsolve
n = np.arange(10000,100000,10000)
def func(X):
x = X[0]
y = X[1]
L = X[2]
return (x + y + L * (x**2 + y**2 - n))
def dfunc(X):
dLambda = np.zeros(len(X))
h = 1e-3
for i in range(len(X)):
dX = np.zeros(len(X))
dX[i] = h
dLambda[i] = (func(X+dX)-func(X-dX))/(2*h);
return dLambda
X1 = fsolve(dfunc, [1, 1, 0])
print (X1)
Helps would be appreciated, thank you very much
First, check func = fsolve()
Second, print(func([1,1,0]))` - result in not number ([2 2 2 2 2 2 2 2 2]), beause "n" is list. if you want to iterate n try:
import numpy as np
from scipy.optimize import fsolve
n = np.arange(10000,100000,10000)
def func(X,n):
x = X[0]
y = X[1]
L = X[2]
return (x + y + L * (x**2 + y**2 - n))
def dfunc(X,n):
dLambda = np.zeros(len(X))
h = 1e-3
r = 0
for i in range(len(X)):
dX = np.zeros(len(X))
dX[i] = h
dLambda[i] = (func(X+dX,n)-func(X-dX,n))/(2*h)
return dLambda
for iter_n in n:
print("for n = {0} dfunc = {1}".format(iter_n,dfunc([0.8,0.4,0.3],iter_n)))

Python - Cutting an array at a designated point based on value in row

I have a 300 x 4 matrix called X created by the odeint function. In the second column are y-values and I would like to cut the matrix when the y-value dips below 0. As a first step I was attempting to create a function that would read the second column and spit out the row number where the column first dips below 0.
X = odeint(func, X0, t)
Yval = X[:,1]
def indexer():
i = 0
if Yval[i] > 0:
i = i + 1
if Yval[i] < 0:
return i
Which is not working and conceptually I know this is wrong, I just couldn't think of another way to do this. Is there a way to cut out all the rows that contain and follow the first <0 y value?
This is my entire code:
import numpy as np
import math
from scipy.integrate import odeint
g = 9.8
theta = (45 * math.pi)/180
v0 = 10.0
k = 0.3
x0 = 0
y0 = 0
vx0 = v0*math.sin(theta)
vy0 = v0*math.cos(theta)
def func(i_state,time):
f = np.zeros(4)
f[0] = i_state[2]
f[1] = i_state[3]
f[2] = -k*(f[0]**2 + f[1]**2)**(.5)*f[0]
f[3] = -g - k*(f[0]**2 + f[1]**2)**(.5)*f[1]
return f
X0 = [x0, y0, vx0, vy0]
t0 = 0
tf = 3
timestep = 0.01
nsteps = (tf - t0)/timestep
t = np.linspace(t0, tf, num = nsteps)
X = odeint(func, X0, t)
Yval = X[:,1]
def indexer():
i = 0
if Yval[i] > 0:
i = i + 1
if Yval[i] < 0:
return i
Maybe you could use the takewhile function from the itertools package:
from itertools import takewhile
first_elements = list(takewhile(lambda x: x[1] >= 0, X))
Where X is your matrix. I used x[1] in the lambda predicate to compare the numbers in the second column.
Here, first_elements will be the rows of the matrix before the first row that contains a value less than zero. You can use len(first_elements) to know what the cutoff point was.
I converted it to a list but you don't have to if you are just going to iterate through the result.
I hope this works.
You could do something like this:
newVals = []
i = 0
while( i < len(X) and X[i][1] >= 0):
newVals.append(X[i])
i += 1
This would go through X and append values to the list newVals until you either reach the end of the list (i < len(X)) or you reach your condition (X[i][1] >= 0).

Adding two arrays of different width using numpy

I am learning Numpy as a substitute to Matlab. I am having problem mapping Matlab function to Numpy. Program is to add two signals using Matlab
Matlab version :
function [y.d = sigadd(xl,nl,x2,n2)
% implements y(n) = xi(n)+x2(n)
% [y,nl - sigadd(xi,nl,x2,n2)
X
% xi = first sequence over nl
% x2 - second sequence over n2 (n2 can be different from nl)
%
n = min(min(n1) ,min(n2)) :max(max(nl) ,max(n2)) ; X duration of y(n)
yl - zeros(l,length(n)); y2 = yl;
yl(find((n>=min(nl))&(n<cmar(nl))-l))lxl;
y2(find((n>=min(n2))&(n<=max(n2))==1))=x2;
y = yl+y2;
I have tried the following in Python :
def SigAdd(x1,n1,x2,n2):
n_l = min(min(n1),min(n2))
n_h= max(max(n1),max(n2))
n = arange(n_l,n_h+1)
y1 = zeros([1,len(n)],int)
y2 = y1
y1 = (argwhere((n>=min(n1))&(n<=max(n1)))==1)
y1 = x1
y2 = (argwhere((n>=min(n2))&(n<=max(n2)))==1)
y2 = x2
y = y1 + y2
return y,n
Expected Results:
Example1: Arrays of unequal length
x1 = array([1,1,1,1,1])
x2 = array([1,1,1,1])
n1 = array([1,2,3,4,5])
n2 = array([1,2,3,4])
y,n = SigAdd(x1,n1,x2,n2)
>> y
array[2,2,2,2,1]
>>n
array[1,2,3,4,5]
Example2:Arrays of equal length
x1 = array([1,1,1])
x2 = array([1,1,1])
n1 = array([1,2,3])
n2 = array([3,4,5])
y,n = SigAdd(x1,n1,x2,n2)
>> y
array[1,1,2,1,1]
>>n
array[1,2,3,4,5]
It works fine if both the arrays are of equal length, but won't work for unequal arrays. I know the problem is i am overriding the y1 (which i initially created with zeros) with value of x1 causing problem. I have used argwhere command in Numpy which is equivalent to Find command of Matlab, but if I use it like Matlab program shown above, it shows error that value can't be assigned to callable function.
Basically in Matlab program, unequal arrays are filled with zero's. Matlab version handles condition even if two signals are of equal length but are at different positions. I want to use Python instead of Matlab but these conversion problems are causing pain.
Some Modifications : (But is not working, Indexing Error : Out of bound coming)
def SigAdd(x1,n1,x2,n2):
n_l = min(min(n1),min(n2))
n_h= max(max(n1),max(n2))
n = arange(n_l,n_h+1)
y1 = zeros([1,len(n)],int)
y2 = y1
y11 = argwhere((n>=min(n1))&(n<=max(n1)))
q = 0
for w in y11:
y1[w]= x1[q]
q = q + 1
y22 = argwhere((n>=min(n2))&(n<=max(n2)))
q = 0
for w in y22:
y2[w]= x2[q]
q = q + 1
y = y1 + y2
return y
You can assign to a slice:
def SigAdd(x1,n1,x2,n2):
n_l = min(n1[0], n2[0])
n_h = max(n1[-1], n2[-1])
n = arange(n_l, n_h+1)
y = zeros(len(n), int)
i = n1[0] - n[0]
y[i:i+len(x1)] = x1
i = n2[0] - n[0]
y[i:i+len(x2)] += x2
return y
Using fancy indexing:
import numpy as np
high = max(n2[-1], n1[-1])
low = min(n2[0], n1[0])
n1_ = n1 - low # use 0-based indexing
n2_ = n2 - low
y = np.zeros(high - low + 1, dtype=x1.dtype)
y[n1_] += x1
y[n2_] += x2
This helped me for a similar problem. The idea is to first make the vectors equal length (with 0 padding the shorter at the end). Disadvantages are the conversion to lists and the memory overhead with those lists. However for quick and dirty tasks it has served well.
def MakeVectorsSameSize(v1,v2):
"""given two vectors zero pad smaller to match length of bigger"""
#make the vectors length of longest 0 pad
l1 = len(v1)
l2 = len(v2)
if l1 < l2:
#put l2-l1 elements into v1
z1 = numpy.ones(l2-l1)*0
v1 = list(v1)
v1.extend(z1)
v1 = numpy.array(v1)
elif l1 > l2:
#put l1-l2 elements into v2
z2 = numpy.ones(l1-l2)*0
v2 = list(v2)
v2.extend(z2)
v2 = numpy.array(vTemp)
return v1,v2

Categories

Resources