Skip to content

Commit

Permalink
add the rng as an attribute of simulated annealing
Browse files Browse the repository at this point in the history
This allows to easily experiment with different RNG and to more easily
test it given that we can now seed the rng as we like.
  • Loading branch information
danieledapo authored and sharkdp committed Sep 15, 2019
1 parent 9e1a996 commit 9bdd6e8
Show file tree
Hide file tree
Showing 2 changed files with 27 additions and 16 deletions.
35 changes: 20 additions & 15 deletions src/distinct.rs
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@ use core::f64 as scalar;
use rand::prelude::*;

use crate::delta_e;
use crate::random::{self, RandomizationStrategy};
use crate::random;
use crate::{Color, Lab};

type Scalar = f64;
Expand Down Expand Up @@ -64,13 +64,14 @@ pub struct SimulationParameters {
pub fixed_colors: usize,
}

pub struct SimulatedAnnealing {
pub struct SimulatedAnnealing<R: Rng> {
colors: Vec<(Color, Lab)>,
temperature: Scalar,
pub parameters: SimulationParameters,
rng: R,
}

impl SimulatedAnnealing {
impl SimulatedAnnealing<ThreadRng> {
pub fn new(initial_colors: &[Color], parameters: SimulationParameters) -> Self {
let colors = initial_colors
.iter()
Expand All @@ -81,34 +82,37 @@ impl SimulatedAnnealing {
colors,
temperature: parameters.initial_temperature,
parameters,
rng: thread_rng(),
}
}
}

impl<R: Rng> SimulatedAnnealing<R> {
pub fn get_colors(&self) -> Vec<Color> {
self.colors.iter().map(|(c, _)| c.clone()).collect()
}

fn modify_channel(c: &mut u8) {
if random::<bool>() {
*c = c.saturating_add(random::<u8>() % 10);
fn modify_channel(&mut self, c: &mut u8) {
if self.rng.gen::<bool>() {
*c = c.saturating_add(self.rng.gen::<u8>() % 10);
} else {
*c = c.saturating_sub(random::<u8>() % 10);
*c = c.saturating_sub(self.rng.gen::<u8>() % 10);
}
}

fn modify_color(&self, color: &mut (Color, Lab)) {
fn modify_color(&mut self, color: &mut (Color, Lab)) {
const STRATEGY: random::strategies::UniformRGB = random::strategies::UniformRGB {};

match self.parameters.opt_mode {
OptimizationMode::Local => {
let mut rgb = color.0.to_rgba();
Self::modify_channel(&mut rgb.r);
Self::modify_channel(&mut rgb.g);
Self::modify_channel(&mut rgb.b);
self.modify_channel(&mut rgb.r);
self.modify_channel(&mut rgb.g);
self.modify_channel(&mut rgb.b);
color.0 = Color::from_rgb(rgb.r, rgb.g, rgb.b);
}
OptimizationMode::Global => {
color.0 = STRATEGY.generate();
color.0 = STRATEGY.generate_with(&mut self.rng);
}
}
color.1 = color.0.to_lab();
Expand All @@ -129,9 +133,10 @@ impl SimulatedAnnealing {

for iter in 0..self.parameters.num_iterations {
let random_index = if self.parameters.opt_target == OptimizationTarget::Mean {
thread_rng().gen_range(self.parameters.fixed_colors, self.colors.len())
self.rng
.gen_range(self.parameters.fixed_colors, self.colors.len())
} else {
if random::<bool>() {
if self.rng.gen::<bool>() {
result.closest_pair.0
} else {
result.closest_pair.1
Expand Down Expand Up @@ -164,7 +169,7 @@ impl SimulatedAnnealing {
self.colors = new_colors;
} else {
let bolzmann = Scalar::exp(-(score - new_score) / self.temperature);
if random::<Scalar>() <= bolzmann {
if self.rng.gen::<Scalar>() <= bolzmann {
result = new_result;
self.colors = new_colors;
}
Expand Down
8 changes: 7 additions & 1 deletion src/random.rs
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,15 @@ pub mod strategies {

pub struct UniformRGB;

impl UniformRGB {
pub fn generate_with(&self, rng: &mut impl Rng) -> Color {
Color::from_rgb(rng.gen::<u8>(), rng.gen::<u8>(), rng.gen::<u8>())
}
}

impl RandomizationStrategy for UniformRGB {
fn generate(&mut self) -> Color {
Color::from_rgb(random::<u8>(), random::<u8>(), random::<u8>())
self.generate_with(&mut thread_rng())
}
}

Expand Down

0 comments on commit 9bdd6e8

Please sign in to comment.