Having problems with an index error (Python) - python

So I am having some trouble with my code.
Essentially, I am creating an initial array (x0x1) of random coordinates (this is successful). Then, I want to generate a candidate coordinate vector (z) from 3 random choice coordinate vectors from my original coordinate array. I then compare f(z) with every pair of coordinates f(x0x1[i]) in my original array. If f(z) is lower, then I take it to a new array of coordinates. The cycle repeats until I find the value of z that minimizes my function.
The error I get is : index 1 is out of bounds for axis 0 with size 1, and it seems to be happening in my calculateFunction method. Not sure why.
Here is the code I am working with:
import numpy as np
import numpy.random
def calculateFunctionValue(x):
return (x[0]-1)**2+5(x[1]-x[0]**2)**2
def x0x1Array(N, F, K):
x0x1 = np.zeros((N-1, 1), dtype=float)
x0 = np.zeros((N-1, 1), dtype=float)
x1 = np.zeros((N-1, 1), dtype=float)
for i in range(0, len(x0)):
for j in range(0, len(x1)):
x0[i] = np.random.uniform(-2,2)
x1[j] = np.random.uniform(-2,2)
x0x1 = np.array((x0,x1)).T
generateCandidateVector(x0x1, N, F, K)
def generateCandidateVector(newPopulationArray, N, F, K):
x0 = np.zeros((1,2))
x1 = np.zeros((1,2))
x2 = np.zeros((1,2))
populationOneArray = np.zeros((N-1, 1))
generation = 0
while generation <= K:
generation = generation + 1
for i in range(0, N-1):
x0 = np.random.choice(len(newPopulationArray), 1)
x1 = np.random.choice(len(newPopulationArray), 1)
x2 = np.random.choice(len(newPopulationArray), 1)
vectorZ = x0 + F*(x1-x2)
if(calculateFunctionValue(vectorZ) < calculateFunctionValue(newPopulationArray[i])):
vectorZ = newPopulationArray[i]
print(vectorZ)
return generateCandidateVector(vectorZ)
elif(calculateFunctionValue(vectorZ) > calculateFunctionValue(newPopulationArray[i])):
vectorZ = populationOneArray[i]
def main():
K = 50
F = 0.8
N=50
x0x1Array(N, F, K)
main()
The error trace is the following:
runfile('C:/Users/SPNMo/Documents/untitled5.py', wdir='C:/Users/SPNMo/Documents')
[0]
C:\Users\SPNMo\Documents\untitled5.py:17: SyntaxWarning: 'int' object is not callable; perhaps you missed a comma?
return (x[0]-1)**2+5(x[1]-x[0]**2)**2
Traceback (most recent call last):
File "C:\Users\SPNMo\Documents\untitled5.py", line 74, in <module>
main()
File "C:\Users\SPNMo\Documents\untitled5.py", line 71, in main
x0x1Array(N, F, K)
File "C:\Users\SPNMo\Documents\untitled5.py", line 35, in x0x1Array
generateCandidateVector(x0x1, N, F, K)
File "C:\Users\SPNMo\Documents\untitled5.py", line 55, in generateCandidateVector
if(calculateFunctionValue(vectorZ) < calculateFunctionValue(newPopulationArray[i])):
File "C:\Users\SPNMo\Documents\untitled5.py", line 17, in calculateFunctionValue
return (x[0]-1)**2+5(x[1]-x[0]**2)**2
IndexError: index 1 is out of bounds for axis 0 with size 1

These 2 lines in x0x1Array function do not generate arrays of the same shape.
x0x1 = np.zeros((N-1, 1), dtype=float) // shape is (49, 1)
x0x1 = np.array((x0,x1)).T // shape is (1, 49, 2)
You should revisit the second line to create that array in a proper way.
UPDATE: getting 3 pairs from the list:
x0_ind, x1_ind, x2_ind = np.random.choice(lennewPopulationArray), 3)
x0 = newPopulationArray[x0_ind]
x1 = newPopulationArray[x1_ind]
x2 = newPopulationArray[x2_ind]
Also, in the calculateFunctionValue function add multiplication sign after the 5 so python knows to multiply

Related

I'm having trouble getting my code to work, my goal is to make a loglog graph but I'm unable to get any sort of response from my code

Any thoughts on why this doesn't return me a loglog plot? My goal is to loglog.plot the fractional error between the numerically calculated and analytically driven result over a set of panels. I'm quite sure the simpsonsrule part is fine and I've screwed up afterward around plotting and returning variables.
import matplotlib.pyplot as plt
import numpy
%matplotlib inline
def bounds():
a = 0
b = 2
return a,b
def f(x):
return x**2*numpy.cos(2*x)
def simpsonsRule(n):
n = [4, 8, 16, 32, 64, 128, 256, 512, 1024]
a,b = bounds()
sum = float()
sum += f(a)
sum += f(b)
width= (b-a)/(2*n)
oddSum = float()
evenSum = float()
for i in range(1,n):
oddSum += f(2*width*i+a)
sum += oddSum * 2
for i in range(1,n+1):
evenSum += f(width*(-1+2*i)+a)
sum += evenSum * 4
return sum * width/3
def integrate_analytic(a, b):
return ((2*b**2-1)*numpy.sin(2*b)+2*b*numpy.cos(2*b))/4 - (((2*a**2-1)*numpy.sin(2*a)+2*a*numpy.cos(2*a))/4)
def error(n, a, b):
return (simpsonsRule(n)-integrate_analytic(a, b))/integrate_analytic(a, b)
plt.loglog(error1,error1)
plt.figure(figsize=(8, 4))
error1 = error(n, a=0, b=2)
plt.show()
print(error1)

Array won't update with new values in while-loop

I am having a problem updating my x0x1 array with the new values in my while loop. When I print my array out to check each generation iteration, its printing out the same values each time (despite me getting different z vector values). Not sure why.
I am getting the z-values for each iteration in my for loop, but for some reason, my newly generated x0x1 arrays each generation of the while loop are not being updated.
import numpy as np
import numpy.random
def calculateFunctionValueMatrix(x0x1, N):
functionValueArray = np.zeros((N-1, 1))
for i in range(0, N-1):
functionValueArray[i] = calculateFunctionValue(x0x1[i])
return functionValueArray
def calculateFunctionValue(x):
function = (x[0]-1)**2 + 5*((x[1]-x[0]**2)**2)
return function
def x0x1Array(N):
x0x1 = np.random.uniform(-2, 2, size = (N-1,2))
generateCandidateVector(x0x1)
def generateCandidateVector(x0x1):
print(x0x1)
K = 10
F= 0.8
N = 10
generation = 1
while generation <= K:
for i in range(0, N-1):
x0_ind, x1_ind, x2_ind = np.random.choice(len(x0x1), 3)
x0 = x0x1[x0_ind]
x1 = x0x1[x1_ind]
x2 = x0x1[x2_ind]
vectorZ = x0 + F*(x1-x2)
print("this is vector", vectorZ)
if(calculateFunctionValue(vectorZ) < calculateFunctionValue(x0x1[i])):
vectorZ = x0x1[i]
elif(calculateFunctionValue(vectorZ) > calculateFunctionValue(x0x1[i])):
x0x1[i] = x0x1[i]
print(x0x1)
if(np.std(calculateFunctionValueMatrix(x0x1, N)) < 0.01):
print("Optimal Solution Found")
generation = generation + 1
def main():
N=50
x0x1Array(N)
main()

local variable referenced before assignment | matplotlib

I want to visualize the central limit theorem for an exemplary PDF. The following code works as I wish:
import sympy as sp
import numpy as np
import matplotlib.pyplot as plt
x, y = sp.symbols('x y')
dens = sp.exp(-x) #PDF
def sum(dens,n):
"""
Parameters
----------
dens : probabilty density function
n : amount of iteration
Returns
-------
pdf after n iterations
"""
dens2 = dens.subs(x, y-x) #PDF for one further summed random variable
i=1
while i<=n:
int = sp.integrate(dens*dens2, (x,0,y))
int = int.subs(y,x)
dens = int
i += 1
return int
#plot for n th iteration
n1 = 1
n2 = 20
n3=50
n4 = 100
X1 = np.linspace(0,200,num=1000)
Y1 = sp.lambdify(x,sum(dens,n1),'numpy')
plt.plot(X1, Y1(X1),label="n=1")
X2 = np.linspace(0,200,num=1000)
Y2 = sp.lambdify(x,sum(dens,n2),'numpy')
plt.plot(X2, Y2(X2),label="n=20")
X3 = np.linspace(0,200,num=1000)
Y3 = sp.lambdify(x,sum(dens,n3),'numpy')
plt.plot(X3, Y3(X3),label="n=50")
X4 = np.linspace(0,200,num=1000)
Y4 = sp.lambdify(x,sum(dens,n4),'numpy')
plt.plot(X4, Y4(X4),label="n=100")
plt.legend()
plt.show()
Now I'd like to do the plot for all the n possibilities (later I want to try to animate it, but at first I need to understand how to do this loop). Thus I want to do the plot using a loop instead of creating the plots separately as above. But this gives me the error
Traceback (most recent call last):
File "C:\Users\user\Desktop\ZGS.py", line 71, in
Y = sp.lambdify(x,sum(dens,k),'numpy')
File "C:\Users\user\Desktop\ZGS.py", line 32, in sum
return int
UnboundLocalError: local variable 'int' referenced before assignment
I tried some things such as global int but this creates problems within sympy. Why can I use different variables for n when plotting separately but get this error when assigning n using a loop?
n=100
for k in range(n):
X = np.linspace(0,200,num=1000)
Y = sp.lambdify(x,sum(dens,k),'numpy')
plt.plot(X, Y(X))
plt.show()
How can this problem be solved?
for k in range(n):
...
Y = sp.lambdify(x,sum(dens,k),'numpy')
...
On the first iteration k is zero.
>>> for k in range(3):
... print(k)
...
0
1
2
When dens is called with k == 0 - while i<=n is False and nothing in that while loop is processed. When return int is processed int does not exist.
range takes an optional start argument which would alleviate your error:
>>> for k in range(1,3+1):
... print(k)
...
1
2
3
>>>

Write a 2-d array in a for-loop

I want to create 2 arrays from the following for-loop:
with open('y.txt', 'w') as f:
for j in range (1, 3):
xN = 0.5 + 0.5*random.uniform(0, 1)
r = 3.8 + 0.15*random.uniform(0, 1)
for i in range (1, 313+1):
xNew = logistic_map(xN, r)
xN = xNew
f.write("%f" % xNew)
This is of course creating a text file of 313*2=626 rows.
What I want to do is to be able to automatically create j arrays:
Q(j = 1) = the first 313 points
Q(...)
Q(j = N) = the last 313 points.
Also, how do I save this to a text file, with 313 rows and j columns? The text file I have now just saves a file with 626 rows.
To create a 2D array, you can modify your code like so:
import numpy as np
Q = []
for j in range (1, 3):
xN = 0.5 + 0.5*random.uniform(0, 1)
r = 3.8 + 0.15*random.uniform(0, 1)
temp = []
for i in range (1, 313+1):
xNew = logistic_map(xN, r)
xN = xNew
temp.append(xNew)
Q.append(xNew) # Saves each row of 313 points as a separate sub-array
Q = np.transpose(np.array(Q)) # Convert this to an array and take the transpose of it
Then you can use np.savetxt to save this as a text file.
However, if you don't actually need the sub-arrays to contain 313 points, you can add the points in the transpose order directly, thereby skipping the later np.transpose() step. Like this:
import numpy as np
Q = [[0 for j in range(2)] for i in range (313)] # Creates an array of zeros with 2 columns and 313 rows
for j in range (1, 3):
xN = 0.5 + 0.5*random.uniform(0, 1)
r = 3.8 + 0.15*random.uniform(0, 1)
for i in range (1, 313+1):
xNew = logistic_map(xN, r)
xN = xNew
Q[i][j] = xNew
Q = np.array(Q) # Convert this to an array and take the transpose of it

TypeError: only length-1 arrays can be converted to Python scalars

I am really new to python, and am trying to use the Trapezoidal rule to approximate the intergral of 4 functions and then find the error, of this and plot, the error vs the number for strips used, N.
import numpy as np
import pylab as plt
#creating functions of the functions
def f1(x):
'''this is a function to return f1 = e^(-4x)cos(8*pi*x)'''
return (np.exp(-4*x))*np.cos(8*np.pi*x)
def f2(x):
'''this is a function to return f2 = (cos(2*pi*x))^2'''
return (np.cos(2*np.pi*x))**2
def f3(x):
'''this is a function to return f3 = sin(2*pi*x)'''
return np.sin(2*np.pi*x)
def f4(x):
'''this is a function to return f4 = e^(-((x-5)^2)/0.04)'''
a = x-.5
b = a*a
c = -b
return np.exp(c/.04)
x = np.arange (0.0,1.0,0.01)
#plt.figure(1)
#plt.plot(x, f1(x), 'g-', x, f2(x), 'r--', x, f3(x), 'k--', x, f4(x), 'b--')
#plt.show()
# N is the number of strips
a=0.0
b= 1
def TrapRule(f,a,b, N):
'''this a function that appoximates the intregrals of a funtion between
0 and 1, using the Trapezoidal rule and returns the appoximate value.'''
#for N in range (3,15):
H=(b-a)/(N)
x=H
c=0.0
for i in range (1, N-1):
c += 2*f(x)
x += H
print (H/2)*(f(a)+f(b)+ c)
return (H/2)*(f(a)+f(b)+ c)
z=np.pi
a= 16*z**2
b= 4+a
c= 1/b
d= np.exp(4)
e=1/d
f= 1-e
F1 = c*f
F2= 0.5
F3 = 0
F4 = 0.199918*((np.pi)**0.5)
#print F1
#TrapRule(f1, .0, 1. , 20000)
#print F2
#TrapRule(f2, .0, 1. , 20000)
#print F3
#TrapRule(f3, .0, 1. , 20000)
#print F4
#TrapRule(f4, .0, 1. , 20000)
def error(F, f, N): #works
'''this function caluclate the error from using the TrapRule (compared with real answer)'''
A = F - TrapRule(f, .0, 1. , N)
B = A/F
Er = B*100
#print Er
return Er
N1 = np.arange (10, 100, 1)
plt.plot(N1, error(F1, f1, N1), 'g')
plt.show()
When I run the program in get the error,
Traceback (most recent call last):
File "C:\Users\mem208\Portable Python 2.7.6.1\ComAss.py", line 97, in <module>
plt.plot(N1, error(F1, f1, N1), 'g')
File "C:\Users\mem208\Portable Python 2.7.6.1\ComAss.py", line 88, in error
A = F - TrapRule(f, .0, 1. , N)
File "C:\Users\mem208\Portable Python 2.7.6.1\ComAss.py", line 53, in TrapRule
for i in range (1, N-1):
TypeError: only length-1 arrays can be converted to Python scalars
Thanks :D
You're passing N1 which is an array into error under the name N, and then passing it to TrapRule, but it's still an array.
Therefore the line:
for i in range (1, N-1)
is effectively
for i in range(1, np.arange (10, 100, 1)-1)
which doesn't make any sense.
A guess at what you might be trying to do is:
N1 = np.arange (10, 100, 1)
errors = [error(F1, f1, N) for N in N1] # make a vector of errors, one error value each N1 value
plt.plot(N1, errors, 'g')
plt.show()

Categories