🧬 Π§Π°ΡΡ‚ΡŒ 39: Аппаратный гСнСтичСский Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ (ИспользованиС Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠ² для ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΈ)

ΠœΡ‹ Ρ€Π΅Π°Π»ΠΈΠ·ΡƒΠ΅ΠΌ гСнСтичСский Π°Π»Π³ΠΎΡ€ΠΈΡ‚ΠΌ Π½Π΅ Π² ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ½ΠΎΠΌ ΠΊΠΎΠ΄Π΅, Π° с использованиСм Π°ΠΏΠΏΠ°Ρ€Π°Ρ‚Π½Ρ‹Ρ… Ρ‚Π°ΠΉΠΌΠ΅Ρ€ΠΎΠ² ΠΈ ΠΏΡ€Π΅Ρ€Ρ‹Π²Π°Π½ΠΈΠΉ Π΄Π»Ρ ΠΏΠ°Ρ€Π°Π»Π»Π΅Π»ΡŒΠ½ΠΎΠΉ ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΈ!

Аппаратная ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΡ Π½Π° Ρ‚Π°ΠΉΠΌΠ΅Ρ€Π°Ρ…:

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);
    }
}

Π’Π°ΠΌ Ρ‚Π°ΠΊΠΆΠ΅ ΠΌΠΎΠΆΠ΅Ρ‚ ΠΏΠΎΠ½Ρ€Π°Π²ΠΈΡ‚ΡŒΡΡ

About the Author: user1

Π”ΠΎΠ±Π°Π²ΠΈΡ‚ΡŒ ΠΊΠΎΠΌΠΌΠ΅Π½Ρ‚Π°Ρ€ΠΈΠΉ

Π’Π°Ρˆ адрСс email Π½Π΅ Π±ΡƒΠ΄Π΅Ρ‚ ΠΎΠΏΡƒΠ±Π»ΠΈΠΊΠΎΠ²Π°Π½. ΠžΠ±ΡΠ·Π°Ρ‚Π΅Π»ΡŒΠ½Ρ‹Π΅ поля ΠΏΠΎΠΌΠ΅Ρ‡Π΅Π½Ρ‹ *