From 7556d7281871ede083869cdd4098eebd3c392c8f Mon Sep 17 00:00:00 2001 From: reinterpretcat Date: Wed, 26 Jun 2024 21:39:28 +0200 Subject: [PATCH] Add further improvements --- .../benches/general_benchmark.rs | 15 ++++---- vrp-core/examples/cvrp.rs | 5 +++ vrp-core/src/lib.rs | 21 ++++++------ vrp-core/src/models/domain.rs | 9 ++++- vrp-core/src/solver/mod.rs | 34 ------------------- 5 files changed, 32 insertions(+), 52 deletions(-) diff --git a/examples/json-pragmatic/benches/general_benchmark.rs b/examples/json-pragmatic/benches/general_benchmark.rs index 3e7710dc8..8ffeb77dd 100644 --- a/examples/json-pragmatic/benches/general_benchmark.rs +++ b/examples/json-pragmatic/benches/general_benchmark.rs @@ -3,12 +3,10 @@ use std::fs::File; use std::io::BufReader; use std::sync::Arc; use vrp_pragmatic::core::construction::heuristics::InsertionContext; -use vrp_pragmatic::core::models::Solution; -use vrp_pragmatic::core::prelude::{create_default_config_builder, Problem, Solver}; +use vrp_pragmatic::core::prelude::*; use vrp_pragmatic::core::rosomaxa::evolution::TelemetryMode; use vrp_pragmatic::core::solver::search::{Recreate, RecreateWithCheapest}; use vrp_pragmatic::core::solver::{create_elitism_population, RefinementContext}; -use vrp_pragmatic::core::utils::Environment; use vrp_pragmatic::format::problem::PragmaticProblem; fn get_problem(problem_path: &str) -> Arc { @@ -20,17 +18,20 @@ fn get_problem(problem_path: &str) -> Arc { ) } -/// Runs solver with specific amount of generations. It involves some non-determenism. +/// Runs solver with specific number of generations. It involves some non-determenism. fn solve_problem_with_max_generations(problem_path: &str, generations: usize) -> Solution { let problem = get_problem(problem_path); - create_default_config_builder(problem.clone(), Arc::new(Environment::default()), TelemetryMode::None) + VrpConfigBuilder::new(problem.clone()) + .set_telemetry_mode(TelemetryMode::None) + .prebuild() + .expect("cannot prebuild configuration") .with_max_generations(Some(generations)) .build() .map(|config| Solver::new(problem, config)) - .unwrap_or_else(|err| panic!("cannot build solver: {}", err)) + .expect("cannot build solver") .solve() - .unwrap_or_else(|err| panic!("cannot solver problem: {}", err)) + .expect("cannot solver problem: {}") } /// Solve problem using cheapest insertion heuristic and returns one solution. diff --git a/vrp-core/examples/cvrp.rs b/vrp-core/examples/cvrp.rs index 9a8b0996b..3d56be6f3 100644 --- a/vrp-core/examples/cvrp.rs +++ b/vrp-core/examples/cvrp.rs @@ -105,5 +105,10 @@ fn main() -> GenericResult<()> { assert_eq!(solution.routes.len(), 2, "two tours are expected"); assert_eq!(solution.cost, 2135., "unexpected cost (total distance traveled)"); + println!( + "\nIn solution, locations are visited in the following order:\n{:?}\n", + solution.get_locations().map(Iterator::collect::>).collect::>() + ); + Ok(()) } diff --git a/vrp-core/src/lib.rs b/vrp-core/src/lib.rs index 5b25eab34..6379bb3a1 100644 --- a/vrp-core/src/lib.rs +++ b/vrp-core/src/lib.rs @@ -70,24 +70,25 @@ //! //! # Examples //! -//! The most simple way to run solver is to use `Builder`. You can tweak metaheuristic parameters by -//! calling corresponding methods of the builder instance: +//! Detailed examples for some of the VRP variants can be found in `examples` folder. +//! +//! Here, the example shows how to construct default configuration for the solver, override some +//! of the default metaheuristic parameters using fluent interface methods, and run the solver: //! //! ``` //! # use vrp_core::models::examples::create_example_problem; -//! # use vrp_core::solver::get_default_telemetry_mode; //! # use std::sync::Arc; //! use vrp_core::prelude::*; //! //! // create your VRP problem -//! let problem = create_example_problem(); -//! let environment = Arc::new(Environment::new_with_time_quota(Some(10))); -//! let telemetry_mode = get_default_telemetry_mode(environment.logger.clone()); -//! // build solver config to run 10 secs or 1000 generation -//! let config = create_default_config_builder(problem.clone(), environment, telemetry_mode) -//! .with_max_time(Some(10)) -//! .with_max_generations(Some(10)) +//! let problem: Arc = create_example_problem(); +//! // build solver config using pre-build builder with defaults and then override some parameters +//! let config = VrpConfigBuilder::new(problem.clone()) +//! .prebuild()? +//! .with_max_time(Some(60)) +//! .with_max_generations(Some(100)) //! .build()?; +//! //! // run solver and get the best known solution. //! let solution = Solver::new(problem, config).solve()?; //! diff --git a/vrp-core/src/models/domain.rs b/vrp-core/src/models/domain.rs index 0aee0eaf6..012fe4787 100644 --- a/vrp-core/src/models/domain.rs +++ b/vrp-core/src/models/domain.rs @@ -1,5 +1,5 @@ use crate::construction::heuristics::UnassignmentInfo; -use crate::models::common::Cost; +use crate::models::common::{Cost, Location}; use crate::models::problem::*; use crate::models::solution::{Registry, Route}; use crate::models::*; @@ -239,3 +239,10 @@ impl ProblemBuilder { Ok(Problem { fleet, jobs, locks: vec![], goal, activity, transport, extras }) } } + +impl Solution { + /// Iterates through all tours and returns locations of each activity in the order they are visited. + pub fn get_locations(&self) -> impl Iterator + '_> + '_ { + self.routes.iter().map(|route| route.tour.all_activities().map(|activity| activity.place.location)) + } +} diff --git a/vrp-core/src/solver/mod.rs b/vrp-core/src/solver/mod.rs index b48a7f3be..9a6116ec8 100644 --- a/vrp-core/src/solver/mod.rs +++ b/vrp-core/src/solver/mod.rs @@ -216,40 +216,6 @@ impl InitialOperator for RecreateInitialOperator { /// Solves a Vehicle Routing Problem and returns a _(solution, its cost)_ pair in case of success /// or error description, if solution cannot be found. -/// -/// A newly created builder instance is pre-configured with some reasonable defaults for mid-size -/// problems (~200), so there is no need to call any of its methods. -/// -/// -/// # Examples -/// -/// This example shows how to construct default configuration for the solver, override some of default -/// metaheuristic parameters using fluent interface methods, and run the solver: -/// -/// ``` -/// # use vrp_core::models::examples::create_example_problem; -/// # use vrp_core::solver::get_default_telemetry_mode; -/// # use std::sync::Arc; -/// use vrp_core::prelude::*; -/// -/// // create your VRP problem -/// let problem: Arc = create_example_problem(); -/// let environment = Arc::new(Environment::new_with_time_quota(Some(60))); -/// let telemetry_mode = get_default_telemetry_mode(environment.logger.clone()); -/// // build solver config using pre-build builder with defaults and then override some parameters -/// let config = create_default_config_builder(problem.clone(), environment, telemetry_mode) -/// .with_max_time(Some(60)) -/// .with_max_generations(Some(100)) -/// .build()?; -/// -/// // run solver and get the best known solution. -/// let solution = Solver::new(problem, config).solve()?; -/// -/// assert_eq!(solution.cost, 42.); -/// assert_eq!(solution.routes.len(), 1); -/// assert_eq!(solution.unassigned.len(), 0); -/// # Ok::<(), GenericError>(()) -/// ``` pub struct Solver { problem: Arc, config: EvolutionConfig,