Skip to content

Instantly share code, notes, and snippets.

@optozorax
Last active February 23, 2020 07:19
Show Gist options
  • Save optozorax/f6e0ac596af6b55f7e6a4f3d9e29a6ae to your computer and use it in GitHub Desktop.
Save optozorax/f6e0ac596af6b55f7e6a4f3d9e29a6ae to your computer and use it in GitHub Desktop.
genetic_alg.rs
/*
Что это такое? Читай начиная с https://t.me/optozorax_dev/46
*/
use enigo::*;
use spiril::unit::Unit;
use spiril::population::Population;
use rand::{thread_rng, Rng};
use std::process::{Command, Stdio};
use std::thread::sleep;
use std::time::Duration;
use std::fs;
const FILE_SERVICE_POS: (i32, i32) = (1147, 508);
const WRITE: (i32, i32) = (1124, 621);
const EXIT: (i32, i32) = (1242, 882);
const PATH: &str = "C:/Users/zorax/Desktop/TELMA/PRIMER";
fn run_async(command: &str) {
Command::new(command)
.current_dir(PATH)
.stdin(Stdio::null())
.stdout(Stdio::null())
.spawn()
.expect("failed to execute process");
}
fn click(pos: (i32, i32)) {
let mut enigo = Enigo::new();
enigo.mouse_move_to(pos.0, pos.1);
enigo.mouse_click(MouseButton::Left);
}
#[derive(Default, Debug, Clone)]
struct SredaField {
size: f32,
step: f32,
}
#[derive(Default, Debug, Clone)]
struct Sreda {
canonical_result: (Vec<f32>, i32),
x: Vec<SredaField>,
y: Vec<SredaField>,
lines_before_x: Vec<String>,
lines_after_x_before_y: Vec<String>,
lines_after_y: Vec<String>,
}
fn read_sreda(file: &str, canonical_result: (Vec<f32>, i32)) -> Sreda {
let mut result = Sreda::default();
result.canonical_result = canonical_result;
let file = fs::read_to_string(PATH.to_owned() + "/" + file).unwrap();
let mut lines = file.lines();
for _ in 0..20 {
result.lines_before_x.push(lines.next().unwrap().to_string());
}
let x_size_line = lines.next().unwrap();
result.lines_before_x.push(x_size_line.to_string());
let mut x_size: Vec<f32> = x_size_line.split_whitespace().map(|x| x.parse::<f32>().unwrap()).collect();
let x_size_next = x_size.clone();
x_size.insert(0, -6e-2);
for (a, b) in x_size.iter().zip(x_size_next.iter()) {
result.x.push(SredaField { size: b-a, step: 0.0 });
}
let x_line = lines.next().unwrap();
for (i, v) in x_line.split_whitespace().map(|x| x.parse::<f32>().unwrap()).enumerate() {
result.x[i].step = v / result.x[i].size;
}
for _ in 0..3 {
result.lines_after_x_before_y.push(lines.next().unwrap().to_string());
}
let y_size_line = lines.next().unwrap();
result.lines_after_x_before_y.push(y_size_line.to_string());
let mut y_size: Vec<f32> = y_size_line.split_whitespace().map(|y| y.parse::<f32>().unwrap()).collect();
let y_size_next = y_size.clone();
y_size.insert(0, 0.0);
for (a, b) in y_size.iter().zip(y_size_next.iter()) {
result.y.push(SredaField { size: b-a, step: 0.0 });
}
let y_line = lines.next().unwrap();
for (i, v) in y_line.split_whitespace().map(|y| y.parse::<f32>().unwrap()).enumerate() {
result.y[i].step = v / result.y[i].size;
}
for _ in 0..3 {
result.lines_after_y.push(lines.next().unwrap().to_string());
}
result
}
fn write_sreda(sreda: &Sreda) {
let mut result = String::new();
for line in &sreda.lines_before_x {
result += &line;
result += "\n";
}
for field in &sreda.x {
result += &((field.size * field.step).to_string() + " ");
}
result += "\n";
for line in &sreda.lines_after_x_before_y {
result += &line;
result += "\n";
}
for field in &sreda.y {
result += &((field.size * field.step).to_string() + " ");
}
result += "\n";
for line in &sreda.lines_after_y {
result += &line;
result += "\n";
}
fs::write(PATH.to_owned() + "/sreda", result).unwrap();
}
fn get_result() -> (Vec<f32>, i32) {
fs::remove_file(PATH.to_owned() + "/result").unwrap_or_default();
fs::remove_file(PATH.to_owned() + "/inf2tr.dat").unwrap_or_default();
run_async(&(PATH.to_owned() + "/pusk.bat"));
sleep(Duration::from_millis(1000));
click(FILE_SERVICE_POS);
sleep(Duration::from_millis(100));
click(WRITE);
sleep(Duration::from_millis(100));
click(EXIT);
let mut vec = Vec::new();
let contents = fs::read_to_string(PATH.to_owned() + "/result").unwrap();
let mut lines = contents.lines();
lines.next().unwrap();
for (index, line) in lines.enumerate() {
if index == 1 || index == 3 {
vec.push(line
.split_whitespace().nth(3).unwrap()
.parse().unwrap()
);
}
}
let count =
fs::read_to_string(PATH.to_owned() + "/inf2tr.dat")
.unwrap()
.lines().nth(1).unwrap()
.split_whitespace().nth(1).unwrap()
.parse().unwrap();
(vec, count)
}
fn init() {
fs::remove_file(PATH.to_owned() + "/sreda").unwrap_or_default();
fs::copy(PATH.to_owned() + "/sreda1", PATH.to_owned() + "/sreda").unwrap();
}
fn mutate_float(f: &mut f32) {
let mut rng = thread_rng();
*f *= rng.gen_range(0.5, 1.5);
if *f > 1.0 { *f = 1.0; }
if *f < 0.002 { *f = 0.002; }
}
impl Sreda {
fn mutate(mut self) -> Self {
let mut rng = thread_rng();
if rng.gen() {
let pos = rng.gen_range(0, self.x.len());
mutate_float(&mut self.x[pos].step);
} else {
let pos = rng.gen_range(0, self.y.len());
mutate_float(&mut self.y[pos].step);
}
self
}
}
static mut BEST_RESULT: i32 = 1_000_000;
static mut FUNCTION_CALLS: i32 = 0;
impl Unit for Sreda {
fn fitness(&self) -> f64 {
unsafe {
FUNCTION_CALLS += 1;
}
write_sreda(self);
let result = get_result();
let all_values_in_one_percentile = self.canonical_result.0
.iter().zip(result.0.iter())
.all(|(&a, &b)| (1.0 - (a/b)).abs() < 0.01);
if all_values_in_one_percentile {
unsafe {
if result.1 < BEST_RESULT {
BEST_RESULT = result.1;
write_sreda(self);
fs::copy(PATH.to_owned() + "/sreda", PATH.to_owned() + "/sreda_" + &result.1.to_string()).unwrap();
println!("Found new best! Score: {}, Calls: {}", BEST_RESULT, FUNCTION_CALLS);
}
}
1.0/result.1 as f64
} else {
1.0/10000.0
}
}
fn breed_with(&self, other: &Sreda) -> Sreda {
let mut result = self.clone();
let mut rng = thread_rng();
for (a, b) in result.x.iter_mut().zip(other.x.iter()).filter(|_| rng.gen()) {
a.step = b.step;
}
for (a, b) in result.y.iter_mut().zip(other.y.iter()).filter(|_| rng.gen()) {
a.step = b.step;
}
result.mutate()
}
}
fn main() {
init();
let canonical_sreda = read_sreda("sreda1", (vec![0.0], 0));
write_sreda(&canonical_sreda);
let canonical_result = get_result();
let sreda = read_sreda("sreda_162", canonical_result.clone());
println!("canonical: {:#?}", canonical_result);
write_sreda(&sreda);
println!("162: {:#?}", get_result());
let units: Vec<Sreda> = (0..15)
.map(|_| sreda.clone().mutate())
.collect();
let mut pop = Population::new(units);
pop.set_size(15)
.set_breed_factor(0.3)
.set_survival_factor(0.5);
for i in 0..100 {
pop.epochs(1);
println!("Generation {} --------------------------", i);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment