Andreas Fruhwirt 34b7a83d1a not working yet
2024-01-10 19:48:30 +01:00

150 lines
4.6 KiB
Python

#!/usr/bin/python3
from random import randint, random
import networkx as nx
import sys
class Node(object):
def __init__(self, id, g):
self.graph = g
self.id = id
self.color = None
self.candidate_list = None
self.queue = "start"
self.next_tick = None
self.edges = []
self.done = False
def add_edge(self, node):
self.edges.append(node)
def print(self):
print(f"Node {self.id} = (c:{self.color}, #e:{len(self.edges)})")
def run_tick(self):
if not self.done:
# candidate list of colors
self.candidate_list = self.graph.possible_colors.copy()
if not self.next_tick == "start":
# if its not the first iteration w/o data, filter out all neighbor colors from candidate list
neighbor_candidates = self.next_tick.copy()
for colore in neighbor_candidates:
if colore in self.candidate_list:
self.candidate_list.remove(colore)
# if color is in candidate list (no neighbors has this color), finish.
# do not run this at start
if self.color in self.candidate_list and self.color is not None:
self.done = True
self.queue = "stop"
#print(f"{self.id} | is done")
return
# pick random color from candidate list
self.color = self.candidate_list[randint(0, len(self.candidate_list) - 1)]
#print(f"{self.id} | possible colors: {self.candidate_list}, current color: {self.color}")
# send data to the other neighbors
for n in self.edges:
if n.queue != "stop":
n.queue.append(self.color)
#print(f"{self.id} => sending {self.color} to N[{n.id}]")
class Graph(object):
def __init__(self):
self.V = None
self.max_degree = None
def load_graph_file(self, graph_file):
with open(graph_file, "r") as f:
V_amt, E_amt = map(int, f.readline().split(" "))
self.V = [Node(x, self) for x in range(1, V_amt+1)]
self.E = {}
self.max_degree = 0
for i in range(0, E_amt):
a, b = map(int, f.readline().split(" "))
a -= 1
b -= 1
self.V[a].add_edge(self.V[b])
self.V[b].add_edge(self.V[a])
self.max_degree = max(self.max_degree, len(self.V[a].edges), len(self.V[b].edges))
self.possible_colors = [x for x in range(1, self.max_degree + 2)]
def load_graph_networkx(self, graph):
self.V = [Node(x, self) for x in range(1, graph.number_of_nodes() + 1)]
self.E = {}
self.max_degree = 0
for a, b in graph.edges:
self.V[a].add_edge(self.V[b])
self.V[b].add_edge(self.V[a])
self.max_degree = max(self.max_degree, len(self.V[a].edges), len(self.V[b].edges))
self.possible_colors = [x for x in range(1, self.max_degree + 2)]
def run_tick(self):
print("Next Tick")
# send data
for n in self.V:
n.next_tick = n.queue
n.queue = []
# run tick for each
for n in self.V:
n.run_tick()
done = True
for n in self.V:
done &= n.done
if done:
print("Stop")
return -1
pass
def print_graph(self):
print(f"Max Degree: {self.max_degree}")
for n in self.V:
n.print()
def check_correctness(self):
for n in self.V:
color = n.color
for neighbor in n.edges:
if neighbor.color == color:
print("=====================")
n.print()
neighbor.print()
print(f"Neighbor {neighbor.id} has same color as {n.id}")
print("=====================")
return False
return True
def main():
g = Graph()
if len(sys.argv) == 2:
filename = sys.argv[1]
g.load_graph(filename)
else:
G = nx.erdos_renyi_graph(randint(100, 300), random())
g.load_graph_networkx(G)
g.print_graph()
for i in range(0, 10):
ret = g.run_tick()
if ret == -1:
# print info
print("Final colors:")
for n in g.V:
n.print()
# assert if correct
assert g.check_correctness()
exit(0)
pass
if __name__ == '__main__':
main()