radiate-extensions 0.1.1

Extensions for radiate. Genetic Programming implementations for graphs (neural networks) and regression analysis
Documentation
use radiate::engines::codexes::Codex;
use radiate::engines::genome::chromosome::Chromosome;
use radiate::engines::genome::genes::gene::Gene;
use radiate::engines::genome::genotype::Genotype;

use crate::architects::*;
use crate::operations::op::Ops;

pub struct GraphCodex<'a, T>
where
    T: Clone + PartialEq + Default,
{
    pub input_size: usize,
    pub output_size: usize,
    pub factory: &'a NodeFactory<T>,
    pub nodes: Vec<Node<T>>,
}

impl<'a, T> GraphCodex<'a, T>
where
    T: Clone + PartialEq + Default,
{
    pub fn from_factory(factory: &'a NodeFactory<T>) -> Self {
        GraphCodex::from_shape(1, 1, factory)
    }

    pub fn from_shape(input_size: usize, output_size: usize, factory: &'a NodeFactory<T>) -> Self {
        let nodes = Architect::<Graph<T>, T>::new(&factory)
            .acyclic(input_size, output_size)
            .iter()
            .map(|node| node.clone())
            .collect::<Vec<Node<T>>>();

        GraphCodex::from_nodes(nodes, factory)
    }

    pub fn from_nodes(nodes: Vec<Node<T>>, factory: &'a NodeFactory<T>) -> Self {
        GraphCodex {
            input_size: nodes
                .iter()
                .filter(|node| node.node_type == NodeType::Input)
                .count(),
            output_size: nodes
                .iter()
                .filter(|node| node.node_type == NodeType::Output)
                .count(),
            factory,
            nodes,
        }
    }

    pub fn set_nodes<F>(mut self, node_fn: F) -> Self
    where
        F: Fn(&Architect<Graph<T>, T>, NodeCollectionBuilder<Graph<T>, T>) -> Graph<T>,
    {
        let graph = Architect::<Graph<T>, T>::new(&self.factory)
            .build(|arc, builder| node_fn(arc, builder));

        self.nodes = graph
            .iter()
            .map(|node| node.clone())
            .collect::<Vec<Node<T>>>();
        self.input_size = graph
            .iter()
            .filter(|node| node.node_type == NodeType::Input)
            .count();
        self.output_size = graph
            .iter()
            .filter(|node| node.node_type == NodeType::Output)
            .count();
        self
    }
}

impl<'a, T> Codex<Node<T>, Ops<T>, Graph<T>> for GraphCodex<'a, T>
where
    T: Clone + PartialEq + Default,
{
    fn encode(&self) -> Genotype<Node<T>, Ops<T>> {
        Genotype {
            chromosomes: vec![Chromosome::from_genes(
                self.nodes
                    .iter()
                    .map(|node| {
                        let temp_node = self.factory.new_node(node.index, node.node_type);

                        if temp_node.value.arity() == node.value.arity() {
                            node.from_allele(&temp_node.allele());
                        }

                        node.clone()
                    })
                    .collect::<Vec<Node<T>>>(),
            )],
        }
    }

    fn decode(&self, genotype: &Genotype<Node<T>, Ops<T>>) -> Graph<T> {
        Graph::from_nodes(
            genotype
                .iter()
                .next()
                .unwrap()
                .iter()
                .map(|node| node.clone())
                .collect::<Vec<Node<T>>>(),
        )
    }
}