initial commit
This commit is contained in:
@@ -0,0 +1,50 @@
|
||||
import os
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
|
||||
csv_file = "results/synthetic_data/raw/20260302_183202.csv"
|
||||
save_folder = f"results/synthetic_data/derived/{os.path.splitext(os.path.basename(csv_file))[0]}"
|
||||
os.makedirs(save_folder, exist_ok=True)
|
||||
|
||||
df = pd.read_csv(csv_file)
|
||||
df = df[df["algorithm"] == "binary"].copy()
|
||||
df["relax_success_ratio"] = df["relax_success"] / df["relax_attempts"]
|
||||
|
||||
# N vs extract_min_calls
|
||||
grouped = df.groupby("nodes")["extract_min_calls"].mean()
|
||||
|
||||
plt.figure(figsize=(6,4))
|
||||
plt.plot(grouped.index, grouped.values, marker='o')
|
||||
plt.xlabel("N (nodes)")
|
||||
plt.ylabel("Average extract_min_calls")
|
||||
plt.title("Nodes vs Extract-Min Calls")
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f"{save_folder}/N_vs_extract_min.png", dpi=300)
|
||||
plt.close()
|
||||
|
||||
# Density vs relax_attempts
|
||||
grouped = df.groupby("density")["relax_attempts"].mean()
|
||||
|
||||
plt.figure(figsize=(6,4))
|
||||
plt.plot(grouped.index, grouped.values, marker='o')
|
||||
plt.xlabel("Density")
|
||||
plt.ylabel("Average relax_attempts")
|
||||
plt.title("Density vs Relax Attempts")
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f"{save_folder}/density_vs_relax_attempts.png", dpi=300)
|
||||
plt.close()
|
||||
|
||||
# Sigma vs relax_success_ratio
|
||||
grouped = df.groupby("sigma")["relax_success_ratio"].mean()
|
||||
|
||||
plt.figure(figsize=(6,4))
|
||||
plt.plot(grouped.index, grouped.values, marker='o')
|
||||
plt.xlabel("Sigma (lognormal)")
|
||||
plt.ylabel("Relax Success Ratio")
|
||||
plt.title("Sigma vs Relax Success Ratio")
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f"{save_folder}/sigma_vs_relax_ratio.png", dpi=300)
|
||||
plt.close()
|
||||
@@ -0,0 +1,48 @@
|
||||
import numpy as np
|
||||
import pandas as pd
|
||||
from sklearn.linear_model import LinearRegression
|
||||
from sklearn.metrics import r2_score
|
||||
|
||||
def fit_op_cost_functional(df, algo):
|
||||
sub = df[(df["algorithm"] == algo) & (df["reached"] == True)].copy()
|
||||
|
||||
sub["logN"] = np.log(sub["nodes"])
|
||||
sub = sub.rename(columns={"relax_success":"decrease_key_calls",
|
||||
"nodes":"add_calls"})
|
||||
|
||||
if algo == "binary":
|
||||
sub["f_extract"] = sub["extract_min_calls"] * sub["logN"]
|
||||
sub["f_decrease"] = sub["decrease_key_calls"] * sub["logN"]
|
||||
else: # fibonacci
|
||||
sub["f_extract"] = sub["extract_min_calls"] * sub["logN"]
|
||||
sub["f_decrease"] = sub["decrease_key_calls"]
|
||||
|
||||
X = sub[["add_calls", "f_extract", "relax_attempts", "f_decrease"]].to_numpy()
|
||||
y = sub["time"].to_numpy()
|
||||
|
||||
model = LinearRegression()
|
||||
model.fit(X, y)
|
||||
|
||||
y_pred = model.predict(X)
|
||||
r2 = r2_score(y, y_pred)
|
||||
|
||||
return {
|
||||
"algo": algo,
|
||||
"intercept": model.intercept_,
|
||||
"coef_add": model.coef_[0],
|
||||
"coef_extract": model.coef_[1],
|
||||
"coef_relax": model.coef_[2],
|
||||
"coef_decrease": model.coef_[3],
|
||||
"r2": r2,
|
||||
"n_samples": len(sub)
|
||||
}
|
||||
|
||||
def op_cost_functional_analysis(df):
|
||||
return pd.DataFrame([
|
||||
fit_op_cost_functional(df, "binary"),
|
||||
fit_op_cost_functional(df, "fibonacci")
|
||||
])
|
||||
|
||||
df = pd.read_csv("results/synthetic_data/raw/20260302_183202.csv")
|
||||
summary = op_cost_functional_analysis(df)
|
||||
print(summary)
|
||||
@@ -0,0 +1,38 @@
|
||||
import pandas as pd
|
||||
import matplotlib.pyplot as plt
|
||||
import os
|
||||
|
||||
csv_file = "results/synthetic_data/raw/20260302_183202.csv"
|
||||
save_folder = f"results/synthetic_data/derived/{os.path.splitext(os.path.basename(csv_file))[0]}"
|
||||
os.makedirs(save_folder, exist_ok=True)
|
||||
|
||||
df = pd.read_csv(csv_file)
|
||||
# df = df[df["reached"] == True].copy()
|
||||
|
||||
key_cols = ["nodes", "density", "std", "sigma", "trial", "seed"]
|
||||
|
||||
pivot_time = (
|
||||
df.pivot_table(index=key_cols, columns="algorithm", values="time", aggfunc="mean")
|
||||
.reset_index()
|
||||
)
|
||||
pivot_time["speed_ratio"] = pivot_time["binary"] / pivot_time["fibonacci"]
|
||||
|
||||
# print((pivot_time["speed_ratio"] > 1).sum())
|
||||
# print((pivot_time["speed_ratio"] < 1).sum())
|
||||
|
||||
relax = (
|
||||
df[df["algorithm"] == "binary"][key_cols + ["relax_success"]]
|
||||
)
|
||||
|
||||
merged = pivot_time.merge(relax, on=key_cols, how="left")
|
||||
|
||||
plt.figure(figsize=(6, 4))
|
||||
plt.scatter(merged["relax_success"], merged["speed_ratio"], marker=".")
|
||||
plt.axhline(y=1.0, color='red', linestyle='--')
|
||||
plt.xlabel("decrease_key (binary)")
|
||||
plt.ylabel("speed_ratio (binary / fibonacci)")
|
||||
plt.title("decrease_key vs speed_ratio")
|
||||
plt.grid(True)
|
||||
plt.tight_layout()
|
||||
plt.savefig(f"{save_folder}/decrease_key_vs_speed_ratio.png", dpi=300)
|
||||
plt.close()
|
||||
@@ -0,0 +1,36 @@
|
||||
import numpy as np
|
||||
|
||||
def generate_graph(NODES=10, DENSITY=0.1, DISTRIBUTION=('lognormal', (100, 1)), SEED=42):
|
||||
rng = np.random.default_rng(SEED)
|
||||
|
||||
# Calculate variables
|
||||
max_edges = (NODES - 1) * NODES
|
||||
edges = int(round(DENSITY * max_edges))
|
||||
|
||||
# Make edges
|
||||
sel = rng.choice(max_edges, size=edges, replace=False)
|
||||
|
||||
# Make distance array
|
||||
dist_name, dist_params = DISTRIBUTION
|
||||
|
||||
if dist_name == "lognormal":
|
||||
mean, sigma = dist_params
|
||||
distances = rng.lognormal(mean=mean, sigma=sigma, size=edges)
|
||||
elif dist_name == "uniform":
|
||||
mean = dist_params[0]
|
||||
distances = rng.uniform(0.0, 2.0 * mean, size=edges)
|
||||
elif dist_name == "exponential":
|
||||
mean = dist_params[0]
|
||||
distances = rng.exponential(scale=mean, size=edges)
|
||||
else:
|
||||
raise ValueError("Unknown DISTRIBUTION")
|
||||
|
||||
# Make adj
|
||||
adj = [[] for _ in range(NODES)]
|
||||
for idx, dist in zip(sel, distances):
|
||||
u = idx // (NODES-1)
|
||||
r = idx % (NODES-1)
|
||||
v = r if r < u else r + 1
|
||||
adj[u].append((v, dist))
|
||||
|
||||
return adj
|
||||
@@ -0,0 +1,44 @@
|
||||
import numpy as np
|
||||
|
||||
def outdegree_generate_graph(NODES, DENSITY, DISTRIBUTION, SEED=42):
|
||||
rng = np.random.default_rng(SEED)
|
||||
|
||||
max_edges = (NODES - 1) * NODES
|
||||
edges = int(round(DENSITY * max_edges))
|
||||
|
||||
base = edges // NODES
|
||||
rem = edges % NODES
|
||||
|
||||
adj = [[] for _ in range(NODES)]
|
||||
|
||||
dist_name, dist_params = DISTRIBUTION
|
||||
|
||||
if dist_name == "lognormal":
|
||||
mean, sigma = dist_params
|
||||
dist_func = lambda size: rng.lognormal(mean=mean, sigma=sigma, size=size)
|
||||
elif dist_name == "uniform":
|
||||
mean = dist_params[0]
|
||||
dist_func = lambda size: rng.uniform(0.0, 2.0 * mean, size=size)
|
||||
elif dist_name == "exponential":
|
||||
mean = dist_params[0]
|
||||
dist_func = lambda size: rng.exponential(scale=mean, size=size)
|
||||
else:
|
||||
raise ValueError("Unknown DISTRIBUTION")
|
||||
|
||||
for u in range(NODES):
|
||||
d_u = base + (1 if u < rem else 0)
|
||||
|
||||
if d_u == 0:
|
||||
continue
|
||||
|
||||
targets = rng.choice(NODES-1, size=d_u, replace=False)
|
||||
targets = np.where(targets < u, targets, targets + 1)
|
||||
|
||||
weights = dist_func(d_u)
|
||||
weights = np.rint(weights).astype(np.int64)
|
||||
weights = np.maximum(weights, 1)
|
||||
|
||||
for v, w in zip(targets, weights):
|
||||
adj[u].append((v, float(w)))
|
||||
|
||||
return adj
|
||||
@@ -0,0 +1,149 @@
|
||||
import time
|
||||
import pandas as pd
|
||||
import numpy as np
|
||||
from tqdm import tqdm
|
||||
import datetime
|
||||
import json
|
||||
import os
|
||||
|
||||
from experiments.synthetic_data.graph_generators.outdegree_graph_generator import outdegree_generate_graph
|
||||
from core.dijkstra.heap_dijkstra import heap_dijkstra
|
||||
from core.heaps.binary_heap import BinHeap
|
||||
from core.heaps.fibonacci_heap import FiboHeap
|
||||
|
||||
def run_test(
|
||||
nodes_li,
|
||||
densities,
|
||||
stds,
|
||||
trials,
|
||||
mean_dist,
|
||||
start,
|
||||
end,
|
||||
base_seed
|
||||
):
|
||||
timer = time.perf_counter
|
||||
file_exists = False
|
||||
INF = float('inf')
|
||||
|
||||
total_jobs = (
|
||||
len(nodes_li) *
|
||||
len(densities) *
|
||||
len(stds) *
|
||||
trials
|
||||
)
|
||||
|
||||
with tqdm(total=total_jobs) as pbar:
|
||||
for nodes in nodes_li:
|
||||
rows = []
|
||||
|
||||
for density in densities:
|
||||
for std in stds:
|
||||
sigma = np.sqrt(np.log((std / mean_dist)**2 + 1))
|
||||
mu = np.log(mean_dist) - (sigma**2) / 2
|
||||
distribution = ('lognormal', (mu, sigma))
|
||||
|
||||
for trial in range(1, trials + 1):
|
||||
seed = (base_seed * 1_000_003) ^ (nodes * 9176) ^ int(density * 1e9) ^ int(sigma * 1e6) ^ trial
|
||||
seed &= 0xFFFFFFFF
|
||||
|
||||
adj = outdegree_generate_graph(
|
||||
NODES=nodes,
|
||||
DENSITY=density,
|
||||
DISTRIBUTION=distribution,
|
||||
SEED=seed
|
||||
)
|
||||
|
||||
bin_heap = BinHeap(nodes)
|
||||
st = timer()
|
||||
dist, stats = heap_dijkstra(nodes, adj, bin_heap, start, end)
|
||||
et = timer()
|
||||
rows.append(
|
||||
{
|
||||
"nodes": nodes,
|
||||
"density": density,
|
||||
"std": std,
|
||||
"sigma": sigma,
|
||||
"trial": trial,
|
||||
"seed": seed,
|
||||
"time": et - st,
|
||||
"algorithm": "binary",
|
||||
"reached": dist != INF,
|
||||
"extract_min_calls": stats.extract_min_calls,
|
||||
"relax_attempts": stats.relax_attempts,
|
||||
"relax_success": stats.relax_success,
|
||||
}
|
||||
)
|
||||
|
||||
fibo_heap = FiboHeap(nodes)
|
||||
st = timer()
|
||||
dist, stats = heap_dijkstra(nodes, adj, fibo_heap, start, end)
|
||||
et = timer()
|
||||
rows.append(
|
||||
{
|
||||
"nodes": nodes,
|
||||
"density": density,
|
||||
"std": std,
|
||||
"sigma": sigma,
|
||||
"trial": trial,
|
||||
"seed": seed,
|
||||
"time": et - st,
|
||||
"algorithm": "fibonacci",
|
||||
"reached": dist != INF,
|
||||
"extract_min_calls": stats.extract_min_calls,
|
||||
"relax_attempts": stats.relax_attempts,
|
||||
"relax_success": stats.relax_success,
|
||||
}
|
||||
)
|
||||
|
||||
pbar.update(1)
|
||||
|
||||
df_nodes = pd.DataFrame(rows)
|
||||
df_nodes.to_csv(
|
||||
csv_file,
|
||||
mode='a',
|
||||
header=not file_exists,
|
||||
index=False
|
||||
)
|
||||
file_exists = True
|
||||
print(f"=== SAVED nodes = {nodes} ({len(df_nodes)} rows) ===")
|
||||
return
|
||||
|
||||
# Settings
|
||||
nodes_li = [2000, 4000, 8000, 16000]
|
||||
densities = [0.00015, 0.0003, 0.0006, 0.0012, 0.0024, 0.0048, 0.0096, 0.0192, 0.0384]
|
||||
stds = [1000, 1500, 2000, 3000, 4000, 6000, 8000, 12000, 16000]
|
||||
trials = 400
|
||||
mean_dist = 3000
|
||||
start = 0
|
||||
end = 1
|
||||
base_seed = 42
|
||||
|
||||
save_folder = "results/synthetic_data/raw"
|
||||
os.makedirs(save_folder, exist_ok=True)
|
||||
timestamp = datetime.datetime.now().strftime("%Y%m%d_%H%M%S")
|
||||
csv_file = f"{save_folder}/{timestamp}.csv"
|
||||
config_file = f"{save_folder}/{timestamp}.json"
|
||||
|
||||
config = {
|
||||
"nodes_li": nodes_li,
|
||||
"densities": densities,
|
||||
"stds": stds,
|
||||
"trials": trials,
|
||||
"mean_dist": mean_dist,
|
||||
"start": start,
|
||||
"end": end,
|
||||
"base_seed": base_seed,
|
||||
}
|
||||
with open(config_file, "w") as f:
|
||||
json.dump(config, f, indent=4)
|
||||
|
||||
df = run_test(
|
||||
nodes_li = nodes_li,
|
||||
densities = densities,
|
||||
stds = stds,
|
||||
trials = trials,
|
||||
mean_dist = mean_dist,
|
||||
start = start,
|
||||
end = end,
|
||||
base_seed = base_seed
|
||||
)
|
||||
Reference in New Issue
Block a user