The loop in Python does not update the array, why? [closed] - python

Closed. This question needs debugging details. It is not currently accepting answers.
Edit the question to include desired behavior, a specific problem or error, and the shortest code necessary to reproduce the problem. This will help others answer the question.
Closed 4 years ago.
Improve this question
The following code does not update the array V. The array is first created before the loop and is supposed to be changed within the loop, but it does not. Could someone explain why?
PS: I'm a beginner in Python.
import numpy as np
def priceCall(S0=4,u=2,d=0.5,T=1,r=0.25,K=5):
n = range(T+1);
Tmn = np.subtract(T,n);
S = S0*np.power(u,Tmn)*np.power(d,n);
p = (1+r-d)/(u-d);
V = np.maximum(np.subtract(S,K),[0]*len(S));
for j in range(1,T+1):
for i in range(1,len(V)-j):
V[i] = 1/(1+r)*(p*V[i]+(1-p)*V[i+1]);
print(V)
return V

Because your second forloop is not even executing. Let's assume you want to call priceCall with no parameters, in that case it means that the first range will be range(1, 2) which essentially means [1], and j=1 for the first iteration of the loop, meaning that the second range will be range(1, 1) which essentially means [] because the end index in a range will always be excluded.
Here is how I tested it:
import numpy as np
def priceCall(S0=4,u=2,d=0.5,T=1,r=0.25,K=5):
n = range(T+1);
Tmn = np.subtract(T,n);
S = S0*np.power(u,Tmn)*np.power(d,n);
p = (1+r-d)/(u-d);
V = np.maximum(np.subtract(S,K),[0]*len(S));
print("INITIAL")
print(V)
print("R1")
print(range(1, T+1))
for j in range(1, T+1):
print("R2")
print(range(1, len(V)-j))
for i in range(1, len(V)-j):
new_val = 1/(1+r)*(p*V[i]+(1-p)*V[i+1])
print(new_val)
V[i] = new_val
print("AFTER")
print(V)
return V
priceCall()
And here is the output:
(py3) > $ python sover.py
INITIAL
[3. 0.]
R1
range(1, 2)
R2
range(1, 1)
AFTER
[3. 0.]
Demonstration that the vector does indeed change:
import numpy as np
def priceCall(S0=4,u=2,d=0.5,T=1,r=0.25,K=5):
n = range(T+1);
Tmn = np.subtract(T,n);
S = S0*np.power(u,Tmn)*np.power(d,n);
V = np.maximum(np.subtract(S,K),[0]*len(S));
print("INITIAL")
print(V)
V[0] = 9999
print("AFTER")
print(V)
priceCall()
with the output
(py3) > $ python sover.py
INITIAL
[3. 0.]
AFTER
[9999. 0.]

You have an off by one error in your nested for loop. len(V) is equal to 1 when you enter the first loop.

Related

Need explaination of a python code - newbiew to Python

I am quite new to Python and there is one assignment that I could not understand even though I have already reviewed similar solutions:
Assignment: Find K numbers in a list that their sum is equal to M ( input K and M). Print these numbers
For example:
Array= [3,2,4,8,5]
Input:K=2, M=5
Output: [3,2]
Input: K=3, M=13
Output: [3,2,8]
Here is a solution of this modified assignment: print all subsequences that their sum is equal to M.
def subsetSumToK(arr,k):
if len(arr)==0:
if k == 0:
return [[]]
else:
return []
output=[]
if arr[0]<=k:
temp2=subsetSumToK(arr[1:],k-arr[0]) #Including the current element
if len(temp2)>0:
for i in range(len(temp2)):
temp2[i].insert(0,arr[0])
output.append(temp2[i])
temp1=subsetSumToK(arr[1:],k) #Excluding the current element
if len(temp1)>0:
for i in range(len(temp1)):
output.append(temp1[i])
return output
arr=[int(i) for i in input().split()]
k=int(input())
sub=subsetSumToK(arr,k)
for i in sub:
for j in range(len(i)):
if j==len(i)-1:
print(i[j])
else:
print(i[j],end=" ")
Ex: Input:K=2, M=5
Output: [3,2], [5]
The problem here is, even though I have already had seen solutions, I tried to do manually by doing iterations by hand, but I could not understand the algorithm, maybe I read it wrong. I really need your help.
Especially starting from these lines:
if arr[0]<=k:
temp2=subsetSumToK(arr[1:],k-arr[0]) #Including the current element
if len(temp2)>0:
for i in range(len(temp2)):
temp2[i].insert(0,arr[0])
output.append(temp2[i])
Here were my plain explainations:
arr=[3,2,4,8,5], K=5
#1st iteration:
if array[0] #(=3)<=5 :True
temp2=subsetSumToK(arr[1:],k-arr[0]) # temp2= ( [2,4,8,5], 2)
if len(temp2)>0 #(2>0: True):
for i in range (len(temp2)): # i=0
temp2[i].insert(0,arr[0]) # temp2[0]=[2,4,8,5]
# => temp2= ( [3,2,4,8,5],2)
output.append(temp2[i]) # output= ([3,2,4,8,5])
#2nd iteration:
for i in range (len(temp2)): # i=1
temp2[i].insert(0,arr[0]) # temp2[1]= (2)
#=> temp2= ( [3,2,4,8,5], 2, 2) ????
output.append(temp2[i]) # output= ( [3,2,4,8,5], 2)?????
# And then I realised that the length of temp2 goes to infinitive.....
# Far beyond

looping gives me the same set of matrices

Hello so I am trying to run this code where i want X_Matrices dictionary to contain all the X_matrix_i matricies. However, all i am getting that X_Matrices end up being the final X_matrix_i of the final loop. I am not quite sure where i am stuck. Any information would be appreciated! thanks.
n = 5
T = 3
p = 5
X_matrix_i = np.zeros((T,p))
X_Matrices = {}
for i in range(n):
X_Matrices["X" + str(i)] = np.zeros((T,p))
for i in range(n):
for t in range(T):
#initial randomness for loop t
ϵ = np.random.normal(0,1,1)
η = np.random.normal(0,1,1)
Covu = np.zeros((p,p))
#Generating X and e of X
for j in range(len(Covu[0])): #covariance matrix for vector x
for l in range(len(Covu)):
Covu[l,j] = 0.7**(np.abs(l-j))
Zerop = np.zeros(p) # mean vector for vector x
x = np.random.multivariate_normal(Zerop,Covu)
X_matrix_i[t] = x
X_Matrices["X" + str(i)] = X_matrix_i
There are two problems here. First one is the conflicting "i" variables in for loops.
One of them should be changed! I replaced the first for loop i variable with k.
for k in range(n):
for t in range(T):
#initial randomness for loop t
The second problem is that by doing
X_Matrices["X" + str(i)] = X_matrix_i
(last line) you are referencing X_Matrices["X" + str(i)] to X_matrix_i! The issue with mutable objects in Python happens! Instead of doing so, you should use shallow copy to assign values to X_Matrices["X" + str(i)]. So a copy of X_matrix_i will be assigned, not X_matrix_i itself.
I replaced the last line with
X_Matrices["X" + str(k)][:] = X_matrix_i
and the problem solved.
[:] acts as shallow copy here.
I think your problem is caused by the redeclaration of i in the second for loop
for j in range(len(Covu[0])): #covariance matrix for vector x
for i in range(len(Covu)):
Covu[i,j] = 0.7**(np.abs(i-j))
Try to rename the i to something else and it should solve your problem.

How to stop a nested loop iterating over a list in Python

I'm trying to build a list of "populations" based on two ranges and one list. The nested loop I've created doesn't stop, even though I specify where it should break (I've checked the length of the list used in the loop which is equal to 303). So the output is infinite: after it prints the population value for v=2, J=100 (maximum needed), it goes back to displaying v=0,J=0 value for population. How can i fix that? Here is the code:
from scipy.optimize import minimize_scalar
import math
import itertools
we=268.64
wexe=0.814
weye=-0.0017
Be=0.0568325
ae=0.0001969
ge=-0.00000047
De=1.02E-8
kb=1.38065E-23
energy_groundJ=[]
def energyJ (v,J):
E = we*(v+0.5) + wexe*(v+0.5)**2 + weye*(v+0.5)**3 + Be*(J*(J+1)) - ae*(v+0.5)*(J*(J+1)) - De*(J*(J+1)) + ge*(J*(J+1))*(v+0.5)**2
E_J=E*1.986E-23
return E_J
for v in [0,1,2]:
for J in range(0,101):
E_J=energyJ(v,J)
energy_groundJ.append(E_J)
Population=[]
def population_ground():
P=(2*J+1)*math.exp(-i/(kb*295))
return P
for i in energy_groundJ:
for v in [0,1,2]:
for J in range(0,101):
if i==303:
break
P=population_ground()
Population.append(P)
print("population at v = "+str(v)+" and J ="+str(J)+" = "+str(P))
break only breaks you out of one "for" loop (the closest one/top of the stack), not multiple.
Since your other loops don't do anything before the check, you could do this:
for i in energy_groundJ:
if i==303:
break
for v in [0,1,2]:
for J in range(0,101):
P=population_ground()
Population.append(P)
print("population at v = "+str(v)+" and J ="+str(J)+" = "+str(P))

Synthetically organizing several statements connected by "or"

I want to make a plot where I show several pulses at different times.
I have the list l with the time of each pulse, for example
l=[1.,2.,24.]
and I have the duration d of the pulse, for example d=0.2.
I can do the plot in the following way:
import numpy as np
import matplotlib.pyplot as plt
t=np.linspace(0.,30,1000)
l=[1.,2.,24.]
d=0.2
def pulse(t):
if t<l[0]:
L = 0.
elif l[0]<=t<l[0]+d or l[1]<=t<l[1]+d or l[2]<=t<l[2]+d:
L = 1
else:
L=0.
return L
plt.figure(1)
P=map(pulse,t)
plt.plot(t,P)
plt.show()
Of course, if len(l) becomes very large I cannot use this procedure, that is, I cannot write by hand a very long chain of or. How can I write the algorithm in a more synthetic way?
You can test several different conditions by using a for loop. For example:
def pulse(t):
L = 0
for i in range(len(l)):
if l[i] <= t < l[i] + d:
L += 1
return L
I think you can use numpy indexong for efficiency and of course write a for loop for unknown number of if statements.
p = np.zeros(1000)
for i in l:
p[(0<=t-i) & (t-i<d)] = 1

Binary string in Python issues

For some reason I'm having a heck of a time figuring out how to do this in Python.
I am trying to represent a binary string in a string variable, and all I want it to have is
0010111010
However, no matter how I try to format it as a string, Python always chops off the leading zeroes, which is giving me a headache in trying to parse it out.
I'd hoped this question would have helped, but it doesn't really...
Is there a way to force Python to stop auto-converting my string to an integer?
I have tried the following:
val = ""
if (random.random() > 0.50):
val = val + "1"
else
val = val + "0"
and
val = ""
if (random.random() > 0.50):
val = val + "%d" % (1)
else:
val = val + "%d" % (0)
I had stuck it into an array previously, but ran into issues inserting that array into another array, so I figured it would just be easier to parse it as a string.
Any thoughts on how to get my leading zeroes back? The string is supposed to be a fixed length of 10 bits if that helps.
Edit:
The code:
def create_string(x):
for i in xrange(10): # 10 random populations
for j in xrange(int(x)): # population size
v = ''.join(choice(('0','1')) for _ in range(10))
arr[i][j] = v
return arr
a = create_string(5)
print a
Hopefully the output I'm seeing will show you why I'm having issues:
[[ 10000100 1100000001 101010110 111011 11010111]
[1001111000 1011011100 1110110111 111011001 10101000]
[ 110010001 1011010111 1100111000 1011100011 1000100001]
[ 10011010 1000011001 1111111010 11100110 110010101]
[1101010000 1010110101 110011000 1100001001 1010100011]
[ 10001010 1100000001 1110010000 10110000 11011010]
[ 111011 1000111010 1100101 1101110001 110110000]
[ 110100100 1100000000 1010101001 11010000 1000011011]
[1110101110 1100010101 1110001110 10011111 101101100]
[ 11100010 1111001010 100011101 1101010 1110001011]]
The issue here isn't only with printing, I also need to be able to manipulate them on a per-element basis. So if I go to play with the first element, then it returns a 1, not a 0 (on the first element).
If I understood you right, you could do it this way:
a = 0b0010111010
'{:010b}'.format(a)
#The output is: '0010111010'
Python 2.7
It uses string format method.
This is the answer if you want to represent the binary string with leading zeros.
If you are just trying to generate a random string with a binary you could do it this way:
from random import choice
''.join(choice(('0','1')) for _ in range(10))
Update
Unswering your update.
I made a code which has a different output if compared to yours:
from random import choice
from pprint import pprint
arr = []
def create_string(x):
for i in xrange(10): # 10 random populations
arr.append([])
for j in xrange(x): # population size
v = ''.join(choice(('0','1')) for _ in range(10))
arr[-1].append(v)
return arr
a = create_string(5)
pprint(a)
The output is:
[['1011010000', '1001000010', '0110101100', '0101110111', '1101001001'],
['0010000011', '1010011101', '1000110001', '0111101011', '1100001111'],
['0011110011', '0010101101', '0000000100', '1000010010', '1101001000'],
['1110101111', '1011111001', '0101100110', '0100100111', '1010010011'],
['0100010100', '0001110110', '1110111110', '0111110000', '0000001010'],
['1011001011', '0011101111', '1100110011', '1100011001', '1010100011'],
['0110011011', '0001001001', '1111010101', '1110010010', '0100011000'],
['1010011000', '0010111110', '0011101100', '1111011010', '1011101110'],
['1110110011', '1110111100', '0011000101', '1100000000', '0100010001'],
['0100001110', '1011000111', '0101110100', '0011100111', '1110110010']]
Is this what you are looking for?
How about the following:
In [30]: ''.join('1' if random.random() > 0.50 else '0' for i in xrange(10))
Out[30]: '0000110111'
This gives a ten-character binary string; there's no chopping off of leading zeroes.
If you don't need to vary digit probability (the 0.50 above), a slightly more concise version is:
In [39]: ''.join(random.choice('01') for i in xrange(10))
Out[39]: '0001101001'

Categories