initial commit

This commit is contained in:
2026-03-02 20:55:36 +09:00
commit f224644b49
86 changed files with 1065250 additions and 0 deletions
@@ -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
+149
View File
@@ -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
)