Python - Dijkstra's algorithm in O(V+ElogV) time complexity - python

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")

Related

how do i leave the list with only 1 person

The problem:
https://www.beecrowd.com.br/judge/problems/view/1032
I can't get the numbers out of the people list, this method I did gives the error "pop index out of range".
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# PRIME LIST
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
from audioop import reverse
numerosPrimos = 3501
primos = []
for i in range(2, numerosPrimos + 1):
for j in range(2, int(i ** 0.5) + 1):
if i % j == 0:
break
else:
primos.append(i)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# PEOPLE LIST
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
numeroPessoas = int(input())
pessoas = []
for l in range(1, numeroPessoas + 1):
pessoas.append(l)
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# REMOVING PEOPLE
# =-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
# pessoasEliminada = pessoas
p = primos[0]
pessoas.sort(reverse=True)
mult = 1
while len(pessoas) >= 1 and p <= 3501:
pessoas.pop(len(pessoas) - p)
print(pessoas)
p = p + p

Trust-Region Dogleg Method for Nonlinear Equations

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

Converting floats in Python to Scientific Numbers

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'

Degree, Proximity and Rank Prestige

I want to find these three Prestige measures for an existing graph using python:
Degree Prestige
Proximity Prestige
Rank Prestige
Can I use networkx for this purpose? If not, then which library can I use and how can I do it. Any links or references are appreciated.
Yes, you can but you to implement the measures by yourself as far as I know.
For instance, consider the Degree prestige defined as the number of incoming links to a node divided by the total possible number of incoming links.
In this case you could just calculate it as:
n_nodes = 10
d = nx.gnp_random_graph(n_nodes, 0.5, directed=True)
degree_prestige = dict((v,len(d.in_edges(v))/(n_nodes-1)) for v in d.nodes_iter())
Same for the other measures which can be easily implemented used the functions defined by networkx.
n_nodes = 5
d = nx.gnp_random_graph(n_nodes, 0.5, directed=True)
degree_prestige = dict((v,len(d.in_edges(v))/(n_nodes-1)) for v in d.nodes())
print("DEGREE PRESTIGE :\n")
for i in degree_prestige:
print(i, " : ", degree_prestige[i])
distance = []
temp_dis = 0
n = 0
for dest in d.nodes:
temp_dis = 0
n = 0
for src in d.nodes:
if (nx.has_path(d,src,dest) == True):
temp_dis = temp_dis + nx.shortest_path_length(d,source = src,target = dest)
n = n + 1
if temp_dis == 0:
distance.append([dest, 0])
else:
distance.append([dest, temp_dis/(n - 1)])
print("\nPROXIMITY PRESTIGE :\n")
for i in distance:
print(str(i[0]) + " : " + str(i[1]))
prominance = np.random.randint(1, 4, size=n_nodes)
print("\nASSUME PROMINANCE :\n")
print(prominance)
rank_prestige = np.zeros([n_nodes], dtype = int)
path_matrix = np.zeros([n_nodes, n_nodes], dtype = int)
i = 0
j = 0
for src in d.nodes:
for dest in d.nodes:
if d.has_edge(dest, src):
path_matrix[i][j] = 1
j = j+1
j = 0
i = i+1
for i in range(n_nodes):
pr_i = 0
for j in range(n_nodes):
pr_i = pr_i + path_matrix[i][j] * prominance[j]
rank_prestige[i] = pr_i
print("\nRANK PRESTIGE :\n")
print(rank_prestige)

Python code vs BBC Basic for Windows

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

Categories

Resources