I have function for mutation
, which takes 3d Vec
of Vec
s and "mutates" every pair in each of the sequential pairs (using chunks(2)
for this) given some probability.
children
is a 3d matrix of shape (n_pop, n_teams, team_len)
of Player
structure.
mut_prob
is some real value from [0, 1]
range.
pub struct Player {
sex: String,
age: usize,
city: String,
}
fn mutation(&self, children: &[Vec<Vec<Player>>]) -> Vec<Vec<Vec<Player>>> {
let range = Uniform::from(0. ..1.);
// let mutation_type = "replace"; // make split and combine later
for current_set_teams in children {
let range_over_indices = Uniform::from(1..team_len - 1);
let probs = rand::thread_rng().sample_iter(&range).take(n_teams);
current_set_teams
.chunks(2)
.zip(probs)
.map(|(pair, prob)| {
let change_ptr = rand::thread_rng().sample(range_over_indices);
if prob > mut_prob {
pair
} else {
pair
}
})
.collect()
}
So what this function is doing is calculates probs
for each pair in the 2d matrix (so there will be n_teams / 2
(n_teams is usize
) elements in probs
.
Then it tries to swap some of the elements for this pair of Vec<Player>
. How can I do it correctly (if there is even the possibility to make it)?
Probably I could use some code like:
for team_set in children {
let temp_vec: Vec<Vec<Player>> = Vec::new();
for ind in (0..n_teams).step_by(2) {
let mut temp_child1 = team_set[ind].clone(); //
let mut temp_child2 = team_set[ind + 1].clone();
let prob_vec: Vec<f32> = rand::thread_rng()
.sample_iter(&range_probs)
.take(n_teams / 2)
.collect();
if prob_vec[ind / 2] > mut_prob {
let num_to_swap = rand::thread_rng().sample(range_number_to_swap);
let indices_to_swap =
(0..self.team_len).choose_multiple(&mut rand::thread_rng(), num_to_swap);
for swap in indices_to_swap {
temp_child1[swap] = temp_child2[swap];
temp_child2[swap] = team_set[ind][swap];
}
}
temp_vec.push(temp_child1);
temp_vec.push(temp_child2);
}
successors.push(temp_vec);
}
But there are a lot of allocations so probably it is less sufficient.
How can I do it correctly?