Commit second task of 3rd lab
This commit is contained in:
+3
-2
@@ -1,4 +1,5 @@
|
|||||||
benchmark
|
benchmark
|
||||||
|
.direnv
|
||||||
*.csv
|
*.csv
|
||||||
charts/
|
*.png
|
||||||
direnv/
|
*.txt
|
||||||
|
|||||||
@@ -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