~ruther/ctu-fee-eoa

381091456ff37887e03f4a75f69304ffbeddb0e3 — Rutherther a month ago 0ec0006
feat: add loading of optimal cost from solutions.txt
1 files changed, 38 insertions(+), 2 deletions(-)

M codes/tsp_hw01/src/main.rs
M codes/tsp_hw01/src/main.rs => codes/tsp_hw01/src/main.rs +38 -2
@@ 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<TSPInstance<Dyn>, Box<dyn std::er
    Ok(TSPInstance::new_dyn(cities))
}

fn load_optimal_cost(instance_filename: &str) -> Result<f64, Box<dyn std::error::Error>> {
    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::<f64>()
                    .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<dyn std::error::Error>> {
    // 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<dyn std::error::Error>> {
        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(())
}