Предположим, что у нас есть stack
, заполненный 0
и 1
. Я хочу изменить mutation_rate_
многих элементов с 0
на 1
и наоборот. Элементы, которые должны быть «видоизменены», выбираются случайным образом. Я написал две функции для этого, которые я опубликую ниже вместе с тестовым примером, но одна из них, похоже, не работает должным образом.
#include <stack>
#include <vector>
#include <random>
#include <set>
#include <algorithm>
#include <iostream>
using age_t = unsigned int;
std::stack<age_t> mutate( std::stack<age_t> genome_, age_t mutation_rate_ = 3){
std::stack<age_t> final_stack;
// Generate a set, whose elements are the positions at which we perforem the mutation.
std::set<age_t> positions_to_switch;
while(positions_to_switch.size() < mutation_rate_){
positions_to_switch.insert(rand() % genome_.size());
}
// Create a counter to go through the stack amd iterator of the set.
age_t cnt = 0;
std::set<age_t>::iterator it= positions_to_switch.begin();
while(genome_.empty()!=true){ // Go through the whole genome_
if(*it==cnt){ // check if current position in stack matches with
// element that needs mutation
if(genome_.top()==1) final_stack.push(0); // mutate
else final_stack.push(1);
++it; // go to next element that needs mutation
}
else{ // if no mutation is needed
final_stack.push(genome_.top());
}
genome_.pop(); // go to next element in stack
++cnt; // increase counter of stack
}
// final stack is in reverse order
std::stack<age_t> res;
while(!final_stack.empty()){
res.push(final_stack.top());
final_stack.pop();
}
return res;
};
std::stack<age_t> mutate_2( std::stack<age_t> genome_, age_t mutation_rate_ = 3){
std::stack<age_t> final_stack;
std::vector<age_t> enumeration;
age_t pos = 0;
while(enumeration.size() < genome_.size()){
enumeration.push_back(pos);
++pos;
}
pos = 0;
auto rng = std::default_random_engine {};
std::shuffle(enumeration.begin(), enumeration.end(), rng);
std::vector<age_t> positions_to_switch;
while(positions_to_switch.size() < mutation_rate_){
positions_to_switch.push_back(enumeration[pos]);
++pos;
}
// Create a counter to go through the stack amd iterator of the set.
age_t cnt = 0;
std::vector<age_t>::iterator it= positions_to_switch.begin();
while(genome_.empty()!=true){ // Go through the whole genome_
if(*it==cnt){ // check if current position in stack matches with
// element that needs mutation
if(genome_.top()==1) final_stack.push(0); // mutate
else final_stack.push(1);
++it; // go to next element that needs mutation
}
else{ // if no mutation is needed
final_stack.push(genome_.top());
}
genome_.pop(); // go to next element in stack
++cnt; // increase counter of stack
}
// final stack is in reverse order
std::stack<age_t> res;
while(!final_stack.empty()){
res.push(final_stack.top());
final_stack.pop();
}
return res;
};
int main(){
std::stack<age_t> test_stack;
test_stack.push(1);
test_stack.push(0);
test_stack.push(0);
test_stack.push(0);
test_stack.push(1);
test_stack.push(1);
std::stack<age_t> test_stack_copy = test_stack;
std::stack<age_t> test_stack_copy_2 = test_stack;
std::stack<age_t> res = mutate(test_stack);
std::stack<age_t> res_2 = mutate_2(test_stack);
std::cout << "Original Stack:\t";
while(test_stack_copy_2.empty()!=true){
std::cout << test_stack_copy_2.top();
test_stack_copy_2.pop();
}
std::cout << "\n";
std::cout << "Muatet:\t\t";
while(res.empty()!=true){
std::cout << res.top();
res.pop();
}
std::cout << "\n";
std::cout << "Muatet_2:\t";
while(res_2.empty()!=true){
std::cout << res_2.top();
res_2.pop();
}
std::cout << "\n";
return 0;
}
Учитывая тестовый пример 110001
, mutate
возвращает 100111
и mutate_2
возвращает 111101
, где я установил mutation_rate_=3
, поэтому три элемента исходного стека должны были быть изменены. Мы можем непосредственно видеть, что mutate
действительно изменил три записи, в то время как mutate_2
изменил только две из них ... Я уверен, что это как-то связано с обработкой объектов set
и vector
,но я просто не могу найти ошибку ...