radiate-engines 1.3.1

Engines for the Radiate genetic algorithm library.
Documentation
#![cfg(feature = "serde")]

use crate::Generation;
use crate::{
    FileWriter,
    events::{CheckpointSaved, Warning},
};
use crate::{
    Handler,
    events::{EventContext, EventHandler, GenerationSnapshot},
};
use radiate_core::{Chromosome, error::RadiateResult};
use serde::Serialize;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};

pub struct CheckpointWriterHandler<C, T>
where
    C: Chromosome + Clone + 'static,
    T: Clone + Send + Sync + 'static,
{
    pub(crate) interval: usize,
    pub(crate) path: PathBuf,
    pub(crate) writer: Arc<Mutex<dyn FileWriter<Generation<C, T>> + Send + Sync>>,
}

impl<C, T> CheckpointWriterHandler<C, T>
where
    C: Chromosome + Clone + 'static,
    T: Clone + Send + Sync + 'static,
{
    pub fn new<F>(interval: usize, path: PathBuf, writer: F) -> Self
    where
        F: FileWriter<Generation<C, T>> + Send + Sync + 'static,
    {
        Self {
            interval,
            path,
            writer: Arc::new(Mutex::new(writer)),
        }
    }
}

impl<C, T> EventHandler for CheckpointWriterHandler<C, T>
where
    C: Chromosome + Clone + Serialize + 'static,
    T: Clone + Send + Sync + Serialize + 'static,
{
    fn start(&mut self, ctx: &EventContext<'_, Self>) -> RadiateResult<()> {
        ctx.subscribe::<GenerationSnapshot<C, T>>()
            .schedule(self.interval)?;
        Ok(())
    }
}

impl<C, T> Handler<GenerationSnapshot<C, T>> for CheckpointWriterHandler<C, T>
where
    C: Chromosome + Clone + Serialize + 'static,
    T: Clone + Send + Sync + Serialize + 'static,
{
    fn handle(&mut self, message: &GenerationSnapshot<C, T>, ctx: &EventContext<'_, Self>) {
        let generation = &message.generation;
        let mut writer = self.writer.lock().unwrap();

        let file_path = self.path.join(format!(
            "chckpnt_{}.{}",
            generation.index(),
            writer.extension()
        ));

        match writer.write(file_path.clone(), generation) {
            Ok(_) => {
                ctx.publish(CheckpointSaved {
                    index: generation.index(),
                    path: file_path.into_string().unwrap_or_default(),
                });
            }
            Err(err) => {
                ctx.publish(Warning(err.to_string()));
            }
        };
    }
}