Adding implementation to binary
This commit is contained in:
parent
e5188ec02f
commit
2fdf4c2545
5 changed files with 44 additions and 39 deletions
|
@ -3,7 +3,7 @@ version: "0.1"
|
||||||
autor: Jacob VanDomelen <jacob.vandome15@gmail.com>
|
autor: Jacob VanDomelen <jacob.vandome15@gmail.com>
|
||||||
about: Uses a genetic algorithm to generate a machine learning algorithm.
|
about: Uses a genetic algorithm to generate a machine learning algorithm.
|
||||||
args:
|
args:
|
||||||
- DIRECTORY:
|
- FILE:
|
||||||
help: Sets the input/output directory for the program.
|
help: Sets the input/output file for the program.
|
||||||
required: true
|
required: true
|
||||||
index: 1
|
index: 1
|
|
@ -5,27 +5,27 @@ extern crate gemla;
|
||||||
mod test_state;
|
mod test_state;
|
||||||
|
|
||||||
use clap::App;
|
use clap::App;
|
||||||
use std::fs::metadata;
|
use gemla::bracket::Gemla;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use test_state::TestState;
|
||||||
|
|
||||||
/// Runs a simluation of a genetic algorithm against a dataset.
|
/// Runs a simluation of a genetic algorithm against a dataset.
|
||||||
///
|
///
|
||||||
/// Use the -h, --h, or --help flag to see usage syntax.
|
/// Use the -h, --h, or --help flag to see usage syntax.
|
||||||
/// TODO
|
/// TODO
|
||||||
fn main() {
|
fn main() -> anyhow::Result<()> {
|
||||||
// Command line arguments are parsed with the clap crate. And this program uses
|
// Command line arguments are parsed with the clap crate. And this program uses
|
||||||
// the yaml method with clap.
|
// the yaml method with clap.
|
||||||
let yaml = load_yaml!("../../cli.yml");
|
let yaml = load_yaml!("../../cli.yml");
|
||||||
let matches = App::from_yaml(yaml).get_matches();
|
let matches = App::from_yaml(yaml).get_matches();
|
||||||
|
|
||||||
// Checking that the first argument <DIRECTORY> is a valid directory
|
// Checking that the first argument <DIRECTORY> is a valid directory
|
||||||
let directory = matches.value_of(gemla::constants::args::DIRECTORY).unwrap();
|
let file_path = matches.value_of(gemla::constants::args::FILE).unwrap();
|
||||||
let metadata = metadata(directory);
|
let mut gemla = Gemla::<TestState>::new(&PathBuf::from(file_path), true)?;
|
||||||
match &metadata {
|
|
||||||
Ok(m) if m.is_dir() => {
|
gemla.simulate(1)?;
|
||||||
println!("{} is a valid directory!", directory);
|
gemla.simulate(1)?;
|
||||||
println!("Building tree for {}.", directory);
|
gemla.simulate(1)?;
|
||||||
}
|
|
||||||
Ok(_) => println!("{} is not a valid directory!", directory),
|
Ok(())
|
||||||
_ => println!("{} does not exist!", directory),
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,39 +1,50 @@
|
||||||
use gemla::bracket::genetic_node::GeneticNode;
|
use gemla::bracket::genetic_node::GeneticNode;
|
||||||
use gemla::error;
|
use gemla::error;
|
||||||
use rand::prelude::*;
|
use rand::prelude::*;
|
||||||
use rand::rngs::ThreadRng;
|
use rand::{random, thread_rng};
|
||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
const POPULATION_SIZE: u64 = 5;
|
const POPULATION_SIZE: u64 = 5;
|
||||||
const POPULATION_REDUCTION_SIZE: u64 = 3;
|
const POPULATION_REDUCTION_SIZE: u64 = 3;
|
||||||
|
|
||||||
struct TestState {
|
#[derive(Serialize, Deserialize, Debug)]
|
||||||
|
pub struct TestState {
|
||||||
pub population: Vec<f64>,
|
pub population: Vec<f64>,
|
||||||
thread_rng: ThreadRng,
|
}
|
||||||
|
|
||||||
|
impl Default for TestState {
|
||||||
|
fn default() -> Self {
|
||||||
|
let mut population: Vec<f64> = vec![];
|
||||||
|
|
||||||
|
for _ in 0..POPULATION_SIZE {
|
||||||
|
population.push(random::<u64>() as f64)
|
||||||
|
}
|
||||||
|
|
||||||
|
TestState { population }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GeneticNode for TestState {
|
impl GeneticNode for TestState {
|
||||||
fn initialize() -> Result<Box<Self>, error::Error> {
|
fn initialize() -> Result<Box<Self>, error::Error> {
|
||||||
let mut thread_rng = thread_rng();
|
|
||||||
let mut population: Vec<f64> = vec![];
|
let mut population: Vec<f64> = vec![];
|
||||||
|
|
||||||
for _ in 0..POPULATION_SIZE {
|
for _ in 0..POPULATION_SIZE {
|
||||||
population.push(thread_rng.gen::<u64>() as f64)
|
population.push(random::<u64>() as f64)
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Box::new(TestState {
|
Ok(Box::new(TestState { population }))
|
||||||
population,
|
|
||||||
thread_rng,
|
|
||||||
}))
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn simulate(&mut self, iterations: u64) -> Result<(), error::Error> {
|
fn simulate(&mut self, iterations: u64) -> Result<(), error::Error> {
|
||||||
|
let mut rng = thread_rng();
|
||||||
|
|
||||||
for _ in 0..iterations {
|
for _ in 0..iterations {
|
||||||
self.population = self
|
self.population = self
|
||||||
.population
|
.population
|
||||||
.clone()
|
.clone()
|
||||||
.iter()
|
.iter()
|
||||||
.map(|p| p + self.thread_rng.gen_range(-10.0..10.0))
|
.map(|p| p + rng.gen_range(-10.0..10.0))
|
||||||
.collect()
|
.collect()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -52,26 +63,27 @@ impl GeneticNode for TestState {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mutate(&mut self) -> Result<(), error::Error> {
|
fn mutate(&mut self) -> Result<(), error::Error> {
|
||||||
|
let mut rng = thread_rng();
|
||||||
loop {
|
loop {
|
||||||
if self.population.len() >= POPULATION_SIZE.try_into().unwrap() {
|
if self.population.len() >= POPULATION_SIZE.try_into().unwrap() {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
let new_individual_index = self.thread_rng.gen_range(0..self.population.len());
|
let new_individual_index = rng.gen_range(0..self.population.len());
|
||||||
let mut cross_breed_index = self.thread_rng.gen_range(0..self.population.len());
|
let mut cross_breed_index = rng.gen_range(0..self.population.len());
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
if new_individual_index != cross_breed_index {
|
if new_individual_index != cross_breed_index {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
cross_breed_index = self.thread_rng.gen_range(0..self.population.len());
|
cross_breed_index = rng.gen_range(0..self.population.len());
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut new_individual = self.population.clone()[new_individual_index];
|
let mut new_individual = self.population.clone()[new_individual_index];
|
||||||
let cross_breed = self.population.clone()[cross_breed_index];
|
let cross_breed = self.population.clone()[cross_breed_index];
|
||||||
|
|
||||||
new_individual += cross_breed + self.thread_rng.gen_range(-10.0..10.0);
|
new_individual += cross_breed + rng.gen_range(-10.0..10.0);
|
||||||
|
|
||||||
self.population.push(new_individual);
|
self.population.push(new_individual);
|
||||||
}
|
}
|
||||||
|
@ -88,10 +100,7 @@ impl GeneticNode for TestState {
|
||||||
|
|
||||||
v = v[..(POPULATION_REDUCTION_SIZE as usize)].to_vec();
|
v = v[..(POPULATION_REDUCTION_SIZE as usize)].to_vec();
|
||||||
|
|
||||||
let mut result = TestState {
|
let mut result = TestState { population: v };
|
||||||
population: v,
|
|
||||||
thread_rng: thread_rng(),
|
|
||||||
};
|
|
||||||
|
|
||||||
result.mutate()?;
|
result.mutate()?;
|
||||||
|
|
||||||
|
@ -114,7 +123,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_simulate() {
|
fn test_simulate() {
|
||||||
let mut state = TestState {
|
let mut state = TestState {
|
||||||
thread_rng: thread_rng(),
|
|
||||||
population: vec![1.0, 1.0, 2.0, 3.0],
|
population: vec![1.0, 1.0, 2.0, 3.0],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -139,7 +147,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_calculate_scores_and_trim() {
|
fn test_calculate_scores_and_trim() {
|
||||||
let mut state = TestState {
|
let mut state = TestState {
|
||||||
thread_rng: thread_rng(),
|
|
||||||
population: vec![4.0, 1.0, 1.0, 3.0, 2.0],
|
population: vec![4.0, 1.0, 1.0, 3.0, 2.0],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -154,7 +161,6 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_mutate() {
|
fn test_mutate() {
|
||||||
let mut state = TestState {
|
let mut state = TestState {
|
||||||
thread_rng: thread_rng(),
|
|
||||||
population: vec![4.0, 3.0, 3.0],
|
population: vec![4.0, 3.0, 3.0],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -166,12 +172,10 @@ mod tests {
|
||||||
#[test]
|
#[test]
|
||||||
fn test_merge() {
|
fn test_merge() {
|
||||||
let state1 = TestState {
|
let state1 = TestState {
|
||||||
thread_rng: thread_rng(),
|
|
||||||
population: vec![1.0, 2.0, 4.0, 5.0],
|
population: vec![1.0, 2.0, 4.0, 5.0],
|
||||||
};
|
};
|
||||||
|
|
||||||
let state2 = TestState {
|
let state2 = TestState {
|
||||||
thread_rng: thread_rng(),
|
|
||||||
population: vec![0.0, 1.0, 3.0, 7.0],
|
population: vec![0.0, 1.0, 3.0, 7.0],
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -1,2 +1,2 @@
|
||||||
/// Corresponds to the DIRECTORY command line argument used in accordance with the clap crate.
|
/// Corresponds to the FILE command line argument used in accordance with the clap crate.
|
||||||
pub const DIRECTORY: &str = "DIRECTORY";
|
pub const FILE: &str = "FILE";
|
||||||
|
|
1
gemla/temp
Normal file
1
gemla/temp
Normal file
File diff suppressed because one or more lines are too long
Loading…
Add table
Reference in a new issue