sequence/
sequence.rs

1// Copyright 2019 Brendan Cox
2// 
3// Licensed under the Apache License, Version 2.0 (the "License");
4// you may not use this file except in compliance with the License.
5// You may obtain a copy of the License at
6//
7//    http://www.apache.org/licenses/LICENSE-2.0
8//
9// Unless required by applicable law or agreed to in writing, software
10// distributed under the License is distributed on an "AS IS" BASIS,
11// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12// See the License for the specific language governing permissions and
13// limitations under the License.
14
15extern crate aristeia;
16extern crate rand;
17
18use self::Gene::{
19    MovePointerLeft,
20    MovePointerRight,
21    IncreaseValueByOne,
22    DecreaseValueByOne,
23    CopyValueFromLeft,
24    CopyValueFromRight
25};
26use rand::{
27    distributions::{Distribution, Standard},
28    Rng,
29};
30use std::time::Instant;
31use aristeia::agent::{Agent};
32
33use aristeia::manager::create_manager;
34use aristeia::fitness::ScoreError;
35
36
37#[derive(Clone, PartialEq, Hash)]
38enum Gene {
39    MovePointerLeft,
40    MovePointerRight,
41    IncreaseValueByOne,
42    DecreaseValueByOne,
43    CopyValueFromLeft,
44    CopyValueFromRight
45}
46
47pub fn main() {
48    let now = Instant::now();
49
50    let data = vec![0; 10];
51
52    let mut manager = create_manager(fitness_function, data.clone());
53    manager.set_number_of_genes(30, false);
54    manager.run(9999);
55    let agents = manager.get_population().get_agents();
56
57    println!("Duration: {}", now.elapsed().as_secs() as f64 + now.elapsed().subsec_nanos() as f64 * 1e-9);
58    println!("Population: {}", agents.len());
59
60    let mut first = true;
61    let mut first_score = 0;
62
63    for (score_index, agent) in agents.iter().rev() {
64        if first {
65            first = false;
66            first_score = *score_index;
67        }
68        if score_index < &(first_score - 20) {
69            break;
70        }
71        println!("{}", score_index);
72        println!("{:?}", get_processed_data(agent.get_genes(), &data));
73    }
74}
75
76fn get_processed_data(genes: &Vec<Gene>, data: &Vec<u8>) -> Vec<u8> {
77    let mut copy = data.clone();
78    let mut pointer = 0;
79    for gene in genes {
80        match gene {
81            MovePointerLeft => move_pointer_left(&mut pointer, &mut copy),
82            MovePointerRight => move_pointer_right(&mut pointer, &mut copy),
83            IncreaseValueByOne => increase_value_by_one(&mut pointer, &mut copy),
84            DecreaseValueByOne => decrease_value_by_one(&mut pointer, &mut copy),
85            CopyValueFromLeft => copy_value_from_left(&mut pointer, &mut copy),
86            CopyValueFromRight => copy_value_from_right(&mut pointer, &mut copy),
87        }
88    }
89
90    return copy;
91}
92
93fn move_pointer_left(pointer: &mut usize, _data: &mut Vec<u8>) {
94    if *pointer == 0 {
95        return;
96    }
97
98    *pointer -= 1;
99}
100
101fn move_pointer_right(pointer: &mut usize, data: &mut Vec<u8>) {
102    if *pointer == data.len() - 1 {
103        return;
104    }
105
106    *pointer += 1;
107}
108
109fn increase_value_by_one(pointer: &mut usize, data: &mut Vec<u8>) {
110    data[*pointer] += 1;
111}
112
113fn decrease_value_by_one(pointer: &mut usize, data: &mut Vec<u8>) {
114    if data[*pointer] == 0 {
115        return;
116    }
117    data[*pointer] -= 1;
118}
119
120fn copy_value_from_left(pointer: &mut usize, data: &mut Vec<u8>) {
121    if *pointer == 0 {
122        return;
123    }
124
125    data[*pointer] = data[*pointer-1];
126}
127
128fn copy_value_from_right(pointer: &mut usize, data: &mut Vec<u8>) {
129    if *pointer == data.len() - 1 {
130        return;
131    }
132
133    data[*pointer] = data[*pointer+1];
134}
135
136impl Distribution<Gene> for Standard {
137    fn sample<R: Rng + ?Sized>(&self, rng: &mut R) -> Gene {
138        match rng.gen_range(0, 6) {
139            0 => MovePointerLeft,
140            1 => MovePointerRight,
141            2 => IncreaseValueByOne,
142            3 => DecreaseValueByOne,
143            4 => CopyValueFromLeft,
144            _ => CopyValueFromRight
145        }
146    }
147}
148
149fn score_data(candidate: &Vec<u8>) -> u64 {
150    let mut score = 1.0;
151    let candidate_length_squared = candidate.len().pow(2) as f64;
152    let max_loss = 1.0 / candidate_length_squared;
153
154    for i in 1..candidate.len() {
155        let previous = candidate[i - 1];
156        let expected = previous + 1;
157        let value = candidate[i];
158        if value == 0 {
159            score = score - max_loss;
160            continue;
161        }
162
163        let diff = value as f64 - expected as f64;
164        score = score - (diff.abs() / candidate_length_squared);
165
166        if score < 0.0 {
167            score = 0.0;
168            break;
169        }
170    }
171
172    (score * 10000.0) as u64
173}
174
175fn fitness_function(agent: &Agent<Gene>, data: &Vec<u8>) -> Result<u64, ScoreError> {
176    let processed = get_processed_data(agent.get_genes(), data);
177    Ok(score_data(&processed))
178}