🧬 Π§Π°ΡΡ‚ΡŒ 57: Бамовоспроизводящаяся ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° β€” ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΡ ΠΊΠΎΠ΄Π°

ΠœΡ‹ создадим ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ, которая ΡΠ°ΠΌΠ° сСбя ΠΎΠΏΡ‚ΠΈΠΌΠΈΠ·ΠΈΡ€ΡƒΠ΅Ρ‚ ΠΈ ΡΠ²ΠΎΠ»ΡŽΡ†ΠΈΠΎΠ½ΠΈΡ€ΡƒΠ΅Ρ‚, создавая Π½ΠΎΠ²Ρ‹Π΅ вСрсии сСбя!

ГСнСтичСский Π°Π²Ρ‚ΠΎΠΌΠ°Ρ‚:

cpp

#include <EEPROM.h>
#include <avr/wdt.h>

#define PROGRAM_SIZE 512
#define POPULATION_SIZE 4

// Π‘Ρ‚Ρ€ΡƒΠΊΡ‚ΡƒΡ€Π° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ (Π³Π΅Π½ΠΎΠΌ)
struct Program {
    uint8_t code[PROGRAM_SIZE];
    uint16_t fitness;
    uint8_t generation;
    uint8_t mutationCount;
};

Program population[POPULATION_SIZE];
uint8_t bestProgram[PROGRAM_SIZE];
uint16_t bestFitness = 0;

// Π—Π°Π³Ρ€ΡƒΠ·ΠΊΠ° ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ ΠΈΠ· EEPROM
void loadProgram(uint8_t index) {
    uint16_t addr = index * PROGRAM_SIZE;
    for (uint16_t i = 0; i < PROGRAM_SIZE; i++) {
        population[index].code[i] = EEPROM.read(addr + i);
    }
}

// Π‘ΠΎΡ…Ρ€Π°Π½Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ Π² EEPROM
void saveProgram(uint8_t index) {
    uint16_t addr = index * PROGRAM_SIZE;
    for (uint16_t i = 0; i < PROGRAM_SIZE; i++) {
        EEPROM.write(addr + i, population[index].code[i]);
    }
}

// Π’Ρ‹ΠΏΠΎΠ»Π½Π΅Π½ΠΈΠ΅ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹ (имитация)
uint16_t executeProgram(uint8_t* code) {
    uint16_t result = 0;
    uint16_t pc = 0;
    
    while (pc < PROGRAM_SIZE && code[pc] != 0xFF) {  // 0xFF = HALT
        uint8_t op = code[pc];
        switch (op) {
            case 0x01: {  // ADD
                result += code[pc + 1];
                pc += 2;
                break;
            }
            case 0x02: {  // XOR
                result ^= code[pc + 1];
                pc += 2;
                break;
            }
            case 0x03: {  // SHIFT
                result <<= (code[pc + 1] % 8);
                pc += 2;
                break;
            }
            case 0x04: {  // BRANCH
                if (result > 1000) {
                    pc = code[pc + 1];
                } else {
                    pc += 2;
                }
                break;
            }
            default:
                pc++;
        }
    }
    
    return result;
}

// ΠžΡ†Π΅Π½ΠΊΠ° приспособлСнности (ΡΠ»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ + ΡΡ„Ρ„Π΅ΠΊΡ‚ΠΈΠ²Π½ΠΎΡΡ‚ΡŒ)
uint16_t calculateFitness(uint8_t* code) {
    // ВыполняСм ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ с Ρ€Π°Π·Π½Ρ‹ΠΌΠΈ Π²Ρ…ΠΎΠ΄Π½Ρ‹ΠΌΠΈ Π΄Π°Π½Π½Ρ‹ΠΌΠΈ
    uint16_t totalScore = 0;
    uint16_t complexity = 0;
    
    for (uint16_t test = 0; test < 10; test++) {
        // ΠšΠΎΠΏΠΈΡ€ΡƒΠ΅ΠΌ ΠΊΠΎΠ΄ Π²ΠΎ Π²Ρ€Π΅ΠΌΠ΅Π½Π½ΡƒΡŽ ΠΎΠ±Π»Π°ΡΡ‚ΡŒ
        uint8_t testCode[PROGRAM_SIZE];
        memcpy(testCode, code, PROGRAM_SIZE);
        // ΠŸΠΎΠ΄ΡΡ‚Π°Π²Π»ΡΠ΅ΠΌ Π²Ρ…ΠΎΠ΄Π½Ρ‹Π΅ Π΄Π°Π½Π½Ρ‹Π΅
        testCode[1] = test;
        testCode[3] = test * 2;
        
        uint16_t result = executeProgram(testCode);
        totalScore += result;
        
        // Π‘Π»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ (количСство Π½Π΅Π½ΡƒΠ»Π΅Π²Ρ‹Ρ… Π±Π°ΠΉΡ‚)
        for (uint16_t i = 0; i < PROGRAM_SIZE; i++) {
            if (code[i] != 0) complexity++;
        }
    }
    
    // ЀизичСская ΠΏΡ€ΠΈΡΠΏΠΎΡΠΎΠ±Π»Π΅Π½Π½ΠΎΡΡ‚ΡŒ = Ρ€Π΅Π·ΡƒΠ»ΡŒΡ‚Π°Ρ‚ / ΡΠ»ΠΎΠΆΠ½ΠΎΡΡ‚ΡŒ
    uint16_t fitness = totalScore / (complexity / 16 + 1);
    return fitness;
}

// ΠšΡ€ΠΎΡΡΠΈΠ½Π³ΠΎΠ²Π΅Ρ€ (ΠΎΠ±ΠΌΠ΅Π½ участками ΠΊΠΎΠ΄Π°)
void crossover(uint8_t* parent1, uint8_t* parent2, uint8_t* child1, uint8_t* child2) {
    uint16_t point1 = random(PROGRAM_SIZE);
    uint16_t point2 = random(PROGRAM_SIZE);
    if (point1 > point2) {
        uint16_t temp = point1;
        point1 = point2;
        point2 = temp;
    }
    
    for (uint16_t i = 0; i < PROGRAM_SIZE; i++) {
        if (i < point1 || i > point2) {
            child1[i] = parent1[i];
            child2[i] = parent2[i];
        } else {
            child1[i] = parent2[i];
            child2[i] = parent1[i];
        }
    }
}

// ΠœΡƒΡ‚Π°Ρ†ΠΈΡ
void mutate(uint8_t* code) {
    uint8_t mutations = random(1, 10);
    for (uint8_t i = 0; i < mutations; i++) {
        uint16_t pos = random(PROGRAM_SIZE);
        code[pos] ^= (1 << random(8));
    }
}

// Π­Π²ΠΎΠ»ΡŽΡ†ΠΈΡ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡ‹
void evolvePrograms() {
    // БСлСкция (турнирная)
    uint8_t parents[POPULATION_SIZE];
    for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
        uint8_t best = random(POPULATION_SIZE);
        for (uint8_t j = 0; j < 3; j++) {
            uint8_t contender = random(POPULATION_SIZE);
            if (population[contender].fitness > population[best].fitness) {
                best = contender;
            }
        }
        parents[i] = best;
    }
    
    // Π‘ΠΎΠ·Π΄Π°Π΅ΠΌ Π½ΠΎΠ²ΠΎΠ΅ ΠΏΠΎΠΊΠΎΠ»Π΅Π½ΠΈΠ΅
    Program newPop[POPULATION_SIZE];
    for (uint8_t i = 0; i < POPULATION_SIZE; i += 2) {
        crossover(population[parents[i]].code, population[parents[i+1]].code,
                  newPop[i].code, newPop[i+1].code);
        mutate(newPop[i].code);
        mutate(newPop[i+1].code);
        
        newPop[i].generation = population[parents[i]].generation + 1;
        newPop[i+1].generation = population[parents[i+1]].generation + 1;
        newPop[i].mutationCount = population[parents[i]].mutationCount + 1;
        newPop[i+1].mutationCount = population[parents[i+1]].mutationCount + 1;
    }
    
    // ΠžΡ†Π΅Π½ΠΈΠ²Π°Π΅ΠΌ Π½ΠΎΠ²ΠΎΠ΅ ΠΏΠΎΠΊΠΎΠ»Π΅Π½ΠΈΠ΅
    for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
        newPop[i].fitness = calculateFitness(newPop[i].code);
    }
    
    // ЗамСняСм ΠΏΠΎΠΏΡƒΠ»ΡΡ†ΠΈΡŽ
    memcpy(population, newPop, sizeof(population));
    
    // Находим Π»ΡƒΡ‡ΡˆΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ
    for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
        if (population[i].fitness > bestFitness) {
            bestFitness = population[i].fitness;
            memcpy(bestProgram, population[i].code, PROGRAM_SIZE);
        }
    }
}

// Π‘Π°ΠΌΠΎ-модификация (ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° мСняСт сСбя)
void selfModify() {
    // Находим участок ΠΊΠΎΠ΄Π° для измСнСния
    uint16_t pos = random(PROGRAM_SIZE - 10);
    uint8_t modification[10];
    for (uint8_t i = 0; i < 10; i++) {
        modification[i] = random(256);
    }
    
    // ΠŸΡ€ΠΈΠΌΠ΅Π½ΡΠ΅ΠΌ ΠΈΠ·ΠΌΠ΅Π½Π΅Π½ΠΈΠ΅
    for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
        for (uint8_t j = 0; j < 10; j++) {
            population[i].code[pos + j] ^= modification[j];
        }
    }
}

void setup() {
    Serial.begin(115200);
    randomSeed(analogRead(A0));
    
    // Π˜Π½ΠΈΡ†ΠΈΠ°Π»ΠΈΠ·Π°Ρ†ΠΈΡ популяции
    for (uint8_t i = 0; i < POPULATION_SIZE; i++) {
        for (uint16_t j = 0; j < PROGRAM_SIZE; j++) {
            population[i].code[j] = random(256);
        }
        population[i].code[PROGRAM_SIZE - 1] = 0xFF;  // HALT
        population[i].generation = 0;
        population[i].mutationCount = 0;
        population[i].fitness = calculateFitness(population[i].code);
    }
    
    Serial.println("🧬 Π‘ΠΠœΠžΠ’ΠžΠ‘ΠŸΠ ΠžΠ˜Π—Π’ΠžΠ”Π―Π©ΠΠ―Π‘Π― ΠŸΠ ΠžΠ“Π ΠΠœΠœΠ Π—ΠΠŸΠ£Π©Π•ΠΠ");
}

void loop() {
    // Π­Π²ΠΎΠ»ΡŽΡ†ΠΈΡ
    evolvePrograms();
    
    // Π‘Π°ΠΌΠΎ-модификация
    if (random(100) < 30) {
        selfModify();
        Serial.println("πŸ”„ ΠŸΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΠ° ΠΌΠΎΠ΄ΠΈΡ„ΠΈΡ†ΠΈΡ€ΠΎΠ²Π°Π»Π° сСбя");
    }
    
    // БохраняСм Π»ΡƒΡ‡ΡˆΡƒΡŽ ΠΏΡ€ΠΎΠ³Ρ€Π°ΠΌΠΌΡƒ
    static uint32_t lastSave = 0;
    if (millis() - lastSave > 10000) {
        saveProgram(0);
        lastSave = millis();
        
        Serial.print("🧬 ПоколСниС: ");
        Serial.print(population[0].generation);
        Serial.print(" | Π›ΡƒΡ‡ΡˆΠ°Ρ ΠΏΡ€ΠΈΡΠΏΠΎΡΠΎΠ±Π»Π΅Π½Π½ΠΎΡΡ‚ΡŒ: ");
        Serial.println(bestFitness);
    }
    
    // Π‘Ρ‚ΠΎΡ€ΠΎΠΆΠ΅Π²ΠΎΠΉ Ρ‚Π°ΠΉΠΌΠ΅Ρ€ Π·Π°Ρ‰ΠΈΡ‰Π°Π΅Ρ‚ ΠΎΡ‚ зависания
    wdt_reset();
    delay(1000);
}

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

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

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