radiate-extensions 0.1.1

Extensions for radiate. Genetic Programming implementations for graphs (neural networks) and regression analysis
Documentation
use std::ops::{Add, Mul, Sub};
use std::sync::Arc;

use num_traits::Float;
use radiate::engines::alterers::mutators::mutate::Mutate;
use radiate::engines::genome::genes::gene::Gene;
use radiate::{Alterer, RandomProvider};
use rand::distributions::uniform::SampleUniform;
use rand::{distributions::Standard, prelude::Distribution};

use crate::architects::node_collections::node::Node;
use crate::architects::node_collections::node_factory::NodeFactory;
use crate::operations::op::Ops;

pub struct OpMutator<T>
where
    Standard: Distribution<T>,
    T: Clone + PartialEq + Default + Float,
{
    pub rate: f32,
    pub replace_rate: f32,
    pub factory: NodeFactory<T>,
}

impl<T> OpMutator<T>
where
    Standard: Distribution<T>,
    T: Clone + PartialEq + Default + Float + SampleUniform + 'static,
{
    pub fn alterer(
        factory: NodeFactory<T>,
        rate: f32,
        replace_rate: f32,
    ) -> Alterer<Node<T>, Ops<T>> {
        Alterer::Mutation(Box::new(Self {
            rate,
            replace_rate,
            factory,
        }))
    }
}

impl<T> Mutate<Node<T>, Ops<T>> for OpMutator<T>
where
    T: Clone
        + PartialEq
        + Default
        + Mul<Output = T>
        + Sub<Output = T>
        + Add<Output = T>
        + Float
        + SampleUniform,
    Standard: Distribution<T>,
{
    fn mutate_rate(&self) -> f32 {
        self.rate
    }

    fn name(&self) -> &'static str {
        "OpMutator"
    }

    #[inline]
    fn mutate_gene(&self, gene: &Node<T>) -> Node<T> {
        match gene.allele() {
            Ops::MutableConst(name, arity, value, supplier, operation) => {
                let random_value =
                    RandomProvider::random::<T>() * T::from(2).unwrap() - T::from(1).unwrap();

                if RandomProvider::random::<f32>() < self.replace_rate {
                    gene.from_allele(&Ops::MutableConst(
                        &name,
                        *arity,
                        random_value,
                        Arc::clone(supplier),
                        Arc::clone(operation),
                    ))
                } else {
                    let new_value = random_value + value.clone();
                    gene.from_allele(&Ops::MutableConst(
                        &name,
                        *arity,
                        new_value,
                        Arc::clone(supplier),
                        Arc::clone(operation),
                    ))
                }
            }
            _ => {
                let temp_node = self.factory.new_node(gene.index, gene.node_type);
                if temp_node.value.arity() == gene.value.arity() {
                    return gene.from_allele(temp_node.allele());
                }

                gene.clone()
            }
        }
    }
}