use itertools::Itertools; use crate::{algorithms::{Dinic, EdmondsKarp, FordFulkerson, GoldbergTarjan, MaxflowAlgorithm, MaxflowAlgorithmEnum}, random_generator::MaxflowProblem, graph::FlowGraph}; use std::time::{Instant}; fn solve_problem_all_algos(problem: &MaxflowProblem) -> (f64, f64, f64, f64) { let ff = FordFulkerson::from_problem(&problem); let ek = EdmondsKarp::from_problem(&problem); let di = Dinic::from_problem(&problem); let gt = GoldbergTarjan::from_problem(&problem); let mut instances:Vec = vec![ff.into(), ek.into(), di.into(), gt.into()]; let mut durations = vec![0.0; 4]; for (i,a) in instances.iter_mut().enumerate() { let now = Instant::now(); match a { MaxflowAlgorithmEnum::GoldbergTarjan(_) => { a.run(); }, _ => { a.run(); } } //a.run(); durations[i] = now.elapsed().as_secs_f64(); // check if the flow is valid assert!(a.graph().valid_flow(problem.s, problem.t), "invalid flow"); } // check if all algorithms return the same total flow let total_flows: Vec = instances.iter_mut().map(|x| x.graph().total_flow(problem.s, problem.t)).collect(); println!("total flows: {:?}", total_flows); assert!(total_flows.iter().all(|&x| x == total_flows[0]), "algorithms return different total flows"); return durations.into_iter().collect_tuple().unwrap(); } fn run_tests(test_tuples: Vec<(u64, u64, u64)>) -> String { let mut response = String::new(); for (problem_count, nodes, capacity) in test_tuples { response += format!("=== Testing with problem_count={}, nodes={}, capacity={}\n", problem_count, nodes, capacity).as_str(); let mut problems: Vec<_> = Vec::new(); for _ in 0..problem_count { problems.push(MaxflowProblem::new_random_graph(nodes, capacity)); } let mut durations = Vec::new(); for (_, problem) in problems.iter_mut().enumerate() { durations.push(solve_problem_all_algos(problem)); } let d0 = durations.iter().map(|x| x.0).sum::() / problem_count as f64; let d1 = durations.iter().map(|x| x.1).sum::() / problem_count as f64; let d2 = durations.iter().map(|x| x.2).sum::() / problem_count as f64; let d3 = durations.iter().map(|x| x.3).sum::() / problem_count as f64; response += format!("Ford-Fulkerson:\t{:02.8}s\nEdmonds-Karp:\t{:02.8}s\nDinic:\t\t\t\t\t\t{:02.8}s\nGoldberg-Tarjan:\t{:02.8}s\n\n", d0, d1, d2, d3).as_str(); } return response } pub fn run_small_tests() -> String { let test_tuples = [ // (number of problems, number of nodes, max. capacity) (10, 10, 10), (10, 100, 10), (10, 100, 100), (10, 200, 10), (10, 200, 100) ]; return run_tests(test_tuples.into()); } pub fn run_large_tests() -> String { let test_tuples = [ // (number of problems, number of nodes, max. capacity) (10, 100, 10), (10, 100, 100), (10, 100, 1000), (10, 500, 10), (10, 500, 100), (10, 500, 1000), (10, 1000, 10), (10, 1000, 100), (10, 1000, 1000), (10, 10000, 10) ]; return run_tests(test_tuples.into()); }