برنامه نویسی

مانند مکالمه در استخر 🎱 به من آموخت که چگونه برنامه هایی را با الگوریتم های ژنتیکی تنظیم کنم 🧬 در PHP

🎱 به عنوان مکالمه در استخر به من آموخت که چگونه برنامه هایی را با الگوریتم های ژنتیکی در PHP تنظیم کنم

این روزها برای استراحت و بازی استخر با دوستم بیرون رفتم رومیبشر

در وسط بازی ، او مرا راه اندازی کرد:

“من خودم را پیدا کردم که چرا عملکردی از آن انجام دادم جستجوی ژنتیکی! “

من فکر کردم که او بازی می کند ، تا اینکه به من گفت که او تابعی به نام ایجاد کرده است buscaGenetica() این به حل یک مشکل واقعی کمک کرد: لغزش را با مبلغ محدود پرداخت کنیدبشر


💸 مشکل لغزش

“تصور کنید که کاربر با یک لغزش چشمگیر وارد می شود ، هر کدام id اشمیه valor، و می گوید 1000 دلار برای پرداخت هرچه بیشتر لغزش وجود دارد. “

او از الگوریتم های ژنتیکی برای یافتن بهترین ترکیب ممکن با احترام به این حد استفاده کرد.


🧬 این جستجوی ژنتیکی چگونه کار می کند؟

توضیحات او آنقدر بازیگوش بود که به نظر می رسید فیلمنامه:

  • 💑 لغزش “متاهل” و نسل های جدیدی از ترکیبات ایجاد کرد.
  • 🧟 برخی از نسل ها با جهش همراه بودند، مانند لغزش های دیگر برای دیگران – که او را با محبت “ناهنجاری های ژنتیکی” (یا سرطانها) نامیدند.
  • 👑 لغزش های بسیار خوب مستقیم زنده مانده اند برای نسل بعدی بدون اینکه تغییراتی را پشت سر بگذارد.
  • 🧠 و همه اینها در حال اجرا بود 100 نسل، تا زمانی که بهترین راه حل را پیدا نکردید: همانطور که بسیاری از گذرگاههای خالی با حداکثر 1000 دلار R \.

من ماندم لعاب داربشر این ایده قدرتمند بود.


⏰ مشکل واقعی من: در دسترس بودن برنامه

در راه بازگشت ، این مکالمه در ذهنم چکش زد.
من فقط با مشکلی در سیستم خود سرم را می شکرم:

من چندین حرفه ای دارم ، با مهارت های مختلف (حمام ، نظافت ، پیرایش) ، و باید برنامه موجود را با بهترین متخصصان برای هر زمان بدون درگیری پر کنم.

و سپس کلیک آمد:

چه می شود اگر من از الگوریتم ژنتیکی که رومن به من گفت این برنامه را تنظیم کنم ، چه می کنم؟

من منطق رومی را در یک سرویس PHP به نام قرار دادم GeneticAlgorithmServiceبشر


💻 اجرای با PHP

طبقه GeneticAlgorithmService این عمومی است و یک شی پیکربندی دریافت می کند. او انجام می دهد همه کارها پشت تکامل:


use App\Services\GeneticAlgorithmService;

$config = [
    "items" => [
        ["id" => 1, "peso" => 10, "altura" => 50, "valor" => 60],
        ["id" => 2, "peso" => 20, "altura" => 60, "valor" => 100],
        ["id" => 3, "peso" => 30, "altura" => 70, "valor" => 120],
    ],
    "constraints" => [
        ["attribute" => "peso", "max" => 50],
        ["attribute" => "altura", "max" => 110],
    ],
    "objective" => ["attribute" => "valor", "goal" => "maximize"],
    "populationSize" => 50,
    "generations" => 100,
    "mutationRate" => 0.05,
    "eliteRate" => 0.2,
];

$configObject = json_decode(json_encode($config), false);
$service = new GeneticAlgorithmService($configObject);
$result = $service->run();

print_r($result);
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید

`


📥 ورودی (پیکربندی)

شما تعریف می کنید:

  • items: مجموعه داده ها (برنامه ها ، لغزش ها ، کارها و غیره)
  • constraints: محدودیت ها (به عنوان مثال محدودیت وزن ، زمان ، قد)
  • objective: چه ویژگی ای خواهد بود حداکثر یا به حداقل رساندن
  • پارامترهای ژنتیکی: جمعیت ، نسل ، جهش و نخبگان

📤 خروج

تابع run() بازگشت:

php
[
['id' => 2, 'peso' => 20, 'altura' => 60, 'valor' => 100],
['id' => 1, 'peso' => 10, 'altura' => 50, 'valor' => 60]]

Ou seja, a melhor combinação possível de acordo com os critérios definidos.


⚙️ O algoritmo completo


`php

namespace App\Services;

class GeneticAlgorithmService
{
    private array $items;
    private array $constraints;
    private string $objectiveAttribute;
    private string $objectiveGoal; // 'maximize' ou 'minimize'
    private int $populationSize;
    private int $generations;
    private float $mutationRate;
    private float $eliteRate;

    private array $population = [];

    public function __construct(object $config)
    {
        $this->items = $config->items;
        $this->constraints = $config->constraints;
        $this->objectiveAttribute = $config->objective->attribute;
        $this->objectiveGoal = $config->objective->goal;
        $this->populationSize = $config->populationSize;
        $this->generations = $config->generations;
        $this->mutationRate = $config->mutationRate;
        $this->eliteRate = $config->eliteRate;
    }

    // Executa o algoritmo e retorna a lista de itens selecionados
    public function run(): array
    {
        $this->initializePopulation();

        for ($gen = 0; $gen < $this->generations; $gen++) {
            $fitnessScores = $this->evaluatePopulation();

            $elite = $this->selectElite($fitnessScores);

            $newPopulation = $elite;

            while (count($newPopulation) < $this->populationSize) {
                $parent1 = $this->tournamentSelection($fitnessScores);
                $parent2 = $this->tournamentSelection($fitnessScores);

                $child = $this->crossover($parent1, $parent2);
                $this->mutate($child);

                if ($this->checkConstraints($child)) {
                    $newPopulation[] = $child;
                }
            }

            $this->population = $newPopulation;
        }

        $finalFitness = $this->evaluatePopulation();
        $bestIndex = $this->getBestIndex($finalFitness);

        return $this->decodeChromosome($this->population[$bestIndex]);
    }

    // Inicializa população com cromossomos aleatórios
    private function initializePopulation(): void
    {
        $this->population = [];
        $numItems = count($this->items);

        for ($i = 0; $i < $this->populationSize; $i++) {
            $chromosome = [];

            for ($j = 0; $j < $numItems; $j++) {
                // 0 ou 1 para representar se o item está selecionado
                $chromosome[] = rand(0, 1);
            }

            // Garante que o cromossomo respeite as restrições
            if ($this->checkConstraints($chromosome)) {
                $this->population[] = $chromosome;
            } else {
                // Caso não respeite, tenta gerar outro até encontrar válido
                $i--;
            }
        }
    }

    // Avalia fitness de cada indivíduo na população
    private function evaluatePopulation(): array
    {
        $fitnessScores = [];

        foreach ($this->population as $chromosome) {
            $fitnessScores[] = $this->fitness($chromosome);
        }

        return $fitnessScores;
    }

    // Função fitness que calcula a pontuação do cromossomo
    private function fitness(array $chromosome): float
    {
        $totalObjective = 0;

        foreach ($chromosome as $index => $gene) {
            if ($gene === 1) {
                $totalObjective += $this->items[$index][$this->objectiveAttribute];
            }
        }

        return $totalObjective;
    }

    // Seleciona os melhores indivíduos (elite) para a próxima geração
    private function selectElite(array $fitnessScores): array
    {
        $numElite = (int) round($this->populationSize * $this->eliteRate);

        // Associa fitness ao índice para ordenar
        $indexedFitness = array_map(fn($score, $i) => ['score' => $score, 'index' => $i], $fitnessScores, array_keys($fitnessScores));

        usort($indexedFitness, function($a, $b) {
            if ($this->objectiveGoal === 'maximize') {
                return $b['score'] <=> $a['score'];
            }
            return $a['score'] <=> $b['score'];
        });

        $elite = [];
        for ($i = 0; $i < $numElite; $i++) {
            $elite[] = $this->population[$indexedFitness[$i]['index']];
        }

        return $elite;
    }

    // Torneio para selecionar um cromossomo (parent)
    private function tournamentSelection(array $fitnessScores): array
    {
        $tournamentSize = 3;
        $candidates = [];

        $populationCount = count($this->population);

        for ($i = 0; $i < $tournamentSize; $i++) {
            $randomIndex = rand(0, $populationCount - 1);
            $candidates[] = ['chromosome' => $this->population[$randomIndex], 'fitness' => $fitnessScores[$randomIndex]];
        }

        usort($candidates, function($a, $b) {
            if ($this->objectiveGoal === 'maximize') {
                return $b['fitness'] <=> $a['fitness'];
            }
            return $a['fitness'] <=> $b['fitness'];
        });

        return $candidates[0]['chromosome'];
    }

    // Crossover simples: um ponto de corte
    private function crossover(array $parent1, array $parent2): array
    {
        $length = count($parent1);
        $cut = rand(1, $length - 2);

        return array_merge(
            array_slice($parent1, 0, $cut),
            array_slice($parent2, $cut)
        );
    }

    // Mutação com probabilidade definida
    private function mutate(array &$chromosome): void
    {
        for ($i = 0; $i < count($chromosome); $i++) {
            if (rand() / getrandmax() < $this->mutationRate) {
                $chromosome[$i] = $chromosome[$i] === 1 ? 0 : 1;
            }
        }
    }

    // Verifica se o cromossomo respeita as restrições
    private function checkConstraints(array $chromosome): bool
    {
        foreach ($this->constraints as $constraint) {
            $attribute = $constraint->attribute;
            $max = $constraint->max;

            $total = 0;
            foreach ($chromosome as $index => $gene) {
                if ($gene === 1) {
                    $total += $this->items[$index][$attribute];
                }
            }

            if ($total > $max) {
                return false;
            }
        }
        return true;
    }

    // Retorna o índice do melhor cromossomo baseado no fitness
    private function getBestIndex(array $fitnessScores): int
    {
        if ($this->objectiveGoal === 'maximize') {
            return array_keys($fitnessScores, max($fitnessScores))[0];
        }
        return array_keys($fitnessScores, min($fitnessScores))[0];
    }

    // Decodifica o cromossomo para retornar os itens selecionados
    private function decodeChromosome(array $chromosome): array
    {
        $selected = [];
        foreach ($chromosome as $index => $gene) {
            if ($gene === 1) {
                $selected[] = $this->items[$index];
            }
        }
        return $selected;
    }
}
حالت تمام صفحه را وارد کنید

از حالت تمام صفحه خارج شوید


🧬 آنچه الگوریتم از پشت انجام می دهد

داخلی ، GeneticAlgorithmService اجرای:

  1. تولید جمعیت اولیه (ترکیبات تصادفی موارد).
  2. ارزیابی تناسب اندام (هر ترکیب چقدر خوب است).
  3. انتخاب بهترین ها (نخبه گرایی).
  4. عبور بین نامزدها (تولید مثل).
  5. جهش در برخی از فرزندانبشر
  6. تکرار توسط نسل های N تا زمانی که پیدا کنید بهترین راه حل ممکنبشر

✅ چرا این کار خوب است؟

چون هست انعطاف پذیربشر می توانید حل کنید:

  • برنامه
  • انتخاب کار با اولویت
  • مقیاس بندی منابع
  • هر مشکلی از بهینه سازی ترکیبی

🧩 آماده تکامل؟

اگر قبلاً نیاز به راه اندازی داشته اید مقیاس ، برنامه یا لیست اولویت ها در جایی که چندین متغیر از هم تلاقی می کنند ، استفاده از نیروی بی رحم می تواند کند یا غیرممکن باشد. اما الگوریتم های ژنتیکی مانند “غریزه طبیعی” هستند که تکامل را شبیه سازی می کند و راه حل هایی پیدا می کند با کمال تعجب خوببشر

و بهترین: با PHP خالص، به روشی قابل آزمایش ، تمیز و گسترده.


🧠 آنچه الگوریتم در پشت پارچه انجام می دهد

  1. تولید جمعیت تصادفی (ترکیب موارد)
  2. ارزیابی می کند که هر ترکیب چقدر خوب است (fitness)
  3. بهترین (نخبه گرایی) را انتخاب کنید
  4. بازتولید عبور از بازماندگان
  5. جهش تغییرات ایجاد می کند
  6. تکرار کردن n نسل ها

✅ چه موقع از این استفاده کنیم؟

می توانید از الگوریتم های ژنتیکی در PHP استفاده کنید:

  • برنامه های پیچیده
  • بهینه سازی منابع
  • ترکیب محصول
  • برنامه ریزی کار
  • و بیشتر

نوشته های مشابه

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *

دکمه بازگشت به بالا