mod dynamic_selective;
pub use self::dynamic_selective::*;
mod static_selective;
pub use self::static_selective::*;
use crate::prelude::*;
use crate::utils::parallel_into_collect;
use std::fmt::Display;
use std::marker::PhantomData;
use std::sync::Arc;
pub trait HeuristicSearchOperator {
type Context: HeuristicContext<Objective = Self::Objective, Solution = Self::Solution>;
type Objective: HeuristicObjective<Solution = Self::Solution>;
type Solution: HeuristicSolution;
fn search(&self, heuristic_ctx: &Self::Context, solution: &Self::Solution) -> Self::Solution;
}
pub trait HeuristicDiversifyOperator {
type Context: HeuristicContext<Objective = Self::Objective, Solution = Self::Solution>;
type Objective: HeuristicObjective<Solution = Self::Solution>;
type Solution: HeuristicSolution;
fn diversify(&self, heuristic_ctx: &Self::Context, solution: &Self::Solution) -> Vec<Self::Solution>;
}
pub trait HyperHeuristic: Display {
type Context: HeuristicContext<Objective = Self::Objective, Solution = Self::Solution>;
type Objective: HeuristicObjective<Solution = Self::Solution>;
type Solution: HeuristicSolution;
fn search(&mut self, heuristic_ctx: &Self::Context, solution: &Self::Solution) -> Vec<Self::Solution>;
fn search_many(&mut self, heuristic_ctx: &Self::Context, solutions: Vec<&Self::Solution>) -> Vec<Self::Solution>;
fn diversify(&self, heuristic_ctx: &Self::Context, solution: &Self::Solution) -> Vec<Self::Solution>;
fn diversify_many(&self, heuristic_ctx: &Self::Context, solutions: Vec<&Self::Solution>) -> Vec<Self::Solution>;
}
fn get_diversify_probability<C, O, S>(heuristic_ctx: &C) -> f64
where
C: HeuristicContext<Objective = O, Solution = S>,
O: HeuristicObjective<Solution = S>,
S: HeuristicSolution,
{
let last = heuristic_ctx.statistics().improvement_1000_ratio;
let global = heuristic_ctx.statistics().improvement_all_ratio;
match last {
_ if last > 0.2 => 0.001,
_ if last > 0.1 => 0.01,
_ if last > 0.05 => 0.02,
_ if global < 0.001 => 0.1,
_ => 0.05,
}
}
fn diversify_solution<C, O, S>(
heuristic_ctx: &C,
solution: &S,
operators: &[Arc<dyn HeuristicDiversifyOperator<Context = C, Objective = O, Solution = S> + Send + Sync>],
) -> Vec<S>
where
C: HeuristicContext<Objective = O, Solution = S>,
O: HeuristicObjective<Solution = S>,
S: HeuristicSolution,
{
assert!(!operators.is_empty());
let random = heuristic_ctx.environment().random.as_ref();
let operator_idx = random.uniform_int(0, operators.len() as i32 - 1) as usize;
let operator = &operators[operator_idx];
operator.diversify(heuristic_ctx, solution)
}
fn diversify_solutions<C, O, S>(
heuristic_ctx: &C,
solutions: Vec<&S>,
operators: &[Arc<dyn HeuristicDiversifyOperator<Context = C, Objective = O, Solution = S> + Send + Sync>],
) -> Vec<S>
where
C: HeuristicContext<Objective = O, Solution = S>,
O: HeuristicObjective<Solution = S>,
S: HeuristicSolution,
{
assert!(!operators.is_empty());
let random = heuristic_ctx.environment().random.as_ref();
let probability = get_diversify_probability(heuristic_ctx);
let solutions = solutions.into_iter().filter(|_| random.is_hit(probability)).collect::<Vec<_>>();
parallel_into_collect(solutions.iter().enumerate().collect(), |(solution_idx, solution)| {
heuristic_ctx
.environment()
.parallelism
.thread_pool_execute(solution_idx, || diversify_solution(heuristic_ctx, solution, operators))
})
.into_iter()
.flatten()
.collect()
}