From 381091456ff37887e03f4a75f69304ffbeddb0e3 Mon Sep 17 00:00:00 2001 From: Rutherther Date: Tue, 28 Oct 2025 21:27:19 +0100 Subject: [PATCH] feat: add loading of optimal cost from solutions.txt --- codes/tsp_hw01/src/main.rs | 40 ++++++++++++++++++++++++++++++++++++-- 1 file changed, 38 insertions(+), 2 deletions(-) diff --git a/codes/tsp_hw01/src/main.rs b/codes/tsp_hw01/src/main.rs index 62984b3592da7bc81b4e950d8cc93da8529ceb89..5c3ddb73731776ed150a15df693647887aeb0f54 100644 --- a/codes/tsp_hw01/src/main.rs +++ b/codes/tsp_hw01/src/main.rs @@ -2,7 +2,7 @@ pub mod tsp; pub mod graph; use tsp::{TSPInstance, TSPRandomInitializer, SwapPerturbation}; -use nalgebra::{Const, Dyn}; +use nalgebra::{Const, Dim, Dyn}; use eoa_lib::{ initializer::Initializer, local_search::local_search_first_improving, @@ -56,10 +56,43 @@ fn load_tsp_instance(filename: &str) -> Result, Box Result> { + let instance_name = std::path::Path::new(instance_filename) + .file_stem() + .and_then(|s| s.to_str()) + .ok_or("Could not extract instance name")? + .trim_end_matches(".tsp"); + + let solutions_path = std::path::Path::new(instance_filename) + .parent() + .unwrap_or_else(|| std::path::Path::new(".")) + .join("solutions.txt"); + + let content = std::fs::read_to_string(solutions_path)?; + + for line in content.lines() { + let line = line.trim(); + if let Some(colon_pos) = line.find(':') { + let name = line[..colon_pos].trim(); + if name == instance_name { + let cost_str = line[colon_pos + 1..].trim(); + return cost_str.parse::() + .map_err(|e| format!("Could not parse cost '{}': {}", cost_str, e).into()); + } + } + } + + Err(format!("Optimal cost not found for instance '{}'", instance_name).into()) +} + fn main() -> Result<(), Box> { // Load a TSP instance from file - let instance = load_tsp_instance("instances/berlin52.tsp.gz")?; + let filename = "instances/berlin52.tsp.gz"; + let instance = load_tsp_instance(filename)?; let dimension = instance.dimension(); + let optimal_cost = load_optimal_cost(filename)?; + + println!("Loaded {} with {} cities (optimal cost: {})", filename, dimension.value(), optimal_cost); // Plot just the instance instance.plot("tsp_instance.png")?; @@ -95,6 +128,9 @@ fn main() -> Result<(), Box> { instance.solution_cost(&initial_solution), result.best_candidate.fit, result.cycles); + println!("Gap to optimal: {:.2} ({:.1}%)", + result.best_candidate.fit - optimal_cost, + ((result.best_candidate.fit - optimal_cost) / optimal_cost) * 100.0); Ok(()) }