1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
extern crate rand;
use std::mem;
use std::sync::{Arc, RwLock};
use std::marker::PhantomData;
use rand::prelude::SliceRandom;
use rayon::prelude::*;
use super::generation::{Member, MemberWeak};
use super::genome::{Genome};
#[derive(Debug, Clone)]
pub struct NicheMember<T>(pub f32, pub MemberWeak<T>);
#[derive(Debug, Clone)]
pub struct Niche<T, E> {
pub mascot: Member<T>,
pub members: Vec<NicheMember<T>>,
pub age: i32,
pub total_adjusted_fitness: Option<f32>,
phantom: PhantomData<E>
}
impl<T, E> Niche<T, E>
where
T: Genome<T, E> + Send + Sync + Clone,
E: Send + Sync
{
pub fn new(mascot: &Member<T>, mascot_fitness: f32) -> Self {
Niche {
mascot: Arc::clone(mascot),
members: vec![NicheMember(mascot_fitness, Arc::downgrade(mascot))],
age: 0,
total_adjusted_fitness: None,
phantom: PhantomData
}
}
pub fn fittest(&self) -> (f32, Member<T>) {
let mut top: Option<&NicheMember<T>> = None;
for i in self.members.iter() {
if top.is_none() || i.0 > top.unwrap().0 {
top = Some(i);
}
}
match top {
Some(t) => (t.0, Arc::new(RwLock::new((*t.1.upgrade().unwrap()).read().unwrap().clone()))),
None => panic!("Failed to get top species member.")
}
}
pub fn reset(&mut self) {
let new_mascot = self.members.choose(&mut rand::thread_rng());
match new_mascot {
Some(member) => {
self.age += 1;
self.total_adjusted_fitness = None;
self.mascot = Arc::new(RwLock::new((*member.1.upgrade().unwrap()).read().unwrap().clone()));
self.members = Vec::new();
},
None => panic!("Failed to get new mascot")
}
}
pub fn calculate_total_adjusted_fitness(&mut self) {
let length = self.members.len() as f32;
self.total_adjusted_fitness = Some(
self.members
.par_iter_mut()
.map(|x| {
x.0 = x.0 / length;
x.0
})
.sum()
)
}
pub fn get_total_adjusted_fitness(&self) -> f32 {
match self.total_adjusted_fitness {
Some(fit) => fit,
None => panic!("Total adjusted fitness for this species was not set")
}
}
pub fn display_info(&self) {
let address: u64 = unsafe { mem::transmute(self) };
println!("Species: {} gens( {} ) members( {} ) adj fit( {:.3} )",
address,
self.age,
self.members.len(),
self.total_adjusted_fitness.unwrap(),
);
}
}