How would I be able to improve the speed of this monty hall program, interestingly, the same code written using BBC BASIC for Windows completes the task in half the time of the Python code.
Python Code:
import random
t = 10000001
j = 0
k = 0
for a in range(1, t):
p = int(random.random() * 3) + 1
g = int(random.random() * 3) + 1
if p == g:
r = int(random.random() * 2) + 1
if p == 1:
r += 1
if p == 2 and r == 2:
r = 3
else:
r = p ^ g
s = g
f = g ^ r
if s == p:
j = j + 1
if f == p:
k = k + 1
print(f"After a total of {t - 1} trials,")
print(f"The 'sticker' won {j} times ({int(j/t*100)}%)")
print(f"The 'swapper' won {k} times ({int(k/t*100)}%)")
BBC BASIC for Windows code
T% = 10000000
for A% = 1 to T%
P% = rnd(3)
G% = rnd(3)
if P% = G% then
R% = rnd(2)
if P% = 1 then R% += 1
if P% = 2 and R% = 2 then R% = 3
else
R% = P% eor G%
endif
S% = G%
F% = G% eor R%
if S% = P% then J% = J% + 1
if F% = P% then K% = K% + 1
next
print "After a total of ";T%;" trials,"
print "The 'sticker' won ";J%;" times (";int(J%/T%*100);"%)"
print "The 'swapper' won ";K%;" times (";int(K%/T%*100);"%)"
First thing is changing your import from:
import random
to
from random import random
then using:
p = int(random() * 3) + 1
g = int(random() * 3) + 1
Second thing you can do is change your:
if s == p:
j = j + 1
if f == p:
k = k + 1
Into:
if s == p:
j = j + 1
elif f == p:
k = k + 1
Related
I have a for loop as follows:
import MDAnalysis as mda
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from tqdm import tqdm as tq
import MDAnalysis.analysis.pca as pca
import random
def PCA_projection(pdb,dcd,atomgroup):
u = mda.Universe(pdb,dcd)
PSF_pca = pca.PCA(u, select=atomgroup)
PSF_pca.run(verbose=True)
n_pcs = np.where(PSF_pca.results.cumulated_variance > 0.95)[0][0]
atomgroup = u.select_atoms(atomgroup)
pca_space = PSF_pca.transform(atomgroup, n_components=n_pcs)
PC1_proj = [pca_space[i][0] for i in range(len(pca_space))]
PC2_proj = [pca_space[i][1] for i in range(len(pca_space))]
return PC1_proj, PC2_proj
def Read_bias_potential(bias_potential):
Bias_potential = pd.read_csv(bias_potential)
Bias_potential = Bias_potential['En-User']
Bias_potential = Bias_potential.values.tolist()
W = [math.exp((-1 * i) / (0.001987*300)) for i in Bias_potential]
return W
def Bin(PC1_prj, PC2_prj, frame_num, min_br1, max_br1, min_br2, max_br2, bin_num, W):
#import pdb;pdb.set_trace()
data1 = PC1_prj[0:frame_num]
bins1 = np.linspace(min_br1, max_br1, bin_num)
bins1 = np.round(bins1,2)
digitized1 = np.digitize(data1, bins1)
binc1 = np.arange(min_br1 + (max_br1 - min_br1)/2*bin_num,
max_br1 + (max_br1 - min_br1)/2*bin_num, (max_br1 - min_br1)/bin_num, dtype = float)
binc1 = np.around(binc1,3)
data2 = PC2_prj[0:frame_num]
bins2 = np.linspace(min_br2, max_br2, bin_num)
bins2 = np.round(bins2,2)
digitized2 = np.digitize(data2, bins2)
binc2 = np.arange(min_br2 + (max_br2 - min_br2)/2*bin_num, max_br2 + (max_br2 - min_br2)/2*bin_num, (max_br2 - min_br2)/bin_num, dtype = float)
binc2 = np.around(binc2,3)
w_array = np.zeros((bin_num,bin_num))
for j in range(frame_num):
w_array[digitized1[j]][digitized2[j]] += (W[digitized1[j]] + W[digitized2[j]])
for m in range(bin_num):
for n in range(bin_num):
if w_array[m][n] == 0:
w_array[m][n] = 1e-100
return w_array, binc1, binc2
def gaussian(Sj1,Slj1,Sj2,Slj2,count):
sigma1 = 0.5
sigma2 = 0.5
Kb = 0.001987204
T = 300
h0 = 0.0001
g = 0
C1 = 0
C2 = 0
for i in range((np.where(Slj2 == Sj2)[0][0] - 5),(np.where(Slj2 == Sj2)[0][0] + 6)):
if i < 0:
C2 = i + 1000
elif i > 999:
C2 = i - 1000
else:
C2 = i
for j in range((np.where(Slj1 == Sj1)[0][0] - 5),(np.where(Slj2 == Sj2)[0][0] + 6)):
if j < 0:
C1 = j + 1000
elif j > 999:
C1 = j -1000
else:
C1 = j
g = g + count[C2,C1] * h0 * np.exp( (-(Sj1 - Slj1[C1]) ** 2 / (2 * sigma1 ** 2)) + (-(Sj2 - Slj2[C2]) ** 2 / (2 * sigma2 ** 2)) )
return np.exp(-g / (Kb * T))
def resampling(binc1, binc2, w_array):
# import pdb;pdb.set_trace()
l =1000
F = np.zeros((l,l))
count = np.zeros((l,l))
Wn = w_array
for i in tq(range(10000000)):
SK1 = random.choice(binc1)
SK2 = random.choice(binc2)
SL1 = random.choice(binc1)
SL2 = random.choice(binc2)
while SK1 == SL1:
SL1 = random.choice(binc1)
while SK2 == SL2:
SL2 = random.choice(binc2)
F[np.where(binc2 == SK2)[0][0]][np.where(binc1 == SK1)[0][0]] = gaussian(SK1,binc1,SK2,binc2,count)
F[np.where(binc2 == SK2)[0][0]][np.where(binc1 == SK1)[0][0]] = gaussian(SL1,binc1,SL2,binc2,count)
W_SK = Wn[np.where(binc2 == SK2)[0][0]][np.where(binc1 == SK1)[0][0]] * F[np.where(binc2 == SK2)[0][0]][np.where(binc1 == SK1)[0][0]]
W_SL = Wn[np.where(binc2 == SL2)[0][0]][np.where(binc1 == SL1)[0][0]] * F[np.where(binc2 == SL2)[0][0]][np.where(binc1 == SL1)[0][0]]
if W_SK <= W_SL:
SK1 = SL1
SK2 = SL2
else:
a = random.random()
if W_SL/W_SK >= a:
SK1 = SL1
SK2 = SL2
else:
SK1 = SK1
SK2 = SK2
#print('SK =',SK)
count[np.where(binc2 == SK2)[0][0]][np.where(binc1 == SK1)[0][0]] += 1
return F
where binc1 and binc2 are two np.arrays, gaussian is a gaussian fxn I defined, is there anyway I can speed up this for loop? Now 1000000 steps takes approximately 50 mins. I am thinking about using pytorch but I got no idea on how to do it. Any suggestions would be helpful!
Thanks
I tried to use pytorch, like put all the variables on gpu but it only does worse.
I would like to implement the above mentioned algorithm in Python. Time Complexity of Dijkstra's Algorithm is O(V2), but I would like to implement it using min-priority queue so it drops down to O(V+ElogV).
Heres an example input:
The program should 2 problems, src: 0 dest: 2 and src: 1 dest: 2. 3 vertexes will be provided by the input and there will be 3 edges provided also, all of these are separated by an empty line.
2
3
3
0 2
1 2
2 0
-4 1
6 3
1 0
1 2
0 2
Solution:
5.0 10.2
Heres my current code:
import math
import sys
def build_graph(edges, weights, e):
graph = edges
for i in range(e):
graph[i].append(weights[i])
return graph
def debug():
print(pontparok)
print(csucsok)
print(utszakaszok)
print(hosszak)
def read(n, bemenet):
for i in range(n):
temp = input().split("\t")
bemenet[i] = temp
bemenet[i][0] = int(bemenet[i][0])
bemenet[i][1] = int(bemenet[i][1])
def dijkstra(edges, src, dest, n):
dist = [0] * n
current = src
for i in range(n):
dist[i] = sys.maxsize
dist[src] = 0
explored = [False] * n
q = 0
while not explored[dest] and q < 1000:
q += 1
min = sys.maxsize
minVertex = current
for edge in edges:
if edge[0] == current and not explored[edge[1]]:
if min > dist[edge[1]]:
min = dist[edge[1]]
minVertex = edge[1]
elif edge[1] == current and not explored[edge[0]]:
if min > dist[edge[0]]:
min = dist[edge[0]]
minVertex = edge[0]
current = minVertex
explored[current] = True
for edge in edges:
if edge[0] == current:
if dist[current] + edge[2] < dist[edge[1]]:
dist[edge[1]] = dist[current] + edge[2]
elif edge[1] == current:
if dist[current] + edge[2] < dist[edge[0]]:
dist[edge[0]] = dist[current] + edge[2]
return round(dist[dest], 2)
p = int(input())
n = int(input())
e = int(input())
input()
pontparok = [[0] * 2] * p
csucsok = [[0] * 2] * n
utszakaszok = [[0] * 2] * e
hosszak = [0] * e
read(p, pontparok)
input()
read(n, csucsok)
input()
read(e, utszakaszok)
for i in range(e):
hosszak[i] = math.sqrt(pow((csucsok[utszakaszok[i][0]][0] - csucsok[utszakaszok[i][1]][0]), 2) + pow((csucsok[utszakaszok[i][0]][1] - csucsok[utszakaszok[i][1]][1]), 2))
#debug()
graph = build_graph(utszakaszok, hosszak, e)
#print(hosszak)
for i in range(p):
if i == p - 1:
print(dijkstra(graph, pontparok[i][0], pontparok[i][1], n))
else:
print(dijkstra(graph, pontparok[i][0], pontparok[i][1], n), end="\t")
import heapq
import math
def read(n, bemenet):
for i in range(n):
temp = input().split("\t")
bemenet[i] = temp
bemenet[i][0] = int(bemenet[i][0])
bemenet[i][1] = int(bemenet[i][1])
def dijkstra(graph, starting_vertex, destination_vertex):
distances = {vertex: float('infinity') for vertex in graph}
distances[starting_vertex] = 0
pq = [(0, starting_vertex)]
while len(pq) > 0:
current_distance, current_vertex = heapq.heappop(pq)
for neighbor, weight in graph[current_vertex].items():
distance = current_distance + weight
if distance < distances[neighbor]:
distances[neighbor] = distance
heapq.heappush(pq, (distance, neighbor))
return round(distances[destination_vertex], 2)
def build_graph(edges, weights, e):
graph = edges
for i in range(e):
graph[i].append(weights[i])
return graph
p = int(input())
n = int(input())
e = int(input())
input()
pontparok = [[0] * 2] * p
csucsok = [[0] * 2] * n
utszakaszok = [[0] * 2] * e
hosszak = [0] * e
read(p, pontparok)
input()
read(n, csucsok)
input()
read(e, utszakaszok)
for i in range(e):
hosszak[i] = math.sqrt(pow((csucsok[utszakaszok[i][0]][0] - csucsok[utszakaszok[i][1]][0]), 2) + pow((csucsok[utszakaszok[i][0]][1] - csucsok[utszakaszok[i][1]][1]), 2))
graph2 = build_graph(utszakaszok, hosszak, e)
graph = { }
[graph.setdefault(i, []) for i in range(n)]
for i in range(n):
graph[i] = {}
for edge in graph2:
graph[edge[0]].update({edge[1]: edge[2]})
graph[edge[1]].update({edge[0]: edge[2]})
for i in range(p):
if i == p - 1:
print(dijkstra(graph, pontparok[i][0], pontparok[i][1]))
else:
print(dijkstra(graph, pontparok[i][0], pontparok[i][1]), end="\t")
Hi I am trying to write a trust-region algorithm using the dogleg method with python for a class I have. I have a Newton's Method algorithm and Broyden's Method algorthm that agree with each other but I can't seem to get this Dogleg method to work.
Here is the function I am trying to find the solution to:
def test_function(x):
x1 = float(x[0])
x2 = float(x[1])
r = np.array([[x2**2 - 1],
[np.sin(x1) - x2]])
return r
and here is the jacobian I wrote
def Test_Jacobian(x, size):
e = create_ID_vec(size)
#print(e[0])
epsilon = 10e-8
J = np.zeros([size,size])
#print (J)
for i in range(0, size):
for j in range(0, size):
J[i][j] = ((test_function(x[i]*e[j] + epsilon*e[j])[i] - test_function(x[i]*e[j])[i])/epsilon)
return J
and here is my Trust-Region algorithm:
def Trust_Region(x):
trust_radius = 1
max_trust = 300
eta = rand.uniform(0,.25)
r = test_function(x) # change to correspond with the function you want
J = Test_Jacobian(r, r.size) # change to correspond with function
i = 0
iteration_table = [i]
function_table = [vector_norm(r, r.size)]
while vector_norm(r, r.size) > 10e-10:
print(x, 'at iteration', i, "norm of r is", vector_norm(r, r.size))
p = dogleg(x, r, J, trust_radius)
rho = ratio(x, J, p)
if rho < 0.25:
print('first')
trust_radius = 0.25*vector_norm(p,p.size)
elif rho > 0.75 and vector_norm(p,p.size) == trust_radius:
print('second')
trust_radius = min(2*trust_radius, max_trust)
else:
print('third')
trust_radius = trust_radius
if rho > eta:
print('x changed')
x = x + p
#r = test_function(x)
#J = Test_Jacobian(r, r.size)
else:
print('x did not change')
x = x
r = test_function(x) # change to correspond with the function you want
J = Test_Jacobian(r, r.size) # change to correspond with function
i = i + 1
#print(r)
#print(J)
#print(vector_norm(p,p.size))
print(rho)
#print(trust_radius)
iteration_table.append(i)
function_table.append(vector_norm(r,r.size))
print ('The solution to the non-linear equation is: ', x)
print ('This solution was obtained in ', i, 'iteratations')
plt.figure(figsize=(10,10))
plt.plot(iteration_table, np.log10(function_table))
plt.xlabel('iteration number')
plt.ylabel('function value')
plt.title('Semi-Log Plot for Convergence')
return x, iteration_table, function_table
def dogleg(x, r, J, trust_radius):
tau_k = min(1, vector_norm(J.transpose().dot(r), r.size)**3/(trust_radius*r.transpose().dot(J).dot(J.transpose().dot(J)).dot(J.transpose()).dot(r)))
p_c = -tau_k*(trust_radius/vector_norm(J.transpose().dot(r), r.size))*J.transpose().dot(r)
if vector_norm(p_c, p_c.size) == trust_radius:
print('using p_c')
p_k = p_c
else:
p_j = -np.linalg.inv(J.transpose().dot(J)).dot(J.transpose().dot(r))
print ('using p_j')
tau = tau_finder(x, p_c, p_j, trust_radius, r.size)
p_k = p_c + tau*(p_j-p_c)
return p_k
def ratio(x, J, p):
r = test_function(x)
r_p = test_function(x + p)
print (vector_norm(r, r.size)**2)
print (vector_norm(r_p, r_p.size)**2)
print (vector_norm(r + J.dot(p), r.size)**2)
rho_k =(vector_norm(r, r.size)**2 - vector_norm(r_p, r_p.size)**2)/(vector_norm(r, r.size)**2 - vector_norm(r + J.dot(p), r.size)**2)
return rho_k
def tau_finder(x, p_c, p_j, trust_radius, size):
a = 0
b = 0
c = 0
for i in range(0, size):
a = a + (p_j[i] - p_c[i])**2
b = b + 2*(p_j[i] - p_c[i])*(p_c[i] - x[i])
c = (p_c[i] - x[i])**2
c = c - trust_radius**2
tau_p = (-b + np.sqrt(b**2 - 4*a*c))/(2*a)
tau_m = (-b - np.sqrt(b**2 - 4*a*c))/(2*a)
#print(tau_p)
#print(tau_m)
if tau_p <= 1 and tau_p >=0:
return tau_p
elif tau_m <= 1 and tau_m >=0:
return tau_m
else:
print('error')
return 'error'
def model_function(p):
r = test_function(x)
J = Test_Jacobian(r, r.size)
return 0.5*vector_norm(r + J.dot(p), r.size)**2
The answer should be about [[1.57076525], [1. ]]
but here is the output after about 28-30 iterations:
ZeroDivisionError Traceback (most recent call last)
<ipython-input-359-a414711a1671> in <module>
1 x = create_point(2,1)
----> 2 Trust_Region(x)
<ipython-input-358-7cb77bd44d7b> in Trust_Region(x)
11 print(x, 'at iteration', i, "norm of r is", vector_norm(r, r.size))
12 p = dogleg(x, r, J, trust_radius)
---> 13 rho = ratio(x, J, p)
14
15 if rho < 0.25:
<ipython-input-358-7cb77bd44d7b> in ratio(x, J, p)
71 print (vector_norm(r_p, r_p.size)**2)
72 print (vector_norm(r + J.dot(p), r.size)**2)
---> 73 rho_k =(vector_norm(r, r.size)**2 - vector_norm(r_p, r_p.size)**2)/(vector_norm(r, r.size)**2 - vector_norm(r + J.dot(p), r.size)**2)
74 return rho_k
75
ZeroDivisionError: float division by zero
So I have an application in Python that calculates the variable number in the "PV = nRT" chemical equation. The code is like this:
r = 0.082
# Variables
p = float(input('Pressure = '))
p_unit = input('Unit = ')
print('_____________________')
v = float(input('Volume = '))
v_unit = input('Unit = ')
print('_____________________')
n = float(input('Moles = '))
print('_____________________')
t = float(input('Temperature = '))
t_unit = input('Unit = ')
# Unit Conversion
if p_unit == 'bar':
p = p * 0.987
if v_unit == 'cm3':
v = v / 1000
if v_unit == 'm3':
v = v * 1000
if t_unit == 'c':
t = t + 273
if t_unit == 'f':
t = ((t - 32) * (5 / 9)) + 273
# Solve Equation
def calc():
if p == 000:
return (n * r * t) / v
if v == 000:
return (n * r * t) / p
if n == 000:
return (p * v) / (r * t)
if t == 000:
return (p * v) / (n * r)
and then at the end I run the function to get the result. But the problem is I want to convert the result to a Scientific Number (e.g. 0.005 = 5 x 10^-3). I tried the solution below:
def conv_to_sci(num):
i = 0
if num > 10:
while num > 10:
num / 10
i = i - 1
if num < 10:
while num < 10:
num * 10
i = i + 1
return num + "x 10^" + i
but it didn't work. Any questions?
I'd just use numpy to get scientific notation
import numpy as np
num = 0.005
num_sc = np.format_float_scientific(num)
>>> num_sc
'5.e-03'
Use str.format
"{:.0e}".format(0.005)
This will print:
'5e-03'
Or,
def conv_to_sci(num):
i = 0
while int(num) != num:
num *= 10
i += 1
return "{0} x 10^{1}".format(int(num), i)
conv_to_sci(0.005)
Will give: '5 x 10^3'
The function does what I want it to, but when it's done it just sits there rather than continuing from where I called it and I can't figure out why. The code is:
x = 9
y = 9
n = 10
ty = 1
tx = 1
while ty <= y:
while tx <= x:
vars()["p" + str(ty) + str(tx)] = 0
tx += 1
ty += 1
tx = 1
tn = 1
while tn <= n:
vars()["m" + str(tn)] = tn
tn += 1
t = x * y
tm = n
def recursion(z):
global tm
if z < n:
for x in range(n):
recursion(z + 1)
else:
if tm > 0:
tv = "m" + str(tm)
otm = eval(tv)
while eval(tv) < t - n + tm:
vars()[tv] = eval(tv) + 1
print(tv + " = " + str(eval(tv)))
vars()[tv] = otm + 1
print(tv + " = " + str(eval(tv)))
if tm > 1:
vars()["m" + str(tm - 1)] = eval("m" + str(tm - 1)) + 1
print(str("m" + str(tm - 1) + " = " + str(eval("m" + str(tm -1)))))
tm -= 1
recursion(1)
print("done")
I've put the return in where I would expect it to end but as far as I know it shouldn't actually need it.
Can anyone see what I've done to cause it to get stuck?
Thanks
Note for people not going through the change history: This is based on the comments on other answers. UPDATE: Better version.
import itertools
def permutations(on, total):
all_indices = range(total)
for indices in itertools.combinations(all_indices, on):
board = ['0'] * total
for index in indices:
board[index] = '1'
yield ''.join(board)
If anyone is interested in what the original code did, I rearranged the conditionals to prune the tree of function calls:
x = 9
y = 9
n = 10
ty = 1
tx = 1
while ty <= y:
while tx <= x:
vars()["p" + str(ty) + str(tx)] = 0
tx += 1
ty += 1
tx = 1
tn = 1
while tn <= n:
vars()["m" + str(tn)] = tn
tn += 1
t = x * y
tm = n
def recursion(z):
global tm
if tm > 0:
if z < n:
for x in range(n):
recursion(z + 1)
else:
tv = "m" + str(tm)
otm = eval(tv)
while eval(tv) < t - n + tm:
vars()[tv] = eval(tv) + 1
print(tv + " = " + str(eval(tv)))
vars()[tv] = otm + 1
print(tv + " = " + str(eval(tv)))
if tm > 1:
vars()["m" + str(tm - 1)] = eval("m" + str(tm - 1)) + 1
print(str("m" + str(tm - 1) + " = " + str(eval("m" + str(tm -1)))))
tm -= 1
recursion(1)
print("done")
This could be made much clearer through the use of lists and range objects, but that takes effort.
I wasn't able to work out what was happening (turns out if I left it for a few minutes it would actually finish though), instead, I realised that I didn't need to use recursion to achieve what I wanted (and I also realised the function didn't actually do what I want to do).
For anyone interested, I simplified and rewrote it to be a few while loops instead:
x = 9
y = 9
t = x * y
n = 10
tt = 1
while tt <= t:
vars()["p" + str(tt)] = 0
tt += 1
tn = 1
while tn <= n:
vars()["m" + str(tn)] = tn
vars()["p" + str(tn)] = 1
tn += 1
def cl():
w = ""
tt = 1
while tt <= t:
w = w + str(eval("p" + str(tt)))
tt += 1
p.append(w)
tm = n
tv = "m" + str(tm)
p = []
while m1 < t - n + tm - 1:
cl()
while tm == n and eval(tv) < t - n + tm:
vars()["p" + str(eval(tv))] = 0
vars()[tv] = eval(tv) + 1
vars()["p" + str(eval(tv))] = 1
cl()
tm -= 1
tv = "m" + str(tm)
while tm < n and tm > 0:
if eval(tv) < t - n + tm:
vars()["p" + str(eval(tv))] = 0
vars()[tv] = eval(tv) + 1
vars()["p" + str(eval(tv))] = 1
while tm < n:
tm += 1
ptv = tv
tv = "m" + str(tm)
vars()["p" + str(eval(tv))] = 0
vars()[tv] = eval(ptv) + 1
vars()["p" + str(eval(tv))] = 1
else:
tm -= 1
tv = "m" + str(tm)