extern crate rand;
use crate::construction::heuristics::InsertionContext;
use crate::models::{GoalContext, Problem, Solution};
use crate::solver::search::Recreate;
use rosomaxa::evolution::*;
use rosomaxa::prelude::*;
use rosomaxa::{get_default_population, TelemetryHeuristicContext};
use std::any::Any;
use std::collections::HashMap;
use std::sync::Arc;
pub use self::heuristic::*;
use rosomaxa::population::Rosomaxa;
use rosomaxa::utils::Timer;
pub mod processing;
pub mod search;
mod heuristic;
pub struct RefinementContext {
pub problem: Arc<Problem>,
pub environment: Arc<Environment>,
pub state: HashMap<String, Box<dyn Any + Sync + Send>>,
inner_context: TelemetryHeuristicContext<GoalContext, InsertionContext>,
}
#[derive(Clone)]
pub enum RefinementSpeed {
Slow(Float),
Moderate,
}
impl RefinementContext {
pub fn new(
problem: Arc<Problem>,
population: TargetPopulation,
telemetry_mode: TelemetryMode,
environment: Arc<Environment>,
) -> Self {
let inner_context =
TelemetryHeuristicContext::new(problem.goal.clone(), population, telemetry_mode, environment.clone());
Self { problem, environment, inner_context, state: Default::default() }
}
pub fn add_solution(&mut self, solution: InsertionContext) {
self.inner_context.add_solution(solution);
}
}
impl HeuristicContext for RefinementContext {
type Objective = GoalContext;
type Solution = InsertionContext;
fn objective(&self) -> &Self::Objective {
self.inner_context.objective()
}
fn selected<'a>(&'a self) -> Box<dyn Iterator<Item = &Self::Solution> + 'a> {
self.inner_context.selected()
}
fn ranked<'a>(&'a self) -> Box<dyn Iterator<Item = &Self::Solution> + 'a> {
self.inner_context.ranked()
}
fn statistics(&self) -> &HeuristicStatistics {
self.inner_context.statistics()
}
fn selection_phase(&self) -> SelectionPhase {
self.inner_context.selection_phase()
}
fn environment(&self) -> &Environment {
self.inner_context.environment()
}
fn on_initial(&mut self, solution: Self::Solution, item_time: Timer) {
self.inner_context.on_initial(solution, item_time)
}
fn on_generation(&mut self, offspring: Vec<Self::Solution>, termination_estimate: Float, generation_time: Timer) {
self.inner_context.on_generation(offspring, termination_estimate, generation_time)
}
fn on_result(self) -> HeuristicResult<Self::Objective, Self::Solution> {
self.inner_context.on_result()
}
}
impl Stateful for RefinementContext {
type Key = String;
fn set_state<T: 'static + Send + Sync>(&mut self, key: Self::Key, state: T) {
self.state.insert(key, Box::new(state));
}
fn get_state<T: 'static + Send + Sync>(&self, key: &Self::Key) -> Option<&T> {
self.state.get(key).and_then(|v| v.downcast_ref::<T>())
}
fn state_mut<T: 'static + Send + Sync, F: Fn() -> T>(&mut self, key: Self::Key, inserter: F) -> &mut T {
self.state.entry(key).or_insert_with(|| Box::new(inserter())).downcast_mut::<T>().unwrap()
}
}
pub struct RecreateInitialOperator {
recreate: Arc<dyn Recreate>,
}
impl RecreateInitialOperator {
pub fn new(recreate: Arc<dyn Recreate>) -> Self {
Self { recreate }
}
}
impl InitialOperator for RecreateInitialOperator {
type Context = RefinementContext;
type Objective = GoalContext;
type Solution = InsertionContext;
fn create(&self, heuristic_ctx: &Self::Context) -> Self::Solution {
let insertion_ctx = InsertionContext::new(heuristic_ctx.problem.clone(), heuristic_ctx.environment.clone());
self.recreate.run(heuristic_ctx, insertion_ctx)
}
}
pub struct Solver {
problem: Arc<Problem>,
config: EvolutionConfig<RefinementContext, GoalContext, InsertionContext>,
}
impl Solver {
pub fn new(
problem: Arc<Problem>,
config: EvolutionConfig<RefinementContext, GoalContext, InsertionContext>,
) -> Self {
Self { problem, config }
}
pub fn solve(self) -> GenericResult<Solution> {
(self.config.context.environment.logger)(&format!(
"total jobs: {}, actors: {}",
self.problem.jobs.size(),
self.problem.fleet.actors.len()
));
let (mut solutions, metrics) = EvolutionSimulator::new(self.config)?.run()?;
let insertion_ctx = if solutions.is_empty() { None } else { solutions.drain(0..1).next() }
.ok_or_else(|| "cannot find any solution".to_string())?;
let solution = (insertion_ctx, metrics).into();
Ok(solution)
}
}