Browse Source

currently broken; trying to get multithreaded sort to work

main
Thomas Johnson 11 months ago
parent
commit
a78b6d6f89
  1. 1
      Cargo.toml
  2. 41
      src/genetic.rs
  3. 89
      src/main.rs
  4. 2
      src/map.rs

1
Cargo.toml

@ -7,3 +7,4 @@ edition = "2018"
image = "0.23"
rand = "0.8"
rand_distr = "0.4"
rayon = "1.5"

41
src/genetic.rs

@ -1,10 +1,11 @@
use rand::Rng;
use rayon::prelude::*;
pub struct Arena<T: Genetic> {
pub keep: usize,
pub mutate: usize,
pub crossover: usize,
set: Vec<T>,
pub set: Vec<T>,
pub config: T::Configuration,
}
@ -22,6 +23,44 @@ impl<T: Genetic> Arena<T> {
config,
}
}
pub fn generate<R: Rng>(&mut self, rng: &mut R) {
let n = self.set.len();
for _ in 0..self.mutate {
let which = rng.gen_range(0..n);
let mutant = self.set[which].mutate(rng, &self.config);
self.set.push(mutant);
}
for _ in 0..self.crossover {
let p1 = rng.gen_range(0..n);
let p2 = rng.gen_range(0..n);
let child = self.set[p1].crossover(rng, &self.set[p2], &self.config);
self.set.push(child);
}
}
pub fn cull<R: Rng>(&mut self, rng: &mut R) {
let config = &self.config;
let set = &mut self.set;
set.sort_by(|a, b| a.compare(rng, b, config));
self.set.truncate(self.keep);
}
}
impl <T: Genetic> Arena<T> where
T: Sync,
T::Configuration: Sync,
{
pub fn par_process<F: Fn(&mut T, &T::Configuration) + Sync>(&mut self, f: F) {
self.set.par_iter_mut().for_each(|x| f(x, &self.config));
}
pub fn par_cull(&mut self) {
let config = &self.config;
let set = &mut self.set;
set.par_sort_unstable_by(|a, b| a.compare(&mut rand::thread_rng(), b, config));
self.set.truncate(self.keep);
}
}
pub trait Genetic {

89
src/main.rs

@ -1,6 +1,7 @@
#![allow(confusable_idents)]
#![allow(mixed_script_confusables)]
use image::{ImageBuffer, Rgb, GenericImage};
use rayon::prelude::*;
mod transform;
mod genetic;
@ -18,8 +19,6 @@ fn main() {
let pix = image_in_u16.get_pixel(x, y);
Rgb([pix[0] as f32 / 65535.0, pix[1] as f32 / 65535.0, pix[2] as f32 / 65535.0])
});
// let mut image_in: ImageBuffer<Rgb<f32>, Vec<f32>> = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
let mut image_out: ImageBuffer<Rgb<f32>, Vec<f32>> = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
let mut rng = rand::thread_rng();
let cfg = MapGeneticConfig::new(
@ -27,45 +26,61 @@ fn main() {
50,
20,
);
let map = cfg.create_map(&mut rng, 50);
let mut arena = genetic::Arena::<map::Map>::new(&mut rng, 100, 50, 50, cfg);
for i in 0..50 {
map.apply_add(&image_in, &mut image_out, dims);
println!("iteration {}", i);
arena.generate(&mut rng);
// arena.par_process(|map, cfg| { map.cost(cfg); });
arena.par_cull();
if true || i % 25 == 0 {
// write intermediate to file
let mut image_out_file = image_out.clone();
correct_image_brightness(&mut image_out_file, dims, 0.5, 1.0);
let image_out_u16: ImageBuffer<Rgb<u16>, Vec<u16>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {
let pix = image_out.get_pixel(x, y);
let scale = 65535.0;
Rgb([(pix[0] * scale) as u16, (pix[1] * scale) as u16, (pix[2] * scale) as u16])
});
image_out_u16.save(format!("{}{}.png", out_name, i)).expect("could not write output file");
let map = &arena.set[0];
println!("best cost: {}", map.cost(&arena.config));
let mut image_in: ImageBuffer<Rgb<f32>, Vec<f32>> = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
let mut image_out = image_in.clone();
for i in 0..20 {
map.apply_add(&image_in, &mut image_out, dims);
// switch buffers; reuse as input
core::mem::swap(&mut image_out, &mut image_in);
image_out = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
}
// switch buffers; reuse as input
core::mem::swap(&mut image_out, &mut image_in);
image_out = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
correct_image_brightness(&mut image_in, dims, 0.5, 0.15);
let image_out_u16: ImageBuffer<Rgb<u16>, Vec<u16>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {
let pix = image_in.get_pixel(x, y);
let scale = 65535.0;
Rgb([(pix[0] * scale) as u16, (pix[1] * scale) as u16, (pix[2] * scale) as u16])
});
image_out_u16.save(format!("{}{}.png", out_name, i)).expect("could not write output file");
}
map.apply_add(&image_in, &mut image_out, dims);
// let transform = Transform {
// color_matrix: [1.0, 0.0, 0.0, 0.0, 1.0, 0.0, 0.0, 0.0, 1.0],
// from_corner: (0, 0),
// from_extents: dims,
//// to_corner: (0.0, 0.0),
//// to_extents: [(dims.0 as f32, 0.0), (0.0, dims.1 as f32)],
// to_corner: (0.0, 1.0),
// to_extents: [(1.0, -0.5), (0.0, -0.5)],
// };
println!("cost: {}", map.cost(&cfg));
correct_image_brightness(&mut image_out, dims, 0.5, 0.15);
let image_out_u16: ImageBuffer<Rgb<u16>, Vec<u16>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {
let pix = image_out.get_pixel(x, y);
let scale = 65535.0;
Rgb([(pix[0] * scale) as u16, (pix[1] * scale) as u16, (pix[2] * scale) as u16])
});
image_out_u16.save(format!("{}.png", out_name)).expect("could not write output file");
// let map = cfg.create_map(&mut rng, 50);
// for i in 0..50 {
// map.apply_add(&image_in, &mut image_out, dims);
//
// if true || i % 25 == 0 {
// // write intermediate to file
// let mut image_out_file = image_out.clone();
// correct_image_brightness(&mut image_out_file, dims, 0.5, 1.0);
// let image_out_u16: ImageBuffer<Rgb<u16>, Vec<u16>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {
// let pix = image_out.get_pixel(x, y);
// let scale = 65535.0;
// Rgb([(pix[0] * scale) as u16, (pix[1] * scale) as u16, (pix[2] * scale) as u16])
// });
// image_out_u16.save(format!("{}{}.png", out_name, i)).expect("could not write output file");
// }
//
// // switch buffers; reuse as input
// core::mem::swap(&mut image_out, &mut image_in);
// image_out = ImageBuffer::from_fn(dims.0, dims.1, |_, _| Rgb([0.0, 0.0, 0.0]));
// }
//
// map.apply_add(&image_in, &mut image_out, dims);
// correct_image_brightness(&mut image_out, dims, 0.5, 0.15);
// let image_out_u16: ImageBuffer<Rgb<u16>, Vec<u16>> = ImageBuffer::from_fn(dims.0, dims.1, |x, y| {
// let pix = image_out.get_pixel(x, y);
// let scale = 65535.0;
// Rgb([(pix[0] * scale) as u16, (pix[1] * scale) as u16, (pix[2] * scale) as u16])
// });
// image_out_u16.save(format!("{}.png", out_name)).expect("could not write output file");
}
fn correct_image_brightness<I: GenericImage<Pixel=Rgb<f32>>>(img: &mut I, dims: (u32, u32), mean: f32, variance: f32) {

2
src/map.rs

@ -1,6 +1,7 @@
use crate::{transform::{Transform, NCOLORS}, genetic::Genetic};
use core::fmt::Debug;
use core::cell::Cell;
use std::sync::RwLock;
use rand::{Rng, distributions::{Uniform, WeightedIndex}};
use rand_distr::{Distribution, Bernoulli};
use image::{Rgb, GenericImage, ImageBuffer};
@ -37,6 +38,7 @@ impl Map {
}
pub fn cost(&self, cfg: &MapGeneticConfig) -> f32 {
println!("computing cost in thread {:?}", std::thread::current().id());
if let Some(c) = self.cached_cost.get() {
c
} else {

Loading…
Cancel
Save