use std::error;
use std::fmt::{self, Debug};
use std::num::TryFromIntError;
use crate::gene::NeuronId;
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum Error {
EmptyGenome,
InvalidInputCount(usize, NeuronId),
NotEnoughInputs(usize, NeuronId),
DuplicateNeuronId(usize, usize, NeuronId),
NonNeuronOutput(usize),
InvalidJumperSource(usize, NeuronId),
InvalidForwardJumper(usize),
Arithmetic,
}
impl fmt::Display for Error {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::EmptyGenome => write!(f, "empty genome"),
Self::InvalidInputCount(index, id) => write!(
f,
"invalid input count for neuron {} at index {}",
id.as_usize(),
index
),
Self::NotEnoughInputs(index, id) => write!(
f,
"not enough inputs to neuron {} at index {}",
id.as_usize(),
index
),
Self::DuplicateNeuronId(index_a, index_b, id) => write!(
f,
"duplicate neuron ID {} at indices {} and {}",
id.as_usize(),
index_a,
index_b
),
Self::NonNeuronOutput(index) => {
write!(f, "non-neuron gene at index {} is a network output", index)
}
Self::InvalidJumperSource(index, source_id) => {
write!(
f,
"jumper gene at index {} points to invalid neuron ID {}",
index,
source_id.as_usize()
)
}
Self::InvalidForwardJumper(index) => {
write!(f, "invalid forward jumper connection at index {}", index)
}
Self::Arithmetic => {
write!(f, "integer overflow/underflow")
}
}
}
}
impl error::Error for Error {}
impl From<TryFromIntError> for Error {
fn from(_: TryFromIntError) -> Self {
Self::Arithmetic
}
}
#[derive(Clone, Debug, PartialEq, Eq)]
pub enum MutationError {
Empty,
InvalidParent,
InvalidJumperSource,
InvalidForwardJumper,
RemoveInvalidIndex,
RemoveNeuron,
RemoveOnlyInput,
Arithmetic,
}
impl fmt::Display for MutationError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match self {
Self::Empty => write!(f, "mutation contains no non-neuron genes"),
Self::InvalidParent => write!(f, "invalid parent neuron ID"),
Self::InvalidJumperSource => write!(f, "jumper gene points to invalid neuron ID"),
Self::InvalidForwardJumper => write!(f, "invalid forward jumper connection"),
Self::RemoveInvalidIndex => write!(f, "removal index out of bounds"),
Self::RemoveNeuron => write!(f, "cannot remove a neuron gene"),
Self::RemoveOnlyInput => {
write!(f, "cannot remove only incoming connection gene of a neuron")
}
Self::Arithmetic => write!(f, "integer overflow/underflow"),
}
}
}
impl error::Error for MutationError {}
#[derive(Clone, Debug)]
pub struct MismatchedLengthsError;
impl fmt::Display for MismatchedLengthsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"length of source array does not equal length of target array"
)
}
}
impl error::Error for MismatchedLengthsError {}
#[derive(Clone, Debug)]
pub struct IndexOutOfBoundsError;
impl fmt::Display for IndexOutOfBoundsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(f, "index out of bounds")
}
}
impl error::Error for IndexOutOfBoundsError {}
#[derive(Clone, Debug, PartialEq, Eq)]
pub struct NotEnoughInputsError {
expected: usize,
provided: usize,
}
impl NotEnoughInputsError {
pub(crate) fn new(expected: usize, provided: usize) -> Self {
Self { expected, provided }
}
}
impl fmt::Display for NotEnoughInputsError {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
write!(
f,
"too few inputs to a network: expected {}, provided {}",
self.expected, self.provided
)
}
}
impl error::Error for NotEnoughInputsError {}