Commit second task of 3rd lab
This commit is contained in:
@@ -0,0 +1,92 @@
|
||||
import random
|
||||
import time
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
def generate_hamiltonian_graph(n, saturation_percent):
|
||||
max_possible_edges = n * (n - 1) // 2
|
||||
target_edges = max_possible_edges * saturation_percent // 100
|
||||
|
||||
# Working on sets, its just easier
|
||||
graph = {i: set() for i in range(n)}
|
||||
edge_count = 0
|
||||
|
||||
cycle = list(range(n))
|
||||
random.shuffle(cycle)
|
||||
for i in range(n):
|
||||
u = cycle[i]
|
||||
v = cycle[(i + 1) % n]
|
||||
if v not in graph[u]:
|
||||
graph[u].add(v)
|
||||
graph[v].add(u)
|
||||
edge_count += 1
|
||||
|
||||
possible_edges = {(i, j) for i in range(n) for j in range(i+1, n)}
|
||||
used_edges = {(min(u, v), max(u, v)) for u in graph for v in graph[u]}
|
||||
available_edges = list(possible_edges - used_edges)
|
||||
random.shuffle(available_edges)
|
||||
|
||||
while edge_count < target_edges and available_edges:
|
||||
u, v = available_edges.pop()
|
||||
if v not in graph[u]:
|
||||
graph[u].add(v)
|
||||
graph[v].add(u)
|
||||
edge_count += 1
|
||||
|
||||
return {k: list(v) for k, v in graph.items()}
|
||||
|
||||
def find_all_hamiltonian_cycles(graph):
|
||||
n = len(graph)
|
||||
cycles = set()
|
||||
|
||||
def backtrack(path, visited):
|
||||
if len(path) == n:
|
||||
if path[0] in graph[path[-1]]:
|
||||
# We have to normalize the cycle to avoid duplicates
|
||||
cycle = tuple(path)
|
||||
rev_cycle = tuple(reversed(path))
|
||||
canonical = min(cycle, rev_cycle)
|
||||
|
||||
min_idx = canonical.index(min(canonical))
|
||||
normalized = canonical[min_idx:] + canonical[:min_idx]
|
||||
cycles.add(normalized)
|
||||
return
|
||||
|
||||
for neighbor in graph[path[-1]]:
|
||||
if neighbor not in visited:
|
||||
visited.add(neighbor)
|
||||
path.append(neighbor)
|
||||
backtrack(path, visited)
|
||||
path.pop()
|
||||
visited.remove(neighbor)
|
||||
|
||||
for start in range(n):
|
||||
backtrack([start], {start})
|
||||
|
||||
return list(cycles)
|
||||
|
||||
if __name__ == "__main__":
|
||||
n_values = range(5, 15)
|
||||
saturation = 50
|
||||
|
||||
times = []
|
||||
cycle_counts = []
|
||||
|
||||
for n in n_values:
|
||||
graph = generate_hamiltonian_graph(n, saturation)
|
||||
print(f"Running test for n={n}...")
|
||||
start = time.time()
|
||||
cycles = find_all_hamiltonian_cycles(graph)
|
||||
elapsed = (time.time() - start) * 1000
|
||||
times.append(elapsed)
|
||||
cycle_counts.append(len(cycles))
|
||||
print(f"Found {len(cycles)} cycles in {elapsed:.2f} ms")
|
||||
|
||||
plt.figure(figsize=(10, 6))
|
||||
plt.plot(n_values, times, marker="o")
|
||||
plt.xlabel("Liczba wierzchołków (n)")
|
||||
plt.ylabel("Czas działania [ms]")
|
||||
plt.title("Czas znajdowania wszystkich cykli Hamiltona dla nasycenia 50%")
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.yscale('log', base=2)
|
||||
plt.savefig("hamilton.png")
|
||||
Reference in New Issue
Block a user