Mutation

Struct Mutation 

Source
pub struct Mutation { /* private fields */ }
Expand description

Genetic Program mutation. Configures crossover (mating) on GP individuals.

Implementations§

Source§

impl Mutation

Source

pub fn uniform() -> Mutation

Perform mutation by randomly replacing a node with a new subtree.

Examples found in repository?
examples/snake.rs (line 272)
251fn main() {
252    let mut rng = OsRng::new().unwrap();
253    let mut tree_gen = TreeGen::full(&mut rng, 1, 4);
254
255    let mut indv1: Individual<SnakeTree> = Individual::new(&mut tree_gen);
256    let mut indv2: Individual<SnakeTree> = Individual::new(&mut tree_gen);
257
258    let mut rng = OsRng::new().unwrap();
259    let crossover = Crossover::one_point();
260    println!("---");
261    println!("{}", indv1);
262    println!("{}", indv2);
263    println!("---");
264    crossover.mate(&mut indv1, &mut indv2, &mut rng);
265    println!("{}", indv1);
266    println!("{}", indv2);
267    println!("---");
268
269    println!("{}", indv1);
270    let mut mutate_rng = OsRng::new().unwrap();
271    let mut tree_gen = TreeGen::full(&mut mutate_rng, 1, 2);
272    let mutation = Mutation::uniform();
273    mutation.mutate(&mut indv1, &mut tree_gen);
274    println!("{}", indv1);
275
276    let mut env = SnakeEnvironment {
277        size: Vector { x: 10, y: 10 },
278        food: Vector { x: 9, y: 9 },
279        snake: vec![Vector { x: 3, y: 3 }, Vector { x: 4, y: 3 }],
280    };
281
282    for _ in 0..200 {
283        let indv: Individual<SnakeTree> = Individual::new(&mut tree_gen);
284
285        let mut score1 = 0;
286        let mut score2 = 0;
287        let mut tick = 100;
288        while tick > 0 {
289            //println!("{:?} {:?}", tick, env.snake);
290            let move_ = indv.tree.evaluate(&env);
291            if env.sense_danger(move_) {
292                break;
293            }
294            if env.sense_food(move_) {
295                score2 += 1;
296                tick += 100;
297                env.food = Vector {
298                    x: rng.gen_range(0, 11),
299                    y: rng.gen_range(0, 11),
300                };
301            }
302            env.perform_movement(move_);
303            score1 += 1;
304            tick -= 1;
305        }
306        if score2 >= 1 {
307            println!("lived={:?} ate={:?}", score1, score2);
308            println!("{}", indv);
309        }
310    }
311}
More examples
Hide additional examples
examples/symbolic_regression.rs (line 159)
150fn main() {
151    let mut rng = OsRng::new().unwrap();
152    let mut tree_gen = TreeGen::full(&mut rng, 1, 4);
153
154    let mut rng = OsRng::new().unwrap();
155    let crossover = Crossover::one_point();
156
157    let mut mutate_rng = OsRng::new().unwrap();
158    let mut mut_tree_gen = TreeGen::full(&mut mutate_rng, 1, 2);
159    let mutation = Mutation::uniform();
160
161    let inputs: Vec<f64> = (-10..11).map(|i| (i as f64) / 10.0).collect();
162    let expecteds: Vec<f64> = inputs.iter()
163        .cloned()
164        .map(|i| i.powi(4) + i.powi(3) + i.powi(2) + i)
165        .collect();
166
167    let mut population: Vec<Individual<Equation>> =
168        (0..200).map(|_| Individual::new(&mut tree_gen)).collect();
169    for round in 0..40 {
170        let mut ranking = BinaryHeap::new();
171        for individual in population.drain(..) {
172            let mut sum_of_squared_errors = 0.0;
173            for i in 0..inputs.len() {
174                let input = inputs[i];
175                let expected = expecteds[i];
176                let output = individual.tree.evaluate(&input);
177                let squared_error = (output - expected).powi(2);
178                sum_of_squared_errors += squared_error;
179            }
180            if !sum_of_squared_errors.is_finite() {
181                sum_of_squared_errors = 100000000000.0;
182            }
183            ranking.push(RankedIndividual(sum_of_squared_errors, individual));
184        }
185
186        let ranking = ranking.into_sorted_vec();
187        //println!("{:?}", ranking);
188
189        println!("=== ROUND {} ===", round);
190        for i in 0..3 {
191            println!("Rank {:?}\n  Range = [-1.0, 1.0]    Step = +0.1\n  Comparing to x^4 + x^3 \
192                      + x^2 + x\n  Sum of squared error = {}\n  Equation = {}",
193                     i,
194                     ranking[i].0,
195                     ranking[i].1);
196        }
197
198        for i in 0..100 {
199            let RankedIndividual(_, mut indv1) = ranking[i].clone();
200            let RankedIndividual(_, mut indv2) = ranking[i + 1].clone();
201
202            population.push(indv1.clone());
203            population.push(indv2.clone());
204
205            crossover.mate(&mut indv1, &mut indv2, &mut rng);
206
207            if rng.gen() {
208                mutation.mutate(&mut indv1, &mut mut_tree_gen);
209            }
210            if rng.gen() {
211                mutation.mutate(&mut indv2, &mut mut_tree_gen);
212            }
213
214            population.push(indv1);
215            population.push(indv2);
216        }
217
218        println!();
219    }
220}
Source

pub fn mutate<T, R>(&self, indv: &mut Individual<T>, tg: &mut TreeGen<'_, R>)
where T: Tree, R: Rng,

Mutate an individual according to the configured mutation mode.

Examples found in repository?
examples/snake.rs (line 273)
251fn main() {
252    let mut rng = OsRng::new().unwrap();
253    let mut tree_gen = TreeGen::full(&mut rng, 1, 4);
254
255    let mut indv1: Individual<SnakeTree> = Individual::new(&mut tree_gen);
256    let mut indv2: Individual<SnakeTree> = Individual::new(&mut tree_gen);
257
258    let mut rng = OsRng::new().unwrap();
259    let crossover = Crossover::one_point();
260    println!("---");
261    println!("{}", indv1);
262    println!("{}", indv2);
263    println!("---");
264    crossover.mate(&mut indv1, &mut indv2, &mut rng);
265    println!("{}", indv1);
266    println!("{}", indv2);
267    println!("---");
268
269    println!("{}", indv1);
270    let mut mutate_rng = OsRng::new().unwrap();
271    let mut tree_gen = TreeGen::full(&mut mutate_rng, 1, 2);
272    let mutation = Mutation::uniform();
273    mutation.mutate(&mut indv1, &mut tree_gen);
274    println!("{}", indv1);
275
276    let mut env = SnakeEnvironment {
277        size: Vector { x: 10, y: 10 },
278        food: Vector { x: 9, y: 9 },
279        snake: vec![Vector { x: 3, y: 3 }, Vector { x: 4, y: 3 }],
280    };
281
282    for _ in 0..200 {
283        let indv: Individual<SnakeTree> = Individual::new(&mut tree_gen);
284
285        let mut score1 = 0;
286        let mut score2 = 0;
287        let mut tick = 100;
288        while tick > 0 {
289            //println!("{:?} {:?}", tick, env.snake);
290            let move_ = indv.tree.evaluate(&env);
291            if env.sense_danger(move_) {
292                break;
293            }
294            if env.sense_food(move_) {
295                score2 += 1;
296                tick += 100;
297                env.food = Vector {
298                    x: rng.gen_range(0, 11),
299                    y: rng.gen_range(0, 11),
300                };
301            }
302            env.perform_movement(move_);
303            score1 += 1;
304            tick -= 1;
305        }
306        if score2 >= 1 {
307            println!("lived={:?} ate={:?}", score1, score2);
308            println!("{}", indv);
309        }
310    }
311}
More examples
Hide additional examples
examples/symbolic_regression.rs (line 208)
150fn main() {
151    let mut rng = OsRng::new().unwrap();
152    let mut tree_gen = TreeGen::full(&mut rng, 1, 4);
153
154    let mut rng = OsRng::new().unwrap();
155    let crossover = Crossover::one_point();
156
157    let mut mutate_rng = OsRng::new().unwrap();
158    let mut mut_tree_gen = TreeGen::full(&mut mutate_rng, 1, 2);
159    let mutation = Mutation::uniform();
160
161    let inputs: Vec<f64> = (-10..11).map(|i| (i as f64) / 10.0).collect();
162    let expecteds: Vec<f64> = inputs.iter()
163        .cloned()
164        .map(|i| i.powi(4) + i.powi(3) + i.powi(2) + i)
165        .collect();
166
167    let mut population: Vec<Individual<Equation>> =
168        (0..200).map(|_| Individual::new(&mut tree_gen)).collect();
169    for round in 0..40 {
170        let mut ranking = BinaryHeap::new();
171        for individual in population.drain(..) {
172            let mut sum_of_squared_errors = 0.0;
173            for i in 0..inputs.len() {
174                let input = inputs[i];
175                let expected = expecteds[i];
176                let output = individual.tree.evaluate(&input);
177                let squared_error = (output - expected).powi(2);
178                sum_of_squared_errors += squared_error;
179            }
180            if !sum_of_squared_errors.is_finite() {
181                sum_of_squared_errors = 100000000000.0;
182            }
183            ranking.push(RankedIndividual(sum_of_squared_errors, individual));
184        }
185
186        let ranking = ranking.into_sorted_vec();
187        //println!("{:?}", ranking);
188
189        println!("=== ROUND {} ===", round);
190        for i in 0..3 {
191            println!("Rank {:?}\n  Range = [-1.0, 1.0]    Step = +0.1\n  Comparing to x^4 + x^3 \
192                      + x^2 + x\n  Sum of squared error = {}\n  Equation = {}",
193                     i,
194                     ranking[i].0,
195                     ranking[i].1);
196        }
197
198        for i in 0..100 {
199            let RankedIndividual(_, mut indv1) = ranking[i].clone();
200            let RankedIndividual(_, mut indv2) = ranking[i + 1].clone();
201
202            population.push(indv1.clone());
203            population.push(indv2.clone());
204
205            crossover.mate(&mut indv1, &mut indv2, &mut rng);
206
207            if rng.gen() {
208                mutation.mutate(&mut indv1, &mut mut_tree_gen);
209            }
210            if rng.gen() {
211                mutation.mutate(&mut indv2, &mut mut_tree_gen);
212            }
213
214            population.push(indv1);
215            population.push(indv2);
216        }
217
218        println!();
219    }
220}

Trait Implementations§

Source§

impl Clone for Mutation

Source§

fn clone(&self) -> Mutation

Returns a duplicate of the value. Read more
1.0.0 · Source§

fn clone_from(&mut self, source: &Self)

Performs copy-assignment from source. Read more
Source§

impl Debug for Mutation

Source§

fn fmt(&self, f: &mut Formatter<'_>) -> Result

Formats the value using the given formatter. Read more
Source§

impl PartialEq for Mutation

Source§

fn eq(&self, other: &Mutation) -> bool

Tests for self and other values to be equal, and is used by ==.
1.0.0 · Source§

fn ne(&self, other: &Rhs) -> bool

Tests for !=. The default implementation is almost always sufficient, and should not be overridden without very good reason.
Source§

impl Copy for Mutation

Source§

impl StructuralPartialEq for Mutation

Auto Trait Implementations§

Blanket Implementations§

Source§

impl<T> Any for T
where T: 'static + ?Sized,

Source§

fn type_id(&self) -> TypeId

Gets the TypeId of self. Read more
Source§

impl<T> Borrow<T> for T
where T: ?Sized,

Source§

fn borrow(&self) -> &T

Immutably borrows from an owned value. Read more
Source§

impl<T> BorrowMut<T> for T
where T: ?Sized,

Source§

fn borrow_mut(&mut self) -> &mut T

Mutably borrows from an owned value. Read more
Source§

impl<T> CloneToUninit for T
where T: Clone,

Source§

unsafe fn clone_to_uninit(&self, dest: *mut u8)

🔬This is a nightly-only experimental API. (clone_to_uninit)
Performs copy-assignment from self to dest. Read more
Source§

impl<T> From<T> for T

Source§

fn from(t: T) -> T

Returns the argument unchanged.

Source§

impl<T, U> Into<U> for T
where U: From<T>,

Source§

fn into(self) -> U

Calls U::from(self).

That is, this conversion is whatever the implementation of From<T> for U chooses to do.

Source§

impl<T> ToOwned for T
where T: Clone,

Source§

type Owned = T

The resulting type after obtaining ownership.
Source§

fn to_owned(&self) -> T

Creates owned data from borrowed data, usually by cloning. Read more
Source§

fn clone_into(&self, target: &mut T)

Uses borrowed data to replace owned data, usually by cloning. Read more
Source§

impl<T, U> TryFrom<U> for T
where U: Into<T>,

Source§

type Error = Infallible

The type returned in the event of a conversion error.
Source§

fn try_from(value: U) -> Result<T, <T as TryFrom<U>>::Error>

Performs the conversion.
Source§

impl<T, U> TryInto<U> for T
where U: TryFrom<T>,

Source§

type Error = <U as TryFrom<T>>::Error

The type returned in the event of a conversion error.
Source§

fn try_into(self) -> Result<U, <U as TryFrom<T>>::Error>

Performs the conversion.