ΠΡ ΡΠ΅Π°Π»ΠΈΠ·ΡΠ΅ΠΌ Π³Π΅Π½Π΅ΡΠΈΡΠ΅ΡΠΊΠΈΠΉ Π°Π»Π³ΠΎΡΠΈΡΠΌ Π½Π΅ Π² ΠΏΡΠΎΠ³ΡΠ°ΠΌΠΌΠ½ΠΎΠΌ ΠΊΠΎΠ΄Π΅, Π° Ρ ΠΈΡΠΏΠΎΠ»ΡΠ·ΠΎΠ²Π°Π½ΠΈΠ΅ΠΌ Π°ΠΏΠΏΠ°ΡΠ°ΡΠ½ΡΡ ΡΠ°ΠΉΠΌΠ΅ΡΠΎΠ² ΠΈ ΠΏΡΠ΅ΡΡΠ²Π°Π½ΠΈΠΉ Π΄Π»Ρ ΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎΠΉ ΡΠ²ΠΎΠ»ΡΡΠΈΠΈ!
ΠΠΏΠΏΠ°ΡΠ°ΡΠ½Π°Ρ ΡΠ²ΠΎΠ»ΡΡΠΈΡ Π½Π° ΡΠ°ΠΉΠΌΠ΅ΡΠ°Ρ :
cpp
#include <avr/io.h>
#include <avr/interrupt.h>
#define POPULATION_SIZE 16
#define GENOME_SIZE 16
#define MUTATION_RATE 10
// ΠΠ΅Π½ΠΎΠΌ (Ρ
ΡΠ°Π½ΠΈΡΡΡ Π² ΡΠ΅Π³ΠΈΡΡΡΠ°Ρ
Π΄Π»Ρ ΡΠΊΠΎΡΠΎΡΡΠΈ)
uint8_t population[POPULATION_SIZE][GENOME_SIZE];
uint8_t fitness[POPULATION_SIZE];
uint8_t bestGenome[GENOME_SIZE];
uint8_t bestFitness = 0;
// Π’Π°ΠΉΠΌΠ΅Ρ 0 Π΄Π»Ρ Π³Π΅Π½Π΅ΡΠ°ΡΠΈΠΈ ΡΠ»ΡΡΠ°ΠΉΠ½ΡΡ
ΡΠΈΡΠ΅Π» (Π°ΠΏΠΏΠ°ΡΠ°ΡΠ½ΡΠΉ LFSR)
uint16_t lfsr = 0xACE1;
ISR(TIMER0_OVF_vect) {
// ΠΠΈΠ½Π΅ΠΉΠ½ΡΠΉ ΡΠ΅Π³ΠΈΡΡΡ ΡΠ΄Π²ΠΈΠ³Π° Ρ ΠΎΠ±ΡΠ°ΡΠ½ΠΎΠΉ ΡΠ²ΡΠ·ΡΡ (LFSR)
uint16_t bit = ((lfsr >> 0) ^ (lfsr >> 2) ^ (lfsr >> 3) ^ (lfsr >> 5)) & 1;
lfsr = (lfsr >> 1) | (bit << 15);
}
// ΠΠΏΠΏΠ°ΡΠ°ΡΠ½ΡΠΉ Π³Π΅Π½Π΅ΡΠ°ΡΠΎΡ ΡΠ»ΡΡΠ°ΠΉΠ½ΡΡ
ΡΠΈΡΠ΅Π»
uint8_t randomByte() {
return lfsr & 0xFF;
}
// Π€ΡΠ½ΠΊΡΠΈΡ ΠΏΡΠΈΡΠΏΠΎΡΠΎΠ±Π»Π΅Π½Π½ΠΎΡΡΠΈ (Π°ΠΏΠΏΠ°ΡΠ°ΡΠ½Π°Ρ, Π½Π° ΠΏΡΠ΅ΡΡΠ²Π°Π½ΠΈΡΡ
)
volatile uint8_t currentInd = 0;
ISR(TIMER1_OVF_vect) {
// ΠΡΡΠΈΡΠ»ΡΠ΅ΠΌ ΠΏΡΠΈΡΠΏΠΎΡΠΎΠ±Π»Π΅Π½Π½ΠΎΡΡΡ Π΄Π»Ρ ΡΠ΅ΠΊΡΡΠ΅ΠΉ ΠΎΡΠΎΠ±ΠΈ (ΠΏΠ°ΠΏΠΏΠ°ΡΠ°Π»Π»Π΅Π»ΡΠ½ΠΎ)
uint8_t fit = 0;
for (uint8_t i = 0; i < GENOME_SIZE; i++) {
// Π¦Π΅Π»Π΅Π²Π°Ρ ΡΡΠ½ΠΊΡΠΈΡ: Π½Π°ΠΉΡΠΈ ΠΏΠΎΡΠ»Π΅Π΄ΠΎΠ²Π°ΡΠ΅Π»ΡΠ½ΠΎΡΡΡ 0x55
fit += (population[currentInd][i] == 0x55) ? 10 : 0;
// ΠΡΠ΅ΠΌ ΡΠ°ΠΊΠΆΠ΅ ΡΠ΅ΡΠ΅Π΄ΠΎΠ²Π°Π½ΠΈΠ΅ Π±ΠΈΡ
for (uint8_t j = 0; j < 7; j++) {
if (((population[currentInd][i] >> j) & 1) !=
((population[currentInd][i] >> (j+1)) & 1)) {
fit += 1;
}
}
}
fitness[currentInd] = fit;
currentInd = (currentInd + 1) % POPULATION_SIZE;
}
// Π‘ΠΊΡΠ΅ΡΠΈΠ²Π°Π½ΠΈΠ΅ (Π½Π° Π°ΠΏΠΏΠ°ΡΠ°ΡΠ½ΠΎΠΌ ΡΡΠΎΠ²Π½Π΅ ΡΠ΅ΡΠ΅Π· Π±ΠΈΡΠΎΠ²ΡΠ΅ ΠΎΠΏΠ΅ΡΠ°ΡΠΈΠΈ)
void crossover(uint8_t* parent1, uint8_t* parent2, uint8_t* child1, uint8_t* child2) {
uint8_t point = randomByte() % GENOME_SIZE;
for (uint8_t i = 0; i < GENOME_SIZE; i++) {
if (i < point) {
child1[i] = parent1[i];
child2[i] = parent2[i];
} else {
child1[i] = parent2[i];
child2[i] = parent1[i];
}
}
}
// ΠΡΡΠ°ΡΠΈΡ (Π°ΠΏΠΏΠ°ΡΠ°ΡΠ½Π°Ρ)
void mutate(uint8_t* genome) {
for (uint8_t i = 0; i < GENOME_SIZE; i++) {
if (randomByte() < MUTATION_RATE) {
genome[i] ^= (1 << (randomByte() % 8));
}
}
}
// ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ Π°ΠΏΠΏΠ°ΡΠ°ΡΠ½ΠΎΠΉ ΡΠ²ΠΎΠ»ΡΡΠΈΠΈ
void initEvolution() {
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΠ°ΠΉΠΌΠ΅ΡΠ° 0 Π΄Π»Ρ LFSR (10 ΠΊΠΡ)
TCCR0A = 0;
TCCR0B = (1 << CS02) | (1 << CS00); // ΠΡΠ΅ΡΠΊΠ°Π»Π΅Ρ 1024
TIMSK0 = (1 << TOIE0);
// ΠΠ°ΡΡΡΠΎΠΉΠΊΠ° ΡΠ°ΠΉΠΌΠ΅ΡΠ° 1 Π΄Π»Ρ ΡΠ²ΠΎΠ»ΡΡΠΈΠΈ (1 ΠΊΠΡ)
TCCR1A = 0;
TCCR1B = (1 << CS12) | (1 << CS10); // ΠΡΠ΅ΡΠΊΠ°Π»Π΅Ρ 1024
TIMSK1 = (1 << TOIE1);
// ΠΠ½ΠΈΡΠΈΠ°Π»ΠΈΠ·Π°ΡΠΈΡ ΠΏΠΎΠΏΡΠ»ΡΡΠΈΠΈ
for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
for (uint8_t j = 0; j < GENOME_SIZE; j++) {
population[i][j] = randomByte();
}
}
sei(); // Π Π°Π·ΡΠ΅ΡΠ°Π΅ΠΌ ΠΏΡΠ΅ΡΡΠ²Π°Π½ΠΈΡ
}
// ΠΠ»Π°Π²Π½ΡΠΉ ΡΠΈΠΊΠ» ΡΠ²ΠΎΠ»ΡΡΠΈΠΈ (Π²ΡΠ·ΡΠ²Π°Π΅ΡΡΡ Π² loop)
void evolveGeneration() {
// Π‘Π΅Π»Π΅ΠΊΡΠΈΡ (ΡΡΡΠ½ΠΈΡΠ½Π°Ρ)
uint8_t parents[POPULATION_SIZE];
for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
uint8_t best = randomByte() % POPULATION_SIZE;
for (uint8_t j = 0; j < 3; j++) {
uint8_t contender = randomByte() % POPULATION_SIZE;
if (fitness[contender] > fitness[best]) {
best = contender;
}
}
parents[i] = best;
}
// Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ Π½ΠΎΠ²ΠΎΠ΅ ΠΏΠΎΠΊΠΎΠ»Π΅Π½ΠΈΠ΅
uint8_t newPop[POPULATION_SIZE][GENOME_SIZE];
for (uint8_t i = 0; i < POPULATION_SIZE; i += 2) {
crossover(population[parents[i]], population[parents[i+1]],
newPop[i], newPop[i+1]);
mutate(newPop[i]);
mutate(newPop[i+1]);
}
// ΠΠΎΠΏΠΈΡΡΠ΅ΠΌ Π½ΠΎΠ²ΡΡ ΠΏΠΎΠΏΡΠ»ΡΡΠΈΡ
memcpy(population, newPop, sizeof(population));
}
void setup() {
Serial.begin(115200);
initEvolution();
}
void loop() {
static uint32_t lastEvolve = 0;
// ΠΠ²ΠΎΠ»ΡΡΠΈΠΎΠ½ΠΈΡΡΠ΅ΠΌ ΠΊΠ°ΠΆΠ΄ΡΠ΅ 100 ΠΌΡ
if (millis() - lastEvolve > 100) {
evolveGeneration();
lastEvolve = millis();
// ΠΠ°Ρ
ΠΎΠ΄ΠΈΠΌ Π»ΡΡΡΡΡ ΠΎΡΠΎΠ±Ρ
uint8_t bestFit = 0;
uint8_t bestIdx = 0;
for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
if (fitness[i] > bestFit) {
bestFit = fitness[i];
bestIdx = i;
}
}
Serial.print("ΠΠΎΠΊΠΎΠ»Π΅Π½ΠΈΠ΅: ");
Serial.print(millis() / 100);
Serial.print(", ΠΡΡΡΠΈΠΉ Π³Π΅Π½ΠΎΠΌ: ");
for (uint8_t i = 0; i < GENOME_SIZE; i++) {
Serial.print(population[bestIdx][i], HEX);
Serial.print(" ");
}
Serial.print(", Fitness: ");
Serial.println(bestFit);
}
}