InΒ [Β ]:
# import warnings
# warnings.filterwarnings('ignore', category=DeprecationWarning)
# warnings.filterwarnings('ignore', message='Glyph.*missing from font')
InΒ [Β ]:
InΒ [1]:
import numpy as np
import pandas as pd
import networkx as nx
import matplotlib.pyplot as plt
import seaborn as sns
import string
import os
from collections import defaultdict
INDEX=90
# ==================== HELPER FUNCTIONS ====================
def generate_two_letter_labels(n):
labels = []
for i in range(n):
first = i // 26
second = i % 26
label = string.ascii_uppercase[first] + string.ascii_uppercase[second]
labels.append(label)
return labels
# ==================== KRUSKAL ALGORITHM ====================
class UnionFind:
def __init__(self, n):
self.parent = list(range(n))
self.rank = [0] * n
def find(self, x):
if self.parent[x] != x:
self.parent[x] = self.find(self.parent[x])
return self.parent[x]
def union(self, x, y):
px, py = self.find(x), self.find(y)
if px == py:
return False
if self.rank[px] < self.rank[py]:
px, py = py, px
self.parent[py] = px
if self.rank[px] == self.rank[py]:
self.rank[px] += 1
return True
def kruskal_mst(dist_matrix):
n = len(dist_matrix)
edges = []
for i in range(n):
for j in range(i+1, n):
edges.append((dist_matrix[i][j], i, j))
edges.sort()
uf = UnionFind(n)
mst_edges = []
total_weight = 0
for weight, u, v in edges:
if uf.union(u, v):
mst_edges.append((u, v))
total_weight += weight
if len(mst_edges) == n - 1:
break
return total_weight, mst_edges
# ==================== ACO BASE CLASS ====================
class ACO:
def __init__(self, dist_matrix, n_ants=10, n_iterations=100, alpha=1, beta=2, rho=0.5):
self.dist_matrix = dist_matrix
self.n_nodes = len(dist_matrix)
self.n_ants = n_ants
self.n_iterations = n_iterations
self.alpha = alpha
self.beta = beta
self.rho = rho
self.pheromone = np.ones((self.n_nodes, self.n_nodes))
def _select_next_node(self, current, unvisited, max_degree=None, degrees=None):
pheromone = self.pheromone[current, unvisited]
heuristic = 1.0 / (self.dist_matrix[current, unvisited] + 1e-10)
if max_degree is not None and degrees is not None:
valid_mask = np.array([degrees[node] < max_degree for node in unvisited])
if not np.any(valid_mask):
return None
pheromone = pheromone * valid_mask
heuristic = heuristic * valid_mask
probabilities = (pheromone ** self.alpha) * (heuristic ** self.beta)
prob_sum = probabilities.sum()
if prob_sum > 0:
probabilities = probabilities / prob_sum
else:
return None
return np.random.choice(unvisited, p=probabilities)
def _update_pheromone(self, solutions, costs):
self.pheromone *= (1 - self.rho)
for solution, cost in zip(solutions, costs):
for i, j in solution:
self.pheromone[i][j] += 1.0 / cost
self.pheromone[j][i] += 1.0 / cost
# ==================== ACO TSP PATH (FAIR - NO CYCLE) ====================
class ACO_TSP_Path(ACO):
"""TSP Hamiltonian Path - TIDAK kembali ke awal (n-1 edges) - FAIR"""
def construct_solution(self, max_degree=None):
start = np.random.randint(self.n_nodes)
tour = [start]
unvisited = list(range(self.n_nodes))
unvisited.remove(start)
degrees = defaultdict(int) if max_degree else None
if max_degree:
degrees[start] = 0
while unvisited:
current = tour[-1]
next_node = self._select_next_node(current, unvisited, max_degree, degrees)
if next_node is None:
return None, float('inf')
tour.append(next_node)
unvisited.remove(next_node)
if max_degree:
degrees[current] += 1
degrees[next_node] += 1
# TIDAK kembali ke awal (PATH - FAIR COMPARISON)
edges = [(tour[i], tour[i+1]) for i in range(len(tour)-1)]
cost = sum(self.dist_matrix[i][j] for i, j in edges)
return edges, cost
def run(self, max_degree=None):
best_cost = float('inf')
best_solution = None
for iteration in range(self.n_iterations):
solutions = []
costs = []
for ant in range(self.n_ants):
solution, cost = self.construct_solution(max_degree)
if solution is not None:
solutions.append(solution)
costs.append(cost)
if cost < best_cost:
best_cost = cost
best_solution = solution
if solutions:
self._update_pheromone(solutions, costs)
return best_cost, best_solution
# ==================== ACO MST ====================
class ACO_MST(ACO):
def construct_solution(self, max_degree=None):
start = np.random.randint(self.n_nodes)
in_tree = {start}
edges = []
degrees = defaultdict(int) if max_degree else None
while len(in_tree) < self.n_nodes:
candidates = []
for node in in_tree:
if max_degree and degrees[node] >= max_degree:
continue
for next_node in range(self.n_nodes):
if next_node not in in_tree:
if max_degree is None or degrees[next_node] < max_degree:
candidates.append((node, next_node))
if not candidates:
return None, float('inf')
probs = []
for i, j in candidates:
pheromone = self.pheromone[i][j]
heuristic = 1.0 / (self.dist_matrix[i][j] + 1e-10)
prob = (pheromone ** self.alpha) * (heuristic ** self.beta)
probs.append(prob)
probs = np.array(probs)
probs = probs / probs.sum()
selected_idx = np.random.choice(len(candidates), p=probs)
selected_edge = candidates[selected_idx]
edges.append(selected_edge)
in_tree.add(selected_edge[1])
if max_degree:
degrees[selected_edge[0]] += 1
degrees[selected_edge[1]] += 1
cost = sum(self.dist_matrix[i][j] for i, j in edges)
return edges, cost
def run(self, max_degree=None):
best_cost = float('inf')
best_solution = None
for iteration in range(self.n_iterations):
solutions = []
costs = []
for ant in range(self.n_ants):
solution, cost = self.construct_solution(max_degree)
if solution is not None:
solutions.append(solution)
costs.append(cost)
if cost < best_cost:
best_cost = cost
best_solution = solution
if solutions:
self._update_pheromone(solutions, costs)
return best_cost, best_solution
# ==================== VISUALIZATION ====================
def visualize_solution(dist_matrix, edges, node_labels, title, save_path=None):
"""Visualize graph solution"""
G = nx.Graph()
# Add all nodes
for i, label in enumerate(node_labels):
G.add_node(label)
# Add solution edges
for i, j in edges:
u = node_labels[i]
v = node_labels[j]
weight = dist_matrix[i][j]
G.add_edge(u, v, weight=weight)
plt.figure(figsize=(12, 10))
pos = nx.spring_layout(G, seed=42, k=2)
# Draw nodes
nx.draw_networkx_nodes(G, pos, node_color='lightblue',
node_size=800, alpha=0.9)
# Draw edges
nx.draw_networkx_edges(G, pos, width=3, alpha=0.6, edge_color='darkblue')
# Draw labels
nx.draw_networkx_labels(G, pos, font_size=10, font_weight='bold')
# Draw edge weights
edge_labels = {(u, v): f'{data["weight"]:.0f}' for u, v, data in G.edges(data=True)}
nx.draw_networkx_edge_labels(G, pos, edge_labels, font_size=8)
plt.title(title, fontsize=16, fontweight='bold', pad=20)
plt.axis('off')
plt.tight_layout()
if save_path:
plt.savefig(save_path, dpi=150, bbox_inches='tight')
plt.show()
# ==================== LOAD DATASET ====================
def load_datasets_from_csv(num_vertices=10, datasetKolomMax=31, folder_name='results'):
if not os.path.exists(folder_name):
os.makedirs(folder_name)
NF = f'datasetNorm/dataset{num_vertices}_ideal.csv'
print(f"Loading file: {NF}")
try:
# PERBAIKAN: Gunakan delimiter semicolon dan strip whitespace dari header
df = pd.read_csv(NF, delimiter=';')
df.columns = df.columns.str.strip() # Hapus whitespace dari nama kolom
print(f"Loaded CSV with {len(df)} rows and {len(df.columns)} columns")
print(f"Columns: {df.columns.tolist()}")
expected_edges = num_vertices * (num_vertices - 1) // 2
print(f"Expected edges for {num_vertices} vertices: {expected_edges}")
datasets = []
for ii in range(1, datasetKolomMax):
COL = f'NamaFile{ii}'
if COL not in df.columns:
print(f"Column {COL} not found, stopping at {ii-1} datasets")
break
weights = df[COL].tolist()
if len(weights) < expected_edges:
print(f"Not enough weights in {COL}: {len(weights)} < {expected_edges}")
break
# Create complete graph
G = nx.complete_graph(num_vertices)
for i, (u, v) in enumerate(G.edges()):
if i < len(weights): # Safety check
G[u][v]['weight'] = weights[i]
# Generate node labels
if num_vertices <= 20:
node_labels = [letter for letter in string.ascii_uppercase[:num_vertices]]
else:
node_labels = generate_two_letter_labels(num_vertices)
G = nx.relabel_nodes(G, {i: node_labels[i] for i in range(num_vertices)})
# Convert to distance matrix
nodes = sorted(G.nodes())
n = len(nodes)
node_to_idx = {node: idx for idx, node in enumerate(nodes)}
dist_matrix = np.zeros((n, n))
for u, v, data in G.edges(data=True):
i = node_to_idx[u]
j = node_to_idx[v]
weight = data['weight']
dist_matrix[i][j] = weight
dist_matrix[j][i] = weight
datasets.append((dist_matrix, node_labels, G))
print(f"Successfully loaded {len(datasets)} datasets")
return datasets
except FileNotFoundError:
print(f"File not found: {NF}")
print(f"Creating sample dataset...")
os.makedirs('datasetNorm', exist_ok=True)
n_edges = num_vertices * (num_vertices - 1) // 2
data = {f'NamaFile{i}': np.random.randint(10, 100, size=n_edges)
for i in range(1, min(datasetKolomMax, 11))}
df_new = pd.DataFrame(data)
df_new.insert(0, 'Nomor', range(1, n_edges + 1))
# PERBAIKAN: Simpan dengan delimiter semicolon
df_new.to_csv(NF, index=False, sep=';')
return load_datasets_from_csv(num_vertices, datasetKolomMax, folder_name)
except Exception as e:
print(f"Error loading datasets: {e}")
import traceback
traceback.print_exc()
return []
# ==================== MAIN EXECUTION ====================
if __name__ == "__main__":
print("="*80)
print("FAIR ACO COMPARISON: TSP PATH vs MST (SAME n-1 EDGES)")
print("="*80)
# Configuration
num_vertices = INDEX
datasetKolomMax = 31
folder_name = 'results'
# Load datasets
print("\nLoading datasets from CSV...")
datasets = load_datasets_from_csv(num_vertices, datasetKolomMax, folder_name)
if not datasets:
print("Error loading datasetsx!")
exit(1)
print(f"Loaded {len(datasets)} datasets with {num_vertices} vertices each")
# Initialize results
results = {
'Dataset': [],
'Kruskal': [],
'ACO_TSP_Path_Same': [],
'ACO_TSP_Path_Tuned': [],
'ACO_MST_Same': [],
'ACO_MST_Tuned': [],
'ACO_TSP_Path_Deg3_Same': [],
'ACO_TSP_Path_Deg3_Tuned': [],
'ACO_MST_Deg3_Same': [],
'ACO_MST_Deg3_Tuned': []
}
# Store first dataset solutions for visualization
first_solutions = {}
print("\n" + "="*80)
print("RUNNING EXPERIMENTS...")
print("="*80)
for idx, (dist_matrix, node_labels, G_complete) in enumerate(datasets):
print(f"\nDataset {idx+1}:")
results['Dataset'].append(f"D{idx+1}")
# Kruskal
kruskal_cost, kruskal_edges = kruskal_mst(dist_matrix)
results['Kruskal'].append(kruskal_cost)
print(f" Kruskal MST: {kruskal_cost:.2f} ({len(kruskal_edges)} edges)")
if idx == 0:
first_solutions['kruskal'] = (kruskal_edges, kruskal_cost)
# ACO TSP Path Same (Ξ²=2, Ο=0.5)
aco_tsp_same = ACO_TSP_Path(dist_matrix, beta=2, rho=0.5)
cost, edges = aco_tsp_same.run()
results['ACO_TSP_Path_Same'].append(cost)
print(f" ACO TSP Path Same: {cost:.2f} ({len(edges) if edges else 0} edges)")
if idx == 0 and edges:
first_solutions['tsp_same'] = (edges, cost)
# ACO TSP Path Tuned (Ξ²=2, Ο=0.3)
aco_tsp_tuned = ACO_TSP_Path(dist_matrix, beta=2, rho=0.3)
cost, edges = aco_tsp_tuned.run()
results['ACO_TSP_Path_Tuned'].append(cost)
print(f" ACO TSP Path Tuned: {cost:.2f} ({len(edges) if edges else 0} edges)")
# ACO MST Same
aco_mst_same = ACO_MST(dist_matrix, beta=2, rho=0.5)
cost, edges = aco_mst_same.run()
results['ACO_MST_Same'].append(cost)
print(f" ACO MST Same: {cost:.2f} ({len(edges) if edges else 0} edges)")
if idx == 0 and edges:
first_solutions['mst_same'] = (edges, cost)
# ACO MST Tuned
aco_mst_tuned = ACO_MST(dist_matrix, beta=1, rho=0.1)
cost, edges = aco_mst_tuned.run()
results['ACO_MST_Tuned'].append(cost)
print(f" ACO MST Tuned: {cost:.2f} ({len(edges) if edges else 0} edges)")
# With Degree=3 constraints
for name, aco_class, params in [
('TSP_Path_Deg3_Same', ACO_TSP_Path, {'beta': 2, 'rho': 0.5}),
('TSP_Path_Deg3_Tuned', ACO_TSP_Path, {'beta': 2, 'rho': 0.3}),
('MST_Deg3_Same', ACO_MST, {'beta': 2, 'rho': 0.5}),
('MST_Deg3_Tuned', ACO_MST, {'beta': 1, 'rho': 0.1})
]:
aco = aco_class(dist_matrix, **params)
cost, edges = aco.run(max_degree=3)
if cost == float('inf'):
for _ in range(5):
cost, edges = aco.run(max_degree=3)
if cost != float('inf'):
break
results[f'ACO_{name}'].append(cost if cost != float('inf') else None)
edge_count = len(edges) if edges and cost != float('inf') else 0
print(f" ACO {name}: {cost:.2f} ({edge_count} edges)" if cost != float('inf') else f" ACO {name}: No solution")
# Create DataFrame
df = pd.DataFrame(results)
print("\n" + "="*80)
print("RESULTS TABLE")
print("="*80)
print(df.to_string(index=False))
# Summary statistics
print("\n" + "="*80)
print("SUMMARY STATISTICS")
print("="*80)
def calc_stats(values):
clean_values = [v for v in values if v is not None and v != float('inf')]
if not clean_values:
return None, None, None, None
return (np.mean(clean_values), np.std(clean_values), min(clean_values), max(clean_values))
summary_data = []
for col in df.columns:
if col != 'Dataset':
mean, std, min_val, max_val = calc_stats(df[col])
summary_data.append({
'Algorithm': col,
'Mean': mean,
'Std': std,
'Min': min_val,
'Max': max_val
})
summary = pd.DataFrame(summary_data)
print(summary.to_string(index=False))
# FAIR COMPARISON ANALYSIS
print("\n" + "="*80)
print("β
FAIR COMPARISON ANALYSIS (n-1 edges)")
print("="*80)
kruskal_mean = summary.iloc[0]['Mean']
tsp_path_same_mean = summary.iloc[1]['Mean']
mst_same_mean = summary.iloc[3]['Mean']
print(f"\nEdge Count: n-1 = {num_vertices - 1} edges")
print(f"\n1. Kruskal (Optimal): {kruskal_mean:.2f}")
print(f"2. ACO TSP Path: {tsp_path_same_mean:.2f}")
print(f"3. ACO MST: {mst_same_mean:.2f}")
tsp_gap = ((tsp_path_same_mean / kruskal_mean) - 1) * 100
mst_gap = ((mst_same_mean / kruskal_mean) - 1) * 100
print(f"\nGap from Optimal:")
print(f" TSP Path vs Kruskal: {tsp_gap:+.2f}%")
print(f" MST vs Kruskal: {mst_gap:+.2f}%")
print(f"\nβ
Fair comparison karena:")
print(f" β’ Same edge count: {num_vertices - 1} edges")
print(f" β’ No cycle: TSP Path & MST both are paths/trees")
print(f" β’ Apple-to-apple: Both connect all nodes without cycle")
# VISUALIZE FIRST DATASET
print("\n" + "="*80)
print("VISUALIZING FIRST DATASET RESULTS")
print("="*80)
dist_matrix_1, node_labels_1, G_complete_1 = datasets[0]
# Visualize Complete Graph
print("\n1. Visualizing Complete Graph...")
plt.figure(figsize=(12, 10))
pos = nx.spring_layout(G_complete_1, seed=42, k=2)
nx.draw_networkx_nodes(G_complete_1, pos, node_color='lightgray', node_size=800, alpha=0.6)
nx.draw_networkx_edges(G_complete_1, pos, width=1, alpha=0.2, edge_color='gray')
nx.draw_networkx_labels(G_complete_1, pos, font_size=10, font_weight='bold')
edge_labels = {(u, v): f'{data["weight"]:.0f}' for u, v, data in G_complete_1.edges(data=True) if data['weight'] < 50}
nx.draw_networkx_edge_labels(G_complete_1, pos, edge_labels, font_size=7)
plt.title('Complete Graph - Dataset 1 (All Edges)', fontsize=16, fontweight='bold', pad=20)
plt.axis('off')
plt.tight_layout()
plt.savefig(f'{folder_name}/complete_graph.png', dpi=150, bbox_inches='tight')
plt.show()
# Visualize Kruskal MST
if 'kruskal' in first_solutions:
print("\n2. Visualizing Kruskal MST...")
edges, cost = first_solutions['kruskal']
visualize_solution(dist_matrix_1, edges, node_labels_1,
f'Kruskal MST - Dataset 1 (Weight={cost:.0f}, {len(edges)} edges)',
f'{folder_name}/kruskal_mst.png')
# Visualize ACO TSP Path
if 'tsp_same' in first_solutions:
print("\n3. Visualizing ACO TSP Path...")
edges, cost = first_solutions['tsp_same']
visualize_solution(dist_matrix_1, edges, node_labels_1,
f'ACO TSP Path - Dataset 1 (Weight={cost:.0f}, {len(edges)} edges)',
f'{folder_name}/aco_tsp_path.png')
# Visualize ACO MST
if 'mst_same' in first_solutions:
print("\n4. Visualizing ACO MST...")
edges, cost = first_solutions['mst_same']
visualize_solution(dist_matrix_1, edges, node_labels_1,
f'ACO MST - Dataset 1 (Weight={cost:.0f}, {len(edges)} edges)',
f'{folder_name}/aco_mst.png')
# Comparison Plots
print("\n5. Creating comparison plots...")
fig, axes = plt.subplots(2, 2, figsize=(16, 12))
# Plot 1: Fair Comparison (n-1 edges)
ax1 = axes[0, 0]
fair_data = [
[v for v in df['Kruskal'].values if v is not None],
[v for v in df['ACO_TSP_Path_Same'].values if v is not None],
[v for v in df['ACO_MST_Same'].values if v is not None]
]
ax1.boxplot(fair_data, tick_labels=['Kruskal\n(Optimal)', 'TSP Path\n(Same)', 'MST\n(Same)'])
ax1.set_title('β Fair Comparison (All n-1 edges)', fontsize=14, fontweight='bold')
ax1.set_ylabel('Total Weight', fontsize=12)
ax1.grid(True, alpha=0.3)
# Plot 2: With Degree Constraint
ax2 = axes[0, 1]
deg_data = [
[v for v in df['ACO_TSP_Path_Deg3_Same'].values if v is not None and v != float('inf')],
[v for v in df['ACO_MST_Deg3_Same'].values if v is not None and v != float('inf')]
]
if all(len(d) > 0 for d in deg_data):
ax2.boxplot(deg_data, tick_labels=['TSP Path\nDeg3', 'MST\nDeg3'])
ax2.set_title('Degree Constraint = 3', fontsize=14, fontweight='bold')
ax2.set_ylabel('Total Weight', fontsize=12)
ax2.grid(True, alpha=0.3)
# Plot 3: Bar comparison
ax3 = axes[1, 0]
means = [m if m is not None else 0 for m in summary['Mean'].values[:5]]
colors = ['green', 'blue', 'lightblue', 'purple', 'orchid']
bars = ax3.bar(range(len(means)), means, color=colors, alpha=0.7)
ax3.set_xticks(range(len(means)))
ax3.set_xticklabels(['Kruskal', 'TSP Path\nSame', 'TSP Path\nTuned', 'MST\nSame', 'MST\nTuned'], fontsize=9)
ax3.set_title('Mean Performance (n-1 edges)', fontsize=14, fontweight='bold')
ax3.set_ylabel('Mean Weight', fontsize=12)
ax3.grid(True, alpha=0.3, axis='y')
for bar, val in zip(bars, means):
if val > 0:
ax3.text(bar.get_x() + bar.get_width()/2, bar.get_height() + 5,
f'{val:.0f}', ha='center', va='bottom', fontsize=9)
# Plot 4: Edge count verification
ax4 = axes[1, 1]
edge_counts = [num_vertices - 1, num_vertices - 1, num_vertices - 1]
labels_edge = ['Kruskal', 'TSP Path', 'MST']
ax4.bar(labels_edge, edge_counts, color=['green', 'blue', 'purple'], alpha=0.7)
ax4.set_title('β Edge Count Verification (Fair!)', fontsize=14, fontweight='bold')
ax4.set_ylabel('Number of Edges', fontsize=12)
ax4.axhline(y=num_vertices - 1, color='r', linestyle='--', label=f'n-1 = {num_vertices - 1}')
ax4.legend()
ax4.grid(True, alpha=0.3, axis='y')
for i, (label, count) in enumerate(zip(labels_edge, edge_counts)):
ax4.text(i, count + 0.1, str(count), ha='center', va='bottom', fontsize=12, fontweight='bold')
plt.tight_layout()
plt.savefig(f'{folder_name}/fair_comparison.png', dpi=300, bbox_inches='tight')
plt.show()
# Save results
df.to_csv(f'{folder_name}/fair_aco_results.csv', index=False)
print("\n" + "="*80)
print("β
COMPLETED!")
print("="*80)
print(f"\nFiles saved to '{folder_name}/' folder:")
print(" π fair_aco_results.csv - Numerical results")
print(" π fair_comparison.png - Comparison plots")
print(" π complete_graph.png - Full graph visualization")
print(" π³ kruskal_mst.png - Kruskal MST result")
print(" π€οΈ aco_tsp_path.png - ACO TSP Path result")
print(" π² aco_mst.png - ACO MST result")
print("\nπ‘ KEY FINDINGS:")
print(f" β’ All methods use n-1 = {num_vertices - 1} edges (FAIR!)")
print(f" β’ TSP Path: NO cycle (like MST)")
print(f" β’ Kruskal: {kruskal_mean:.2f} (optimal)")
print(f" β’ ACO TSP Path: {tsp_path_same_mean:.2f} ({tsp_gap:+.2f}%)")
print(f" β’ ACO MST: {mst_same_mean:.2f} ({mst_gap:+.2f}%)")
================================================================================
FAIR ACO COMPARISON: TSP PATH vs MST (SAME n-1 EDGES)
================================================================================
Loading datasets from CSV...
Loading file: datasetNorm/dataset90_ideal.csv
Loaded CSV with 4005 rows and 31 columns
Columns: ['Nomor', 'NamaFile1', 'NamaFile2', 'NamaFile3', 'NamaFile4', 'NamaFile5', 'NamaFile6', 'NamaFile7', 'NamaFile8', 'NamaFile9', 'NamaFile10', 'NamaFile11', 'NamaFile12', 'NamaFile13', 'NamaFile14', 'NamaFile15', 'NamaFile16', 'NamaFile17', 'NamaFile18', 'NamaFile19', 'NamaFile20', 'NamaFile21', 'NamaFile22', 'NamaFile23', 'NamaFile24', 'NamaFile25', 'NamaFile26', 'NamaFile27', 'NamaFile28', 'NamaFile29', 'NamaFile30']
Expected edges for 90 vertices: 4005
Successfully loaded 30 datasets
Loaded 30 datasets with 90 vertices each
================================================================================
RUNNING EXPERIMENTS...
================================================================================
Dataset 1:
Kruskal MST: 1388.00 (89 edges)
ACO TSP Path Same: 1683.00 (89 edges)
ACO TSP Path Tuned: 1696.00 (89 edges)
ACO MST Same: 1416.00 (89 edges)
ACO MST Tuned: 1983.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1688.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1710.00 (89 edges)
ACO MST_Deg3_Same: 1443.00 (89 edges)
ACO MST_Deg3_Tuned: 1946.00 (89 edges)
Dataset 2:
Kruskal MST: 1352.00 (89 edges)
ACO TSP Path Same: 1674.00 (89 edges)
ACO TSP Path Tuned: 1705.00 (89 edges)
ACO MST Same: 1389.00 (89 edges)
ACO MST Tuned: 2002.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1674.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1669.00 (89 edges)
ACO MST_Deg3_Same: 1420.00 (89 edges)
ACO MST_Deg3_Tuned: 2026.00 (89 edges)
Dataset 3:
Kruskal MST: 1352.00 (89 edges)
ACO TSP Path Same: 1702.00 (89 edges)
ACO TSP Path Tuned: 1711.00 (89 edges)
ACO MST Same: 1392.00 (89 edges)
ACO MST Tuned: 1978.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1715.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1694.00 (89 edges)
ACO MST_Deg3_Same: 1430.00 (89 edges)
ACO MST_Deg3_Tuned: 2061.00 (89 edges)
Dataset 4:
Kruskal MST: 1420.00 (89 edges)
ACO TSP Path Same: 1708.00 (89 edges)
ACO TSP Path Tuned: 1785.00 (89 edges)
ACO MST Same: 1470.00 (89 edges)
ACO MST Tuned: 2097.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1790.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1776.00 (89 edges)
ACO MST_Deg3_Same: 1494.00 (89 edges)
ACO MST_Deg3_Tuned: 2073.00 (89 edges)
Dataset 5:
Kruskal MST: 1380.00 (89 edges)
ACO TSP Path Same: 1694.00 (89 edges)
ACO TSP Path Tuned: 1718.00 (89 edges)
ACO MST Same: 1411.00 (89 edges)
ACO MST Tuned: 2082.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1724.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1720.00 (89 edges)
ACO MST_Deg3_Same: 1457.00 (89 edges)
ACO MST_Deg3_Tuned: 2044.00 (89 edges)
Dataset 6:
Kruskal MST: 1411.00 (89 edges)
ACO TSP Path Same: 1689.00 (89 edges)
ACO TSP Path Tuned: 1700.00 (89 edges)
ACO MST Same: 1441.00 (89 edges)
ACO MST Tuned: 2129.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1709.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1707.00 (89 edges)
ACO MST_Deg3_Same: 1474.00 (89 edges)
ACO MST_Deg3_Tuned: 1978.00 (89 edges)
Dataset 7:
Kruskal MST: 1305.00 (89 edges)
ACO TSP Path Same: 1589.00 (89 edges)
ACO TSP Path Tuned: 1631.00 (89 edges)
ACO MST Same: 1325.00 (89 edges)
ACO MST Tuned: 1801.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1607.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1614.00 (89 edges)
ACO MST_Deg3_Same: 1359.00 (89 edges)
ACO MST_Deg3_Tuned: 1908.00 (89 edges)
Dataset 8:
Kruskal MST: 1346.00 (89 edges)
ACO TSP Path Same: 1641.00 (89 edges)
ACO TSP Path Tuned: 1642.00 (89 edges)
ACO MST Same: 1375.00 (89 edges)
ACO MST Tuned: 2002.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1642.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1632.00 (89 edges)
ACO MST_Deg3_Same: 1405.00 (89 edges)
ACO MST_Deg3_Tuned: 1930.00 (89 edges)
Dataset 9:
Kruskal MST: 1388.00 (89 edges)
ACO TSP Path Same: 1688.00 (89 edges)
ACO TSP Path Tuned: 1720.00 (89 edges)
ACO MST Same: 1407.00 (89 edges)
ACO MST Tuned: 1988.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1740.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1717.00 (89 edges)
ACO MST_Deg3_Same: 1463.00 (89 edges)
ACO MST_Deg3_Tuned: 1962.00 (89 edges)
Dataset 10:
Kruskal MST: 1385.00 (89 edges)
ACO TSP Path Same: 1681.00 (89 edges)
ACO TSP Path Tuned: 1681.00 (89 edges)
ACO MST Same: 1428.00 (89 edges)
ACO MST Tuned: 1919.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1653.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1647.00 (89 edges)
ACO MST_Deg3_Same: 1460.00 (89 edges)
ACO MST_Deg3_Tuned: 1981.00 (89 edges)
Dataset 11:
Kruskal MST: 1385.00 (89 edges)
ACO TSP Path Same: 1678.00 (89 edges)
ACO TSP Path Tuned: 1706.00 (89 edges)
ACO MST Same: 1422.00 (89 edges)
ACO MST Tuned: 2007.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1678.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1659.00 (89 edges)
ACO MST_Deg3_Same: 1457.00 (89 edges)
ACO MST_Deg3_Tuned: 2030.00 (89 edges)
Dataset 12:
Kruskal MST: 1323.00 (89 edges)
ACO TSP Path Same: 1669.00 (89 edges)
ACO TSP Path Tuned: 1674.00 (89 edges)
ACO MST Same: 1360.00 (89 edges)
ACO MST Tuned: 1836.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1689.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1686.00 (89 edges)
ACO MST_Deg3_Same: 1383.00 (89 edges)
ACO MST_Deg3_Tuned: 2035.00 (89 edges)
Dataset 13:
Kruskal MST: 1374.00 (89 edges)
ACO TSP Path Same: 1679.00 (89 edges)
ACO TSP Path Tuned: 1721.00 (89 edges)
ACO MST Same: 1393.00 (89 edges)
ACO MST Tuned: 1938.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1705.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1723.00 (89 edges)
ACO MST_Deg3_Same: 1443.00 (89 edges)
ACO MST_Deg3_Tuned: 1985.00 (89 edges)
Dataset 14:
Kruskal MST: 1331.00 (89 edges)
ACO TSP Path Same: 1619.00 (89 edges)
ACO TSP Path Tuned: 1651.00 (89 edges)
ACO MST Same: 1353.00 (89 edges)
ACO MST Tuned: 1965.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1640.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1632.00 (89 edges)
ACO MST_Deg3_Same: 1392.00 (89 edges)
ACO MST_Deg3_Tuned: 1846.00 (89 edges)
Dataset 15:
Kruskal MST: 1385.00 (89 edges)
ACO TSP Path Same: 1717.00 (89 edges)
ACO TSP Path Tuned: 1711.00 (89 edges)
ACO MST Same: 1430.00 (89 edges)
ACO MST Tuned: 2014.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1667.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1731.00 (89 edges)
ACO MST_Deg3_Same: 1452.00 (89 edges)
ACO MST_Deg3_Tuned: 2073.00 (89 edges)
Dataset 16:
Kruskal MST: 1336.00 (89 edges)
ACO TSP Path Same: 1688.00 (89 edges)
ACO TSP Path Tuned: 1709.00 (89 edges)
ACO MST Same: 1375.00 (89 edges)
ACO MST Tuned: 1914.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1679.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1701.00 (89 edges)
ACO MST_Deg3_Same: 1398.00 (89 edges)
ACO MST_Deg3_Tuned: 1891.00 (89 edges)
Dataset 17:
Kruskal MST: 1395.00 (89 edges)
ACO TSP Path Same: 1734.00 (89 edges)
ACO TSP Path Tuned: 1722.00 (89 edges)
ACO MST Same: 1427.00 (89 edges)
ACO MST Tuned: 2049.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1699.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1738.00 (89 edges)
ACO MST_Deg3_Same: 1470.00 (89 edges)
ACO MST_Deg3_Tuned: 2065.00 (89 edges)
Dataset 18:
Kruskal MST: 1410.00 (89 edges)
ACO TSP Path Same: 1713.00 (89 edges)
ACO TSP Path Tuned: 1740.00 (89 edges)
ACO MST Same: 1439.00 (89 edges)
ACO MST Tuned: 2039.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1733.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1724.00 (89 edges)
ACO MST_Deg3_Same: 1478.00 (89 edges)
ACO MST_Deg3_Tuned: 2085.00 (89 edges)
Dataset 19:
Kruskal MST: 1356.00 (89 edges)
ACO TSP Path Same: 1623.00 (89 edges)
ACO TSP Path Tuned: 1605.00 (89 edges)
ACO MST Same: 1386.00 (89 edges)
ACO MST Tuned: 1989.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1603.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1578.00 (89 edges)
ACO MST_Deg3_Same: 1412.00 (89 edges)
ACO MST_Deg3_Tuned: 1925.00 (89 edges)
Dataset 20:
Kruskal MST: 1387.00 (89 edges)
ACO TSP Path Same: 1706.00 (89 edges)
ACO TSP Path Tuned: 1712.00 (89 edges)
ACO MST Same: 1417.00 (89 edges)
ACO MST Tuned: 1975.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1700.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1734.00 (89 edges)
ACO MST_Deg3_Same: 1456.00 (89 edges)
ACO MST_Deg3_Tuned: 2045.00 (89 edges)
Dataset 21:
Kruskal MST: 1333.00 (89 edges)
ACO TSP Path Same: 1662.00 (89 edges)
ACO TSP Path Tuned: 1663.00 (89 edges)
ACO MST Same: 1372.00 (89 edges)
ACO MST Tuned: 2002.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1659.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1642.00 (89 edges)
ACO MST_Deg3_Same: 1397.00 (89 edges)
ACO MST_Deg3_Tuned: 1954.00 (89 edges)
Dataset 22:
Kruskal MST: 1302.00 (89 edges)
ACO TSP Path Same: 1626.00 (89 edges)
ACO TSP Path Tuned: 1648.00 (89 edges)
ACO MST Same: 1323.00 (89 edges)
ACO MST Tuned: 1925.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1650.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1653.00 (89 edges)
ACO MST_Deg3_Same: 1376.00 (89 edges)
ACO MST_Deg3_Tuned: 1783.00 (89 edges)
Dataset 23:
Kruskal MST: 1293.00 (89 edges)
ACO TSP Path Same: 1669.00 (89 edges)
ACO TSP Path Tuned: 1672.00 (89 edges)
ACO MST Same: 1319.00 (89 edges)
ACO MST Tuned: 1763.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1686.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1669.00 (89 edges)
ACO MST_Deg3_Same: 1396.00 (89 edges)
ACO MST_Deg3_Tuned: 1929.00 (89 edges)
Dataset 24:
Kruskal MST: 1336.00 (89 edges)
ACO TSP Path Same: 1598.00 (89 edges)
ACO TSP Path Tuned: 1599.00 (89 edges)
ACO MST Same: 1361.00 (89 edges)
ACO MST Tuned: 1904.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1579.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1611.00 (89 edges)
ACO MST_Deg3_Same: 1401.00 (89 edges)
ACO MST_Deg3_Tuned: 2005.00 (89 edges)
Dataset 25:
Kruskal MST: 1508.00 (89 edges)
ACO TSP Path Same: 1847.00 (89 edges)
ACO TSP Path Tuned: 1810.00 (89 edges)
ACO MST Same: 1542.00 (89 edges)
ACO MST Tuned: 2098.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1814.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1841.00 (89 edges)
ACO MST_Deg3_Same: 1610.00 (89 edges)
ACO MST_Deg3_Tuned: 2253.00 (89 edges)
Dataset 26:
Kruskal MST: 1373.00 (89 edges)
ACO TSP Path Same: 1714.00 (89 edges)
ACO TSP Path Tuned: 1674.00 (89 edges)
ACO MST Same: 1404.00 (89 edges)
ACO MST Tuned: 1957.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1697.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1664.00 (89 edges)
ACO MST_Deg3_Same: 1455.00 (89 edges)
ACO MST_Deg3_Tuned: 1995.00 (89 edges)
Dataset 27:
Kruskal MST: 1392.00 (89 edges)
ACO TSP Path Same: 1694.00 (89 edges)
ACO TSP Path Tuned: 1701.00 (89 edges)
ACO MST Same: 1422.00 (89 edges)
ACO MST Tuned: 2043.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1708.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1698.00 (89 edges)
ACO MST_Deg3_Same: 1466.00 (89 edges)
ACO MST_Deg3_Tuned: 2070.00 (89 edges)
Dataset 28:
Kruskal MST: 1373.00 (89 edges)
ACO TSP Path Same: 1751.00 (89 edges)
ACO TSP Path Tuned: 1749.00 (89 edges)
ACO MST Same: 1392.00 (89 edges)
ACO MST Tuned: 1964.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1731.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1744.00 (89 edges)
ACO MST_Deg3_Same: 1464.00 (89 edges)
ACO MST_Deg3_Tuned: 2051.00 (89 edges)
Dataset 29:
Kruskal MST: 1347.00 (89 edges)
ACO TSP Path Same: 1695.00 (89 edges)
ACO TSP Path Tuned: 1664.00 (89 edges)
ACO MST Same: 1377.00 (89 edges)
ACO MST Tuned: 1954.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1653.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1666.00 (89 edges)
ACO MST_Deg3_Same: 1426.00 (89 edges)
ACO MST_Deg3_Tuned: 2012.00 (89 edges)
Dataset 30:
Kruskal MST: 1347.00 (89 edges)
ACO TSP Path Same: 1688.00 (89 edges)
ACO TSP Path Tuned: 1691.00 (89 edges)
ACO MST Same: 1370.00 (89 edges)
ACO MST Tuned: 2008.00 (89 edges)
ACO TSP_Path_Deg3_Same: 1666.00 (89 edges)
ACO TSP_Path_Deg3_Tuned: 1668.00 (89 edges)
ACO MST_Deg3_Same: 1415.00 (89 edges)
ACO MST_Deg3_Tuned: 1986.00 (89 edges)
================================================================================
RESULTS TABLE
================================================================================
Dataset Kruskal ACO_TSP_Path_Same ACO_TSP_Path_Tuned ACO_MST_Same ACO_MST_Tuned ACO_TSP_Path_Deg3_Same ACO_TSP_Path_Deg3_Tuned ACO_MST_Deg3_Same ACO_MST_Deg3_Tuned
D1 1388.0 1683.0 1696.0 1416.0 1983.0 1688.0 1710.0 1443.0 1946.0
D2 1352.0 1674.0 1705.0 1389.0 2002.0 1674.0 1669.0 1420.0 2026.0
D3 1352.0 1702.0 1711.0 1392.0 1978.0 1715.0 1694.0 1430.0 2061.0
D4 1420.0 1708.0 1785.0 1470.0 2097.0 1790.0 1776.0 1494.0 2073.0
D5 1380.0 1694.0 1718.0 1411.0 2082.0 1724.0 1720.0 1457.0 2044.0
D6 1411.0 1689.0 1700.0 1441.0 2129.0 1709.0 1707.0 1474.0 1978.0
D7 1305.0 1589.0 1631.0 1325.0 1801.0 1607.0 1614.0 1359.0 1908.0
D8 1346.0 1641.0 1642.0 1375.0 2002.0 1642.0 1632.0 1405.0 1930.0
D9 1388.0 1688.0 1720.0 1407.0 1988.0 1740.0 1717.0 1463.0 1962.0
D10 1385.0 1681.0 1681.0 1428.0 1919.0 1653.0 1647.0 1460.0 1981.0
D11 1385.0 1678.0 1706.0 1422.0 2007.0 1678.0 1659.0 1457.0 2030.0
D12 1323.0 1669.0 1674.0 1360.0 1836.0 1689.0 1686.0 1383.0 2035.0
D13 1374.0 1679.0 1721.0 1393.0 1938.0 1705.0 1723.0 1443.0 1985.0
D14 1331.0 1619.0 1651.0 1353.0 1965.0 1640.0 1632.0 1392.0 1846.0
D15 1385.0 1717.0 1711.0 1430.0 2014.0 1667.0 1731.0 1452.0 2073.0
D16 1336.0 1688.0 1709.0 1375.0 1914.0 1679.0 1701.0 1398.0 1891.0
D17 1395.0 1734.0 1722.0 1427.0 2049.0 1699.0 1738.0 1470.0 2065.0
D18 1410.0 1713.0 1740.0 1439.0 2039.0 1733.0 1724.0 1478.0 2085.0
D19 1356.0 1623.0 1605.0 1386.0 1989.0 1603.0 1578.0 1412.0 1925.0
D20 1387.0 1706.0 1712.0 1417.0 1975.0 1700.0 1734.0 1456.0 2045.0
D21 1333.0 1662.0 1663.0 1372.0 2002.0 1659.0 1642.0 1397.0 1954.0
D22 1302.0 1626.0 1648.0 1323.0 1925.0 1650.0 1653.0 1376.0 1783.0
D23 1293.0 1669.0 1672.0 1319.0 1763.0 1686.0 1669.0 1396.0 1929.0
D24 1336.0 1598.0 1599.0 1361.0 1904.0 1579.0 1611.0 1401.0 2005.0
D25 1508.0 1847.0 1810.0 1542.0 2098.0 1814.0 1841.0 1610.0 2253.0
D26 1373.0 1714.0 1674.0 1404.0 1957.0 1697.0 1664.0 1455.0 1995.0
D27 1392.0 1694.0 1701.0 1422.0 2043.0 1708.0 1698.0 1466.0 2070.0
D28 1373.0 1751.0 1749.0 1392.0 1964.0 1731.0 1744.0 1464.0 2051.0
D29 1347.0 1695.0 1664.0 1377.0 1954.0 1653.0 1666.0 1426.0 2012.0
D30 1347.0 1688.0 1691.0 1370.0 2008.0 1666.0 1668.0 1415.0 1986.0
================================================================================
SUMMARY STATISTICS
================================================================================
Algorithm Mean Std Min Max
Kruskal 1367.100000 41.671213 1293.0 1508.0
ACO_TSP_Path_Same 1683.966667 47.906495 1589.0 1847.0
ACO_TSP_Path_Tuned 1693.700000 45.470980 1599.0 1810.0
ACO_MST_Same 1397.933333 44.591429 1319.0 1542.0
ACO_MST_Tuned 1977.500000 80.981376 1763.0 2129.0
ACO_TSP_Path_Deg3_Same 1685.933333 49.112071 1579.0 1814.0
ACO_TSP_Path_Deg3_Tuned 1688.266667 52.950879 1578.0 1841.0
ACO_MST_Deg3_Same 1438.400000 46.637324 1359.0 1610.0
ACO_MST_Deg3_Tuned 1997.566667 85.357165 1783.0 2253.0
================================================================================
β
FAIR COMPARISON ANALYSIS (n-1 edges)
================================================================================
Edge Count: n-1 = 89 edges
1. Kruskal (Optimal): 1367.10
2. ACO TSP Path: 1683.97
3. ACO MST: 1397.93
Gap from Optimal:
TSP Path vs Kruskal: +23.18%
MST vs Kruskal: +2.26%
β
Fair comparison karena:
β’ Same edge count: 89 edges
β’ No cycle: TSP Path & MST both are paths/trees
β’ Apple-to-apple: Both connect all nodes without cycle
================================================================================
VISUALIZING FIRST DATASET RESULTS
================================================================================
1. Visualizing Complete Graph...
2. Visualizing Kruskal MST...
3. Visualizing ACO TSP Path...
4. Visualizing ACO MST...
5. Creating comparison plots...
================================================================================ β COMPLETED! ================================================================================ Files saved to 'results/' folder: π fair_aco_results.csv - Numerical results π fair_comparison.png - Comparison plots π complete_graph.png - Full graph visualization π³ kruskal_mst.png - Kruskal MST result π€οΈ aco_tsp_path.png - ACO TSP Path result π² aco_mst.png - ACO MST result π‘ KEY FINDINGS: β’ All methods use n-1 = 89 edges (FAIR!) β’ TSP Path: NO cycle (like MST) β’ Kruskal: 1367.10 (optimal) β’ ACO TSP Path: 1683.97 (+23.18%) β’ ACO MST: 1397.93 (+2.26%)
InΒ [Β ]: