1
Files
randomgraphslinks/random_graphs2.py
T
2025-05-29 09:00:30 -04:00

263 lines
6.4 KiB
Python
Executable File

import time
import random
from multiprocessing import Process, Pool
def main():
start = time.time()
# number process
k=int(input('Number of parallel processes: '))
# data points per process
m=int(input('Total number of data points: '))
# vertices per graph
n=int(input('Number of vertices per graph: '))
# probability of each edge appearing
p=float(input('Probability of an edge connecting two vertices: '))
numlinks=[]
pool = Pool(k)
results=[pool.apply_async(generate_data,args=(n,1,p,)) for i in range(m)]
count=[]
for result in results:
result.wait()
output = result.get()
count=merge_data(count,output)
print('Distribution of linking numbers: ' + str(count))
sum_squared=0
for i in range(len(count)):
sum_squared+= i*i* count[i]
avg = 1. * sum_squared/m
print('Average sum of linking number squared: ' + str(avg))
end = time.time()
print('Total time: ' + str(end-start))
def generate_data(n,m,p):
count = []
for i in range(m):
# generate random graph
data = random_graph(n,p)
# merge data
merge_data(count,data)
return count
def merge_data(count, data):
while len(count)< len(data):
count.append(0)
for i in range(len(data)):
count[i]+=data[i]
return count
def generate_coords(len):
#pts = [[1,1,1], [2,2,2], [3,3,3], [4,4,4], [5,5,5], [6,6,6]]
pts=[]
for i in range(len):
pts.append([random.random(),random.random(),random.random()])
return pts
def generate_adj(len,p):
adj = []
for i in range(len):
adj.append([])
for j in range(len):
if j>i:
if random.random()<p:
adj[i].append(1)
else:
adj[i].append(0)
elif j==i:
adj[i].append(0)
else:
adj[i].append(adj[j][i])
return adj
def random_graph(n,p):
pts = generate_coords(n)
adj = generate_adj(n,p)
count=[]
components_list = generate_components([],[],range(n))
for pair in components_list:
cycle1_list = permute_cycle([], pair[0],adj)
cycle2_list = permute_cycle([], pair[1],adj)
for cycle1 in cycle1_list:
for cycle2 in cycle2_list:
link=linking_number(cycle1,cycle2,pts)
while len(count)<=link:
count.append(0)
count[link]+=1
return count
def generate_components(link1, link2, points):
if len(points)==0:
if len(link1)>2 and len(link2)>2:
return [[link1, link2]]
else:
return []
else:
output = []
output+=generate_components(link1+[points[0]], link2, points[1:])
output+=generate_components(link1,link2,points[1:])
if len(link1)>0:
output+=generate_components(link1,link2+[points[0]],points[1:])
return output
def permute_cycle(perm, remainder,adj):
if len(remainder) == 0:
# remove duplicates with reverse orientation
if perm[1] < perm[-1]:
# also check if last and first are connected
if adj[perm[0]][perm[-1]]==1:
return [perm]
else:
return []
else:
return []
if len(perm) == 0:
return permute_cycle([remainder[0]], remainder[1:],adj)
else:
output=[]
for i in range(len(remainder)):
if adj[perm[-1]][remainder[i]]==1:
output+= permute_cycle(perm +[remainder[i]], remainder[:i]+remainder[i+1:],adj)
return output
def linking_number(link1,link2,pts):
len1 = len(link1)
len2 = len(link2)
cross_num=0
for i in range(len1):
for k in range(len2):
j=(i+1) % len1
l=(k+1) % len2
p1=pts[link1[i]]
p2=pts[link1[j]]
q1=pts[link2[k]]
q2=pts[link2[l]]
cross_num+=check_crossing(p1,p2,q1,q2)
# string output for mathematica
comp1 = ''
comp2 = ''
for i in range(len1):
comp1 += '{' + str(link1[i])[1:-1] + '},'
for k in range(len2):
comp2 += '{' + str(link2[k])[1:-1] + '},'
comp1 += '{' + str(link1[0])[1:-1] + '}'
comp2 += '{' + str(link2[0])[1:-1] + '}'
#print('Graphics3D[{Red,Line[{'+comp1+'}],Blue,Line[{'+comp2+'}]}]')
return abs(cross_num // 2)
def check_crossing(p1,p2,q1,q2):
# solve linear system for when two lines cross
dxp = p2[0]-p1[0]
dyp = p2[1]-p1[1]
dxq = q2[0]-q1[0]
dyq = q2[1]-q1[1]
dxc = q1[0]-p1[0]
dyc = q1[1]-p1[1]
det=dyp*dxq-dxp*dyq
t=( dxq*dyc-dyq*dxc ) / det
s=( dxp*dyc-dyp*dxc ) / det
# check if the lines cross inside the segments from p1 to p2 and q1 to q2
if (0<t<1) and (0<s<1):
# segments cross, find which is the over crossing
if (p1[2] + t*(p2[2]-p1[2])) > (q1[2]+s*(q2[2]-q1[2])):
overunder= 1
else:
overunder= -1
else:
overunder= 0
# now determine sign of crossing
if (det*overunder >0):
return 1
elif (det*overunder < 0):
return -1
else:
return 0
if __name__ == "__main__":
main()
#Number of parallel processes: 1
#Number of data points per process: 1
#Number of vertices per graph: 12
#Distribution of linking numbers: [21803078, 12436371, 1439391, 70623, 1826, 20]
#Average sum of linking number squared: 18859258.0
#Total time: 6144.5997149944305
#Number of parallel processes: 4
#Number of data points per process: 25
#Number of vertices per graph: 11
#Distribution of linking numbers: [197717315, 88252703, 6298213, 152203, 2447, 18, 1]
#Average sum of linking number squared: 1148550.2
#Total time: 11594.052151679993
#Number of parallel processes: 4
#Number of data points per process: 25
#Number of vertices per graph: 10
#Distribution of linking numbers: [18121918, 6927567, 347324, 5051, 40]
#Average sum of linking number squared: 83629.62
#Total time: 925.2083818912506
#Number of parallel processes: 10
#Number of data points per process: 100
#Number of vertices per graph: 10
#Distribution of linking numbers: [181141920, 69334838, 3495202, 46635, 404, 1]
#Average sum of linking number squared: 83741.85
#Total time: 4584.27324009
#Number of parallel processes: 4
#Number of data points per process: 25
#Number of vertices per graph: 9
#Distribution of linking numbers: [1747822, 543817, 16180, 81]
#Average sum of linking number squared: 6092.66
#Total time: 84.65731692314148
#Number of parallel processes: 4
#Number of data points per process: 25
#Number of vertices per graph: 8
#Distribution of linking numbers: [167672, 42308, 720]
#Average sum of linking number squared: 451.88
#Total time: 9.123421669006348
#Number of parallel processes: 4
#Number of data points per process: 25
#Number of vertices per graph: 7
#Distribution of linking numbers: [14437, 3046, 17]
#Average sum of linking number squared: 31.14
#Total time: 3.5018203258514404
#Number of parallel processes: 4
#Number of data points per process: 25
#Number of vertices per graph: 6
#Distribution of linking numbers: [838, 162]
#Average sum of linking number squared: 1.62
#Total time: 3.2760980129241943