hlayers, mut_rate ui bridged
This commit is contained in:
parent
39941c8425
commit
8d317346f8
110
src/main.rs
110
src/main.rs
|
@ -61,13 +61,13 @@ async fn main() {
|
||||||
let mut speedup = 1;
|
let mut speedup = 1;
|
||||||
let mut paused = false;
|
let mut paused = false;
|
||||||
let mut bias = false;
|
let mut bias = false;
|
||||||
let mut size = 100;
|
let mut size: u32 = 100;
|
||||||
let mut pop = Population::new(size as usize);
|
let mut hlayers: Vec<usize> = vec![6, 6, 0];
|
||||||
let mut x = 0.;
|
let mut prev_hlayers = hlayers.clone();
|
||||||
let mut xy = "".to_string();
|
let mut mut_rate = 0.05;
|
||||||
let mut l1: usize = 6;
|
let mut prev_mut_rate = 0.05;
|
||||||
let mut l2: usize = 6;
|
let mut pop = Population::new(size as usize, hlayers.clone(), mut_rate);
|
||||||
let mut l3: usize = 0;
|
let mut activ: usize = 0;
|
||||||
|
|
||||||
let ui_thick = 34.;
|
let ui_thick = 34.;
|
||||||
let nums = &[
|
let nums = &[
|
||||||
|
@ -115,7 +115,7 @@ async fn main() {
|
||||||
.build();
|
.build();
|
||||||
let group_style = root_ui()
|
let group_style = root_ui()
|
||||||
.style_builder()
|
.style_builder()
|
||||||
.color(Color::new(1., 0., 0., 1.))
|
.color(Color::new(1., 0., 0., 0.))
|
||||||
.build();
|
.build();
|
||||||
let editbox_style = root_ui()
|
let editbox_style = root_ui()
|
||||||
.style_builder()
|
.style_builder()
|
||||||
|
@ -129,11 +129,7 @@ async fn main() {
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
||||||
// .margin(RectOffset::new(10., 10., 8., 8.))
|
|
||||||
.text_color(WHITE)
|
.text_color(WHITE)
|
||||||
// .color_hovered(WHITE)
|
|
||||||
// .color_inactive(WHITE)
|
|
||||||
// .color(WHITE)
|
|
||||||
.build();
|
.build();
|
||||||
let combobox_style = root_ui()
|
let combobox_style = root_ui()
|
||||||
.style_builder()
|
.style_builder()
|
||||||
|
@ -147,9 +143,6 @@ async fn main() {
|
||||||
],
|
],
|
||||||
})
|
})
|
||||||
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
||||||
// .margin(RectOffset::new(1., 1., 1., 1.))
|
|
||||||
// .text_color_hovered(WHITE)
|
|
||||||
// .text_color(WHITE)
|
|
||||||
.color_hovered(WHITE)
|
.color_hovered(WHITE)
|
||||||
.color_selected_hovered(WHITE)
|
.color_selected_hovered(WHITE)
|
||||||
.color_inactive(WHITE)
|
.color_inactive(WHITE)
|
||||||
|
@ -174,11 +167,31 @@ async fn main() {
|
||||||
.style_builder()
|
.style_builder()
|
||||||
.text_color(WHITE)
|
.text_color(WHITE)
|
||||||
.font_size(16)
|
.font_size(16)
|
||||||
// .margin(RectOffset::new(5., 5., 4., 0.))
|
|
||||||
.text_color_hovered(LIGHTGRAY)
|
.text_color_hovered(LIGHTGRAY)
|
||||||
.text_color_clicked(WHITE)
|
.text_color_clicked(WHITE)
|
||||||
.build();
|
.build();
|
||||||
|
skin2.button_style = root_ui()
|
||||||
|
.style_builder()
|
||||||
|
.background(Image {
|
||||||
|
width: 3,
|
||||||
|
height: 3,
|
||||||
|
bytes: vec![
|
||||||
|
255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 0,
|
||||||
|
0, 0, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255, 255,
|
||||||
|
255, 255,
|
||||||
|
],
|
||||||
|
})
|
||||||
|
.background_margin(RectOffset::new(1., 1., 1., 1.))
|
||||||
|
.color_hovered(RED)
|
||||||
|
.color_clicked(BLUE)
|
||||||
|
.text_color(WHITE)
|
||||||
|
.text_color_hovered(WHITE)
|
||||||
|
.text_color_clicked(WHITE)
|
||||||
|
.margin(RectOffset::new(4., 4., 2., 2.))
|
||||||
|
.color_inactive(WHITE)
|
||||||
|
.build();
|
||||||
|
|
||||||
|
root_ui().push_skin(&skin);
|
||||||
loop {
|
loop {
|
||||||
clear_background(BLACK);
|
clear_background(BLACK);
|
||||||
set_camera(&gamecam);
|
set_camera(&gamecam);
|
||||||
|
@ -245,9 +258,8 @@ async fn main() {
|
||||||
vec2(WIDTH + 2. * th, th),
|
vec2(WIDTH + 2. * th, th),
|
||||||
vec2(ui_width, ui_height),
|
vec2(ui_width, ui_height),
|
||||||
|ui| {
|
|ui| {
|
||||||
ui.push_skin(&skin);
|
widgets::Group::new(hash!(), vec2(ui_width, ui_thick))
|
||||||
widgets::Group::new(hash!(), Vec2::new(ui_width, ui_thick))
|
.position(vec2(0., 0.))
|
||||||
.position(Vec2::new(0., 0.))
|
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
ui.label(None, &format!("Generation: {}", pop.gen));
|
ui.label(None, &format!("Generation: {}", pop.gen));
|
||||||
ui.same_line(242.);
|
ui.same_line(242.);
|
||||||
|
@ -255,8 +267,19 @@ async fn main() {
|
||||||
if let Some(path) = open_file_dialog("Load Model", "model.json", None) {
|
if let Some(path) = open_file_dialog("Load Model", "model.json", None) {
|
||||||
let brain = NN::import(&path);
|
let brain = NN::import(&path);
|
||||||
size = 1;
|
size = 1;
|
||||||
pop = Population::new(1);
|
hlayers = brain
|
||||||
pop.worlds[0] = World::simulate(Some(brain));
|
.config
|
||||||
|
.iter()
|
||||||
|
.take(brain.config.len() - 1)
|
||||||
|
.skip(1)
|
||||||
|
.map(|x| x - 1)
|
||||||
|
.collect::<Vec<_>>();
|
||||||
|
hlayers.resize(3, 0);
|
||||||
|
prev_hlayers = hlayers.clone();
|
||||||
|
mut_rate = brain.mut_rate;
|
||||||
|
prev_mut_rate = brain.mut_rate;
|
||||||
|
pop = Population::new(size as usize, hlayers.clone(), mut_rate);
|
||||||
|
pop.worlds[0] = World::simulate(brain);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ui.same_line(0.);
|
ui.same_line(0.);
|
||||||
|
@ -282,15 +305,18 @@ async fn main() {
|
||||||
paused = !paused;
|
paused = !paused;
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
widgets::Group::new(hash!(), Vec2::new(ui_width, ui_thick))
|
widgets::Group::new(hash!(), vec2(ui_width, ui_thick))
|
||||||
.position(Vec2::new(0., ui_height - ui_thick))
|
.position(vec2(0., ui_height - ui_thick))
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
ui.label(Some(vec2(0., 2.)), "«Population»");
|
ui.label(Some(vec2(0., 2.)), "Population:");
|
||||||
widgets::Group::new(hash!(), Vec2::new(100., ui_thick))
|
widgets::Group::new(hash!(), vec2(200., ui_thick))
|
||||||
.position(Vec2::new(140., 0.))
|
.position(vec2(80., 0.))
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
ui.drag(hash!(), "", Some((1, 300)), &mut size);
|
ui.drag(hash!(), "", Some((1, 300)), &mut size);
|
||||||
});
|
});
|
||||||
|
ui.push_skin(&skin2);
|
||||||
|
ui.label(Some(vec2(230., ui_thick * 0.5 - 7.)), "«Drag»");
|
||||||
|
ui.pop_skin();
|
||||||
ui.same_line(279.);
|
ui.same_line(279.);
|
||||||
if widgets::Button::new(if pop.debug { "Debug:ON " } else { "Debug:OFF" })
|
if widgets::Button::new(if pop.debug { "Debug:ON " } else { "Debug:OFF" })
|
||||||
.ui(ui)
|
.ui(ui)
|
||||||
|
@ -310,29 +336,39 @@ async fn main() {
|
||||||
};
|
};
|
||||||
ui.same_line(0.);
|
ui.same_line(0.);
|
||||||
if widgets::Button::new(restart).ui(ui) {
|
if widgets::Button::new(restart).ui(ui) {
|
||||||
pop = Population::new(size as usize);
|
pop = Population::new(size as usize, hlayers.clone(), mut_rate);
|
||||||
};
|
};
|
||||||
});
|
});
|
||||||
ui.pop_skin();
|
|
||||||
ui.push_skin(&skin2);
|
ui.push_skin(&skin2);
|
||||||
widgets::Group::new(
|
widgets::Group::new(
|
||||||
hash!(),
|
hash!(),
|
||||||
Vec2::new(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
vec2(ui_width * 0.2, ui_height * 0.8 - 2. * th - 2. * ui_thick),
|
||||||
)
|
)
|
||||||
.position(Vec2::new(ui_width * 0.8, ui_height * 0.2 + ui_thick + th))
|
.position(vec2(ui_width * 0.8 - th, ui_height * 0.2 + ui_thick + th))
|
||||||
.ui(ui, |ui| {
|
.ui(ui, |ui| {
|
||||||
// ui.input_text(hash!(), "vec2(100., 100.)", &mut xy);
|
// ui.input_text(hash!(), "vec2(100., 100.)", &mut xy);
|
||||||
ui.label(None, "Hidden Layers Neuron");
|
ui.label(None, "Hidden Layers");
|
||||||
ui.label(None, "Config");
|
ui.label(None, "Neurons Config");
|
||||||
ui.label(None, " ");
|
|
||||||
|
|
||||||
ui.combo_box(hash!(), "Layer 1", nums, &mut l1);
|
ui.combo_box(hash!(), "Layer 1", nums, &mut hlayers[0]);
|
||||||
ui.combo_box(hash!(), "Layer 2", nums, &mut l2);
|
ui.combo_box(hash!(), "Layer 2", nums, &mut hlayers[1]);
|
||||||
ui.combo_box(hash!(), "Layer 3", nums, &mut l3);
|
ui.combo_box(hash!(), "Layer 3", nums, &mut hlayers[2]);
|
||||||
|
if prev_hlayers != hlayers {
|
||||||
|
pop = Population::new(size as usize, hlayers.clone(), mut_rate);
|
||||||
|
prev_hlayers = hlayers.clone();
|
||||||
|
}
|
||||||
ui.label(None, " ");
|
ui.label(None, " ");
|
||||||
ui.label(None, "Mutation Rate");
|
ui.label(None, "Mutation Rate");
|
||||||
// ui.(hash!(), "", 0.0..0.2, &mut x);
|
ui.drag(hash!(), "«Drag»", Some((0., 1.)), &mut mut_rate);
|
||||||
|
if prev_mut_rate != mut_rate {
|
||||||
|
pop.change_mut(mut_rate);
|
||||||
|
prev_mut_rate = mut_rate;
|
||||||
|
}
|
||||||
|
ui.label(None, " ");
|
||||||
|
ui.label(None, "Activation Func");
|
||||||
|
ui.combo_box(hash!(), "«Select»", &["ReLU", "Sigm"], &mut activ);
|
||||||
});
|
});
|
||||||
|
ui.pop_skin();
|
||||||
},
|
},
|
||||||
);
|
);
|
||||||
next_frame().await;
|
next_frame().await;
|
||||||
|
|
10
src/nn.rs
10
src/nn.rs
|
@ -7,7 +7,7 @@ extern crate rand as r;
|
||||||
|
|
||||||
#[derive(PartialEq, Debug, Clone, Copy, Default, Serialize, Deserialize)]
|
#[derive(PartialEq, Debug, Clone, Copy, Default, Serialize, Deserialize)]
|
||||||
|
|
||||||
enum ActivationFunc {
|
pub enum ActivationFunc {
|
||||||
Sigmoid,
|
Sigmoid,
|
||||||
Tanh,
|
Tanh,
|
||||||
#[default]
|
#[default]
|
||||||
|
@ -18,13 +18,13 @@ enum ActivationFunc {
|
||||||
pub struct NN {
|
pub struct NN {
|
||||||
pub config: Vec<usize>,
|
pub config: Vec<usize>,
|
||||||
pub weights: Vec<DMatrix<f32>>,
|
pub weights: Vec<DMatrix<f32>>,
|
||||||
activ_func: ActivationFunc,
|
pub activ_func: ActivationFunc,
|
||||||
mut_rate: f32,
|
pub mut_rate: f32,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl NN {
|
impl NN {
|
||||||
// Vec of number of neurons in input, hidden 1, hidden 2, ..., output layers
|
// Vec of number of neurons in input, hidden 1, hidden 2, ..., output layers
|
||||||
pub fn new(config: Vec<usize>) -> Self {
|
pub fn new(config: Vec<usize>, mut_rate: f32) -> Self {
|
||||||
let mut rng = r::thread_rng();
|
let mut rng = r::thread_rng();
|
||||||
|
|
||||||
Self {
|
Self {
|
||||||
|
@ -45,7 +45,7 @@ impl NN {
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
|
|
||||||
mut_rate: 0.05,
|
mut_rate,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,17 @@ pub struct Player {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Player {
|
impl Player {
|
||||||
pub fn new() -> Self {
|
pub fn new(config: Option<Vec<usize>>, mut_rate: Option<f32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
|
brain: match config {
|
||||||
|
Some(mut c) => {
|
||||||
|
c.retain(|&x| x != 0);
|
||||||
|
c.insert(0, 5);
|
||||||
|
c.push(4);
|
||||||
|
Some(NN::new(c, mut_rate.unwrap()))
|
||||||
|
}
|
||||||
|
_ => None,
|
||||||
|
},
|
||||||
dir: vec2(0., -1.),
|
dir: vec2(0., -1.),
|
||||||
rot: 1.5 * PI,
|
rot: 1.5 * PI,
|
||||||
|
|
||||||
|
@ -41,21 +50,6 @@ impl Player {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn simulate(brain: Option<NN>) -> Self {
|
|
||||||
let mut p = Player::new();
|
|
||||||
if let Some(brain) = brain {
|
|
||||||
// assert_eq!(
|
|
||||||
// brain.config[0] - 1,
|
|
||||||
// 8 + 5,
|
|
||||||
// "NN input size must match max_asteroids"
|
|
||||||
// );
|
|
||||||
p.brain = Some(brain);
|
|
||||||
} else {
|
|
||||||
p.brain = Some(NN::new(vec![5, 6, 6, 4]));
|
|
||||||
}
|
|
||||||
p
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn check_player_collision(&mut self, asteroid: &Asteroid) -> bool {
|
pub fn check_player_collision(&mut self, asteroid: &Asteroid) -> bool {
|
||||||
// To give more near asteroids data:
|
// To give more near asteroids data:
|
||||||
|
|
||||||
|
|
|
@ -10,13 +10,17 @@ pub struct Population {
|
||||||
pub debug: bool,
|
pub debug: bool,
|
||||||
pub worlds: Vec<World>,
|
pub worlds: Vec<World>,
|
||||||
pub track: usize,
|
pub track: usize,
|
||||||
|
pub hlayers: Vec<usize>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Population {
|
impl Population {
|
||||||
pub fn new(size: usize) -> Self {
|
pub fn new(size: usize, hlayers: Vec<usize>, mut_rate: f32) -> Self {
|
||||||
Self {
|
Self {
|
||||||
size,
|
size,
|
||||||
worlds: (0..size).map(|_| World::simulate(None)).collect(),
|
hlayers: hlayers.clone(),
|
||||||
|
worlds: (0..size)
|
||||||
|
.map(|_| World::new(Some(hlayers.clone()), Some(mut_rate)))
|
||||||
|
.collect(),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +59,12 @@ impl Population {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn change_mut(&mut self, mut_rate: f32) {
|
||||||
|
for world in &mut self.worlds {
|
||||||
|
world.player.brain.as_mut().unwrap().mut_rate = mut_rate;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn draw(&self) {
|
pub fn draw(&self) {
|
||||||
for world in self.worlds.iter().rev() {
|
for world in self.worlds.iter().rev() {
|
||||||
if self.focus {
|
if self.focus {
|
||||||
|
@ -95,7 +105,7 @@ impl Population {
|
||||||
}
|
}
|
||||||
println!("Gen: {}, Fitness: {}", self.gen, self.worlds[0].fitness);
|
println!("Gen: {}, Fitness: {}", self.gen, self.worlds[0].fitness);
|
||||||
let mut new_worlds = (0..std::cmp::max(1, self.size / 20))
|
let mut new_worlds = (0..std::cmp::max(1, self.size / 20))
|
||||||
.map(|i| World::simulate(Some(self.worlds[i].see_brain().to_owned())))
|
.map(|i| World::simulate(self.worlds[i].see_brain().to_owned()))
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
while new_worlds.len() < self.size {
|
while new_worlds.len() < self.size {
|
||||||
let rands = (gen_range(0., total), gen_range(0., total));
|
let rands = (gen_range(0., total), gen_range(0., total));
|
||||||
|
@ -118,7 +128,7 @@ impl Population {
|
||||||
}
|
}
|
||||||
let mut new_brain = NN::crossover(a.unwrap(), b.unwrap());
|
let mut new_brain = NN::crossover(a.unwrap(), b.unwrap());
|
||||||
new_brain.mutate();
|
new_brain.mutate();
|
||||||
new_worlds.push(World::simulate(Some(new_brain)));
|
new_worlds.push(World::simulate(new_brain));
|
||||||
}
|
}
|
||||||
self.worlds = new_worlds;
|
self.worlds = new_worlds;
|
||||||
self.worlds[0].track(true);
|
self.worlds[0].track(true);
|
||||||
|
|
|
@ -17,9 +17,9 @@ pub struct World {
|
||||||
}
|
}
|
||||||
|
|
||||||
impl World {
|
impl World {
|
||||||
pub fn simulate(brain: Option<NN>) -> Self {
|
pub fn new(hlayers: Option<Vec<usize>>, mut_rate: Option<f32>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
player: Player::simulate(brain),
|
player: Player::new(hlayers, mut_rate),
|
||||||
score: 1.,
|
score: 1.,
|
||||||
asteroids: vec![
|
asteroids: vec![
|
||||||
Asteroid::new_to(vec2(0., 0.), 1.5, AsteroidSize::Large),
|
Asteroid::new_to(vec2(0., 0.), 1.5, AsteroidSize::Large),
|
||||||
|
@ -32,6 +32,11 @@ impl World {
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
pub fn simulate(brain: NN) -> Self {
|
||||||
|
let mut w = World::new(None, None);
|
||||||
|
w.player.brain = Some(brain);
|
||||||
|
w
|
||||||
|
}
|
||||||
|
|
||||||
pub fn track(&mut self, track: bool) {
|
pub fn track(&mut self, track: bool) {
|
||||||
self.track = track;
|
self.track = track;
|
||||||
|
|
Loading…
Reference in New Issue