Skip to content

Commit

Permalink
Use tuple struct for state keys
Browse files Browse the repository at this point in the history
  • Loading branch information
reinterpretcat committed Dec 13, 2023
1 parent 0c66ddf commit bbcb1ed
Show file tree
Hide file tree
Showing 26 changed files with 122 additions and 121 deletions.
3 changes: 1 addition & 2 deletions vrp-core/src/construction/enablers/departure_time.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,9 @@ mod departure_time_test;

use crate::construction::enablers::{update_route_departure, ScheduleStateKeys};
use crate::construction::features::*;
use crate::construction::heuristics::RouteContext;
use crate::construction::heuristics::{RouteContext, StateKey};
use crate::models::common::Timestamp;
use crate::models::problem::{ActivityCost, TransportCost, TravelTime};
use crate::models::StateKey;
use rosomaxa::prelude::compare_floats;
use std::cmp::Ordering;

Expand Down
2 changes: 1 addition & 1 deletion vrp-core/src/construction/enablers/feature_combinator.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
//! This module provides some helper functionality to combine and use multiple features together.
use crate::construction::heuristics::{MoveContext, RouteContext, SolutionContext};
use crate::construction::heuristics::*;
use crate::models::problem::Job;
use crate::models::*;
use rosomaxa::prelude::*;
Expand Down
5 changes: 2 additions & 3 deletions vrp-core/src/construction/enablers/route_intervals.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::construction::heuristics::{RouteContext, SolutionContext};
use crate::construction::heuristics::{RouteContext, SolutionContext, StateKey};
use crate::models::problem::{Job, Single};
use crate::models::solution::{Activity, Route};
use crate::models::StateKey;
use crate::utils::Either;
use hashbrown::HashSet;
use std::iter::once;
Expand Down Expand Up @@ -93,7 +92,7 @@ impl RouteIntervals for FixedRouteIntervals {
.and_then(|state_code| route_ctx.state().get_route_state::<Vec<(usize, usize)>>(state_code))
}

fn get_interval_key(&self) -> Option<i32> {
fn get_interval_key(&self) -> Option<StateKey> {
Some(self.intervals_key)
}

Expand Down
3 changes: 1 addition & 2 deletions vrp-core/src/construction/enablers/schedule_update.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use crate::construction::heuristics::RouteContext;
use crate::construction::heuristics::{RouteContext, StateKey};
use crate::models::common::{Distance, Schedule, Timestamp};
use crate::models::problem::{ActivityCost, TransportCost, TravelTime};
use crate::models::StateKey;
use crate::models::OP_START_MSG;

/// Contains state keys ids used by route schedule updating logic.
Expand Down
32 changes: 16 additions & 16 deletions vrp-core/src/construction/features/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,36 +45,36 @@ mod work_balance;
pub use self::work_balance::*;

/// A key which tracks latest arrival.
pub const LATEST_ARRIVAL_KEY: StateKey = 1;
pub const LATEST_ARRIVAL_KEY: StateKey = StateKey(1);
/// A key which tracks waiting time.
pub const WAITING_KEY: StateKey = 2;
pub const WAITING_KEY: StateKey = StateKey(2);
/// A key which tracks total distance.
pub const TOTAL_DISTANCE_KEY: StateKey = 3;
pub const TOTAL_DISTANCE_KEY: StateKey = StateKey(3);
/// A key which tracks total duration.
pub const TOTAL_DURATION_KEY: StateKey = 4;
pub const TOTAL_DURATION_KEY: StateKey = StateKey(4);
/// A key which tracks global duration limit.
pub const LIMIT_DURATION_KEY: StateKey = 5;
pub const LIMIT_DURATION_KEY: StateKey = StateKey(5);

/// A key which tracks current vehicle capacity.
pub const CURRENT_CAPACITY_KEY: StateKey = 11;
pub const CURRENT_CAPACITY_KEY: StateKey = StateKey(11);
/// A key which tracks maximum vehicle capacity ahead in route.
pub const MAX_FUTURE_CAPACITY_KEY: StateKey = 12;
pub const MAX_FUTURE_CAPACITY_KEY: StateKey = StateKey(12);
/// A key which tracks maximum capacity backward in route.
pub const MAX_PAST_CAPACITY_KEY: StateKey = 13;
pub const MAX_PAST_CAPACITY_KEY: StateKey = StateKey(13);
/// A key which tracks reload intervals.
pub const RELOAD_INTERVALS_KEY: StateKey = 14;
pub const RELOAD_INTERVALS_KEY: StateKey = StateKey(14);
/// A key which tracks max load in tour.
pub const MAX_LOAD_KEY: StateKey = 15;
pub const MAX_LOAD_KEY: StateKey = StateKey(15);
/// A key which tracks recharge intervals.
pub const RECHARGE_INTERVALS_KEY: StateKey = 16;
pub const RECHARGE_INTERVALS_KEY: StateKey = StateKey(16);
/// A key to track recharge distance.
pub const RECHARGE_DISTANCE_KEY: StateKey = 17;
pub const RECHARGE_DISTANCE_KEY: StateKey = StateKey(17);

/// A key for balancing max load.
pub const BALANCE_MAX_LOAD_KEY: StateKey = 20;
pub const BALANCE_MAX_LOAD_KEY: StateKey = StateKey(20);
/// A key for balancing activities.
pub const BALANCE_ACTIVITY_KEY: StateKey = 21;
pub const BALANCE_ACTIVITY_KEY: StateKey = StateKey(21);
/// A key for balancing distance.
pub const BALANCE_DISTANCE_KEY: StateKey = 22;
pub const BALANCE_DISTANCE_KEY: StateKey = StateKey(22);
/// A key for balancing duration.
pub const BALANCE_DURATION_KEY: StateKey = 23;
pub const BALANCE_DURATION_KEY: StateKey = StateKey(23);
4 changes: 2 additions & 2 deletions vrp-core/src/construction/features/work_balance.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,8 +75,8 @@ pub fn create_distance_balanced_feature(name: &str, threshold: Option<f64>) -> R
fn create_transport_balanced_feature(
name: &str,
threshold: Option<f64>,
value_key: i32,
state_key: i32,
value_key: StateKey,
state_key: StateKey,
) -> Result<Feature, GenericError> {
let route_estimate_fn = Arc::new(move |route_ctx: &RouteContext| {
route_ctx.state().get_route_state::<f64>(value_key).cloned().unwrap_or(0.)
Expand Down
73 changes: 39 additions & 34 deletions vrp-core/src/construction/heuristics/context.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,7 +85,11 @@ impl Debug for InsertionContext {
}
}

/// A any state value.
/// A state key used to retrieve state values associated with a specific activity or with the whole route.
#[derive(Clone, Copy, Debug, Eq, PartialEq, Hash)]
pub struct StateKey(pub usize);

/// A state value which can be anything.
pub type StateValue = Arc<dyn Any + Send + Sync>;

/// Keeps information about unassigned reason code.
Expand Down Expand Up @@ -120,7 +124,7 @@ pub struct SolutionContext {
pub registry: RegistryContext,

/// A collection of data associated with solution.
pub state: HashMap<i32, StateValue>,
pub state: HashMap<StateKey, StateValue>,
}

impl SolutionContext {
Expand Down Expand Up @@ -233,10 +237,10 @@ pub struct RouteContext {
/// NOTE: do not put any state which is not refreshed after `accept_route_state` call: it will be
/// wiped out at some point.
pub struct RouteState {
route_states: HashMap<i32, StateValue, BuildNoHashHasher<i32>>,
route_states: HashMap<usize, StateValue, BuildNoHashHasher<usize>>,
activity_states: HashMap<ActivityWithKey, StateValue, BuildHasherDefault<FxHasher>>,
route_keys: HashSet<i32, BuildNoHashHasher<i32>>,
activity_keys: HashSet<i32, BuildNoHashHasher<i32>>,
route_keys: HashSet<usize, BuildNoHashHasher<usize>>,
activity_keys: HashSet<usize, BuildNoHashHasher<usize>>,
flags: u8,
}

Expand Down Expand Up @@ -331,10 +335,10 @@ impl Debug for RouteContext {
impl Default for RouteState {
fn default() -> RouteState {
RouteState {
route_states: HashMap::with_capacity_and_hasher(2, BuildNoHashHasher::<i32>::default()),
route_states: HashMap::with_capacity_and_hasher(2, BuildNoHashHasher::<usize>::default()),
activity_states: HashMap::with_capacity_and_hasher(4, BuildHasherDefault::<FxHasher>::default()),
route_keys: HashSet::with_capacity_and_hasher(2, BuildNoHashHasher::<i32>::default()),
activity_keys: HashSet::with_capacity_and_hasher(4, BuildNoHashHasher::<i32>::default()),
route_keys: HashSet::with_capacity_and_hasher(2, BuildNoHashHasher::<usize>::default()),
activity_keys: HashSet::with_capacity_and_hasher(4, BuildNoHashHasher::<usize>::default()),
flags: state_flags::NO_FLAGS,
}
}
Expand All @@ -352,7 +356,7 @@ impl RouteState {
(0..total_activities).for_each(|activity_idx| {
other.all_activity_keys().for_each(|key| {
if let Some(value) = other.get_activity_state_raw(key, activity_idx) {
activity_states.insert((activity_idx, key), value.clone());
activity_states.insert((activity_idx, key.0), value.clone());
}
});
});
Expand All @@ -361,57 +365,57 @@ impl RouteState {
}

/// Gets value associated with key converted to given type.
pub fn get_route_state<T: Send + Sync + 'static>(&self, key: i32) -> Option<&T> {
self.route_states.get(&key).and_then(|s| s.downcast_ref::<T>())
pub fn get_route_state<T: Send + Sync + 'static>(&self, key: StateKey) -> Option<&T> {
self.route_states.get(&key.0).and_then(|s| s.downcast_ref::<T>())
}

/// Gets value associated with key.
pub fn get_route_state_raw(&self, key: i32) -> Option<&StateValue> {
self.route_states.get(&key)
pub fn get_route_state_raw(&self, key: StateKey) -> Option<&StateValue> {
self.route_states.get(&key.0)
}

/// Gets value associated with key converted to given type.
pub fn get_activity_state<T: Send + Sync + 'static>(&self, key: i32, activity_idx: usize) -> Option<&T> {
self.activity_states.get(&(activity_idx, key)).and_then(|s| s.downcast_ref::<T>())
pub fn get_activity_state<T: Send + Sync + 'static>(&self, key: StateKey, activity_idx: usize) -> Option<&T> {
self.activity_states.get(&(activity_idx, key.0)).and_then(|s| s.downcast_ref::<T>())
}

/// Gets value associated with key.
pub fn get_activity_state_raw(&self, key: i32, activity_idx: usize) -> Option<&StateValue> {
self.activity_states.get(&(activity_idx, key))
pub fn get_activity_state_raw(&self, key: StateKey, activity_idx: usize) -> Option<&StateValue> {
self.activity_states.get(&(activity_idx, key.0))
}

/// Puts value associated with key.
pub fn put_route_state<T: Send + Sync + 'static>(&mut self, key: i32, value: T) {
self.route_states.insert(key, Arc::new(value));
self.route_keys.insert(key);
pub fn put_route_state<T: Send + Sync + 'static>(&mut self, key: StateKey, value: T) {
self.route_states.insert(key.0, Arc::new(value));
self.route_keys.insert(key.0);
}

/// Puts value associated with key.
pub fn put_route_state_raw(&mut self, key: i32, value: Arc<dyn Any + Send + Sync>) {
self.route_states.insert(key, value);
self.route_keys.insert(key);
pub fn put_route_state_raw(&mut self, key: StateKey, value: Arc<dyn Any + Send + Sync>) {
self.route_states.insert(key.0, value);
self.route_keys.insert(key.0);
}

/// Puts value associated with key and specific activity.
pub fn put_activity_state<T: Send + Sync + 'static>(&mut self, key: i32, activity_idx: usize, value: T) {
self.activity_states.insert((activity_idx, key), Arc::new(value));
self.activity_keys.insert(key);
pub fn put_activity_state<T: Send + Sync + 'static>(&mut self, key: StateKey, activity_idx: usize, value: T) {
self.activity_states.insert((activity_idx, key.0), Arc::new(value));
self.activity_keys.insert(key.0);
}

/// Puts value associated with key and specific activity.
pub fn put_activity_state_raw(&mut self, key: i32, activity_idx: usize, value: StateValue) {
self.activity_states.insert((activity_idx, key), value);
self.activity_keys.insert(key);
pub fn put_activity_state_raw(&mut self, key: StateKey, activity_idx: usize, value: StateValue) {
self.activity_states.insert((activity_idx, key.0), value);
self.activity_keys.insert(key.0);
}

/// Returns all activity state keys.
pub fn all_activity_keys(&'_ self) -> impl Iterator<Item = i32> + '_ {
self.activity_keys.iter().cloned()
pub fn all_activity_keys(&'_ self) -> impl Iterator<Item = StateKey> + '_ {
self.activity_keys.iter().copied().map(StateKey)
}

/// Returns all route state keys.
pub fn all_route_keys(&'_ self) -> impl Iterator<Item = i32> + '_ {
self.route_keys.iter().cloned()
pub fn all_route_keys(&'_ self) -> impl Iterator<Item = StateKey> + '_ {
self.route_keys.iter().copied().map(StateKey)
}

/// Returns size route state storage.
Expand Down Expand Up @@ -567,7 +571,8 @@ pub struct ActivityContext<'a> {
pub next: Option<&'a Activity>,
}

type ActivityWithKey = (usize, i32);
/// An internal hash map key represented as `(activity_idx, state_key)`.
type ActivityWithKey = (usize, usize);

/// A local move context.
pub enum MoveContext<'a> {
Expand Down
8 changes: 5 additions & 3 deletions vrp-core/src/construction/heuristics/metrics.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,8 @@
#[path = "../../../tests/unit/construction/heuristics/metrics_test.rs"]
mod metrics_test;

use super::InsertionContext;
use crate::construction::features::*;
use crate::construction::heuristics::RouteContext;
use crate::construction::heuristics::{InsertionContext, RouteContext, StateKey};
use crate::models::problem::{TransportCost, TravelTime};
use rosomaxa::algorithms::math::*;
use rosomaxa::prelude::*;
Expand Down Expand Up @@ -207,7 +206,10 @@ pub fn group_routes_by_proximity(insertion_ctx: &InsertionContext) -> RouteProxi
)
}

fn get_values_from_route_state(insertion_ctx: &InsertionContext, state_key: i32) -> impl Iterator<Item = f64> + '_ {
fn get_values_from_route_state(
insertion_ctx: &InsertionContext,
state_key: StateKey,
) -> impl Iterator<Item = f64> + '_ {
insertion_ctx
.solution
.routes
Expand Down
3 changes: 0 additions & 3 deletions vrp-core/src/models/goal.rs
Original file line number Diff line number Diff line change
Expand Up @@ -263,9 +263,6 @@ impl ConstraintViolation {
/// Specifies a type for constraint violation code.
pub type ViolationCode = i32;

/// Specifies a type for state key.
pub type StateKey = i32;

/// Provides a way to build feature with some checks.
#[derive(Default)]
pub struct FeatureBuilder(Feature);
Expand Down
10 changes: 5 additions & 5 deletions vrp-core/src/solver/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,8 +87,8 @@
extern crate rand;

use crate::construction::heuristics::InsertionContext;
use crate::models::{GoalContext, Problem, Solution, StateKey};
use crate::construction::heuristics::{InsertionContext, StateKey};
use crate::models::{GoalContext, Problem, Solution};
use crate::solver::search::Recreate;
use hashbrown::HashMap;
use rosomaxa::evolution::*;
Expand All @@ -107,11 +107,11 @@ pub mod search;
mod heuristic;

/// A key to store tabu list.
const TABU_LIST_KEY: StateKey = 1;
const TABU_LIST_KEY: StateKey = StateKey(1);
/// A key to store solution order information.
const SOLUTION_ORDER_KEY: StateKey = 2;
const SOLUTION_ORDER_KEY: StateKey = StateKey(2);
/// A key to store solution weights information.
const SOLUTION_WEIGHTS_KEY: StateKey = 3;
const SOLUTION_WEIGHTS_KEY: StateKey = StateKey(3);

/// A type which encapsulates information needed to perform solution refinement process.
pub struct RefinementContext {
Expand Down
6 changes: 3 additions & 3 deletions vrp-core/tests/helpers/models/solution/route.rs
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
use crate::construction::heuristics::{RouteContext, RouteState};
use crate::construction::heuristics::{RouteContext, RouteState, StateKey};
use crate::helpers::models::problem::*;
use crate::helpers::models::solution::test_actor;
use crate::models::common::{Duration, Location, Schedule, TimeWindow};
Expand Down Expand Up @@ -105,15 +105,15 @@ pub struct RouteStateBuilder {
impl RouteStateBuilder {
pub fn add_activity_state<T: Send + Sync + 'static>(
&mut self,
key: i32,
key: StateKey,
activity_idx: usize,
value: T,
) -> &mut Self {
self.state.put_activity_state(key, activity_idx, value);
self
}

pub fn add_route_state<T: Send + Sync + 'static>(&mut self, key: i32, value: T) -> &mut Self {
pub fn add_route_state<T: Send + Sync + 'static>(&mut self, key: StateKey, value: T) -> &mut Self {
self.state.put_route_state(key, value);
self
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ fn create_feature_and_route(
(create_reserved_times_fn(reserved_times_idx).unwrap(), feature, route_ctx)
}

fn get_activity_states(route_ctx: &RouteContext, key: i32) -> Vec<Option<f64>> {
fn get_activity_states(route_ctx: &RouteContext, key: StateKey) -> Vec<Option<f64>> {
(0..route_ctx.route().tour.total())
.map(|activity_idx| route_ctx.state().get_activity_state::<f64>(key, activity_idx).cloned())
.collect()
Expand Down
5 changes: 2 additions & 3 deletions vrp-core/tests/unit/construction/features/capacity_test.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ use crate::models::common::{Demand, DemandDimension, SingleDimLoad};
use crate::models::problem::{Job, Vehicle};
use crate::models::solution::Activity;

const STATE_KEY: StateKey = 2;
const VIOLATION_CODE: ViolationCode = 2;

fn create_feature() -> Feature {
create_capacity_limit_feature::<SingleDimLoad>("capacity", STATE_KEY).unwrap()
create_capacity_limit_feature::<SingleDimLoad>("capacity", VIOLATION_CODE).unwrap()
}

fn create_test_vehicle(capacity: i32) -> Vehicle {
Expand All @@ -28,7 +27,7 @@ fn create_activity_with_simple_demand(size: i32) -> Activity {
ActivityBuilder::default().job(Some(job)).build()
}

fn get_simple_capacity_state(key: i32, state: &RouteState, activity_idx: Option<usize>) -> i32 {
fn get_simple_capacity_state(key: StateKey, state: &RouteState, activity_idx: Option<usize>) -> i32 {
state.get_activity_state::<SingleDimLoad>(key, activity_idx.unwrap()).expect("expect single capacity").value
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use crate::construction::enablers::NoRouteIntervals;
use crate::helpers::models::problem::*;
use crate::helpers::models::solution::*;

const STATE_KEY: StateKey = 2;
const STATE_KEY: StateKey = StateKey(2);

fn create_test_feature(route_intervals: Arc<dyn RouteIntervals + Send + Sync>) -> Feature {
create_fast_service_feature::<SingleDimLoad>(
Expand Down Expand Up @@ -175,7 +175,7 @@ mod global_estimation {

#[test]
fn can_get_solution_fitness_with_reload() {
const STATE_KEY: StateKey = 0;
const STATE_KEY: StateKey = StateKey(0);
const INTERVAL_LOCATION: Location = 15;

struct FakeRouteIntervals;
Expand Down
Loading

0 comments on commit bbcb1ed

Please sign in to comment.