|
|
@ -5,6 +5,8 @@ use rand::{Rng, distributions::{Uniform, WeightedIndex}}; |
|
|
|
use rand_distr::{Distribution, Bernoulli};
|
|
|
|
use image::{Rgb, GenericImage, ImageBuffer};
|
|
|
|
|
|
|
|
mod gpu;
|
|
|
|
|
|
|
|
#[derive(Debug)]
|
|
|
|
pub struct Map
|
|
|
|
{
|
|
|
@ -102,56 +104,40 @@ impl Genetic for Map |
|
|
|
}
|
|
|
|
|
|
|
|
fn mutate<R: Rng>(&self, mut rng: &mut R, cfg: &Self::Configuration) -> Self {
|
|
|
|
match WeightedIndex::new(&[1, 1, 1]).unwrap().sample(&mut rng) {
|
|
|
|
// four options are:
|
|
|
|
// - change a matrix
|
|
|
|
// - add element(s)
|
|
|
|
// - remove element(s)
|
|
|
|
// //- change extents
|
|
|
|
0 => {
|
|
|
|
let mut new_tfs = self.transforms.clone();
|
|
|
|
let mut accum = 1.0;
|
|
|
|
let threshold = (cfg.mean_add as f32).exp().recip();
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
while accum > threshold {
|
|
|
|
let which = rng.gen_range(0..self.transforms.len());
|
|
|
|
let mut matrix_coeff_dist = Uniform::new(-1.0, 1.0).sample_iter(&mut rng);
|
|
|
|
for i in 0..NCOLORS * NCOLORS {
|
|
|
|
new_tfs[which].color_matrix[i] = matrix_coeff_dist.next().unwrap();
|
|
|
|
}
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
}
|
|
|
|
Map {
|
|
|
|
transforms: new_tfs,
|
|
|
|
cached_error: RwLock::new(None),
|
|
|
|
}
|
|
|
|
}
|
|
|
|
1 => {
|
|
|
|
let mut new = self.clone();
|
|
|
|
let mut accum = 1.0;
|
|
|
|
let threshold = (cfg.mean_add as f32).exp().recip();
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
while accum > threshold {
|
|
|
|
let transform = cfg.random_transform(rng);
|
|
|
|
new.transforms.push(transform);
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
}
|
|
|
|
new
|
|
|
|
}
|
|
|
|
2 => {
|
|
|
|
let mut new = self.clone();
|
|
|
|
let mut accum = 1.0;
|
|
|
|
let threshold = (cfg.mean_add as f32).exp().recip();
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
while new.transforms.len() != 0 && accum > threshold {
|
|
|
|
let which = rng.gen_range(0..new.transforms.len());
|
|
|
|
new.transforms.swap_remove(which);
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
}
|
|
|
|
new
|
|
|
|
// first, remove elements
|
|
|
|
let mut new = self.clone();
|
|
|
|
let mut accum = 1.0;
|
|
|
|
let threshold = (cfg.mean_add as f32).exp().recip();
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
while accum > threshold {
|
|
|
|
let transform = cfg.random_transform(rng);
|
|
|
|
new.transforms.push(transform);
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
}
|
|
|
|
|
|
|
|
// now, change some of the matrices
|
|
|
|
let mut accum = 1.0;
|
|
|
|
let threshold = (cfg.mean_add as f32).exp().recip();
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
while accum > threshold {
|
|
|
|
let which = rng.gen_range(0..self.transforms.len());
|
|
|
|
let mut matrix_coeff_dist = Uniform::new(-1.0, 1.0).sample_iter(&mut rng);
|
|
|
|
for i in 0..NCOLORS * NCOLORS {
|
|
|
|
new.transforms[which].color_matrix[i] = matrix_coeff_dist.next().unwrap();
|
|
|
|
}
|
|
|
|
_ => { unreachable!() }
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
}
|
|
|
|
|
|
|
|
// add some new transforms
|
|
|
|
let mut accum = 1.0;
|
|
|
|
let threshold = (cfg.mean_add as f32).exp().recip();
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
while new.transforms.len() != 0 && accum > threshold {
|
|
|
|
let which = rng.gen_range(0..new.transforms.len());
|
|
|
|
new.transforms.swap_remove(which);
|
|
|
|
accum *= rng.gen::<f32>();
|
|
|
|
}
|
|
|
|
new
|
|
|
|
}
|
|
|
|
|
|
|
|
fn crossover<R: Rng>(&self, rng: &mut R, other: &Self, _config: &Self::Configuration) -> Self {
|
|
|
|