radiate-engines 1.3.0

Engines for the Radiate genetic algorithm library.
Documentation
#[cfg(feature = "serde")]
use crate::FileWriter;
use crate::{EvolutionContext, Generation, runtime::RuntimeAction};
use radiate_core::{Chromosome, Engine, Objective, error::RadiateResult};
#[cfg(feature = "serde")]
use serde::Serialize;
#[cfg(feature = "serde")]
use std::path::PathBuf;
use tracing::info;

pub(crate) struct LoggingAction(pub usize);

impl<C, T, E> RuntimeAction<E> for LoggingAction
where
    E: Engine<Epoch = Generation<C, T>, Ctx = EvolutionContext<C, T>>,
    C: Chromosome + Clone,
    T: Clone + Send + Sync,
{
    fn execute(&mut self, ctx: &E::Ctx) -> RadiateResult<()> {
        if !ctx.index.is_multiple_of(self.0) {
            return Ok(());
        }

        let time = ctx
            .metrics
            .time()
            .and_then(|m| m.times().map(|t| t.sum()))
            .unwrap_or_default();

        match ctx.objective {
            Objective::Single(_) => {
                info!(
                    "Epoch {:<4} | Score: {:>8.4} | Time: {:>5.2?}",
                    ctx.index,
                    ctx.score.as_ref().unwrap().as_f32(),
                    time
                );
            }
            Objective::Multi(_) => {
                let front_size = ctx.metrics.front_size();
                let front_size_value = front_size.map(|ent| ent.last_value()).unwrap_or(0.0);
                info!(
                    "Epoch {:<4} | Front Size: {:.3} | Time: {:>5.2?}",
                    ctx.index, front_size_value, time
                );
            }
        }

        Ok(())
    }
}

#[cfg(feature = "serde")]
pub(crate) struct CheckpointAction<E>
where
    E: Engine,
    E::Epoch: Serialize,
{
    pub(crate) interval: usize,
    pub(crate) path: PathBuf,
    pub(crate) writer: Box<dyn FileWriter<E::Epoch>>,
}

#[cfg(feature = "serde")]
impl<C, T, E> RuntimeAction<E> for CheckpointAction<E>
where
    E: Engine<Epoch = Generation<C, T>, Ctx = EvolutionContext<C, T>>,
    C: Chromosome + Clone,
    T: Clone + Send + Sync,
    E::Epoch: Serialize,
{
    fn execute(&mut self, guard: &E::Ctx) -> RadiateResult<()> {
        if guard.index.is_multiple_of(self.interval) {
            let file_path = self.path.join(format!(
                "chckpnt_{}.{}",
                guard.index,
                self.writer.extension()
            ));

            self.writer.write(file_path, &E::Epoch::from(guard))?;
        }

        Ok(())
    }
}