مانند مکالمه در استخر 🎱 به من آموخت که چگونه برنامه هایی را با الگوریتم های ژنتیکی تنظیم کنم 🧬 در 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
اجرای:
- تولید جمعیت اولیه (ترکیبات تصادفی موارد).
- ارزیابی تناسب اندام (هر ترکیب چقدر خوب است).
- انتخاب بهترین ها (نخبه گرایی).
- عبور بین نامزدها (تولید مثل).
- جهش در برخی از فرزندانبشر
- تکرار توسط نسل های N تا زمانی که پیدا کنید بهترین راه حل ممکنبشر
✅ چرا این کار خوب است؟
چون هست انعطاف پذیربشر می توانید حل کنید:
- برنامه
- انتخاب کار با اولویت
- مقیاس بندی منابع
- هر مشکلی از بهینه سازی ترکیبی
🧩 آماده تکامل؟
اگر قبلاً نیاز به راه اندازی داشته اید مقیاس ، برنامه یا لیست اولویت ها در جایی که چندین متغیر از هم تلاقی می کنند ، استفاده از نیروی بی رحم می تواند کند یا غیرممکن باشد. اما الگوریتم های ژنتیکی مانند “غریزه طبیعی” هستند که تکامل را شبیه سازی می کند و راه حل هایی پیدا می کند با کمال تعجب خوببشر
و بهترین: با PHP خالص، به روشی قابل آزمایش ، تمیز و گسترده.
🧠 آنچه الگوریتم در پشت پارچه انجام می دهد
- تولید جمعیت تصادفی (ترکیب موارد)
- ارزیابی می کند که هر ترکیب چقدر خوب است (
fitness
) - بهترین (نخبه گرایی) را انتخاب کنید
- بازتولید عبور از بازماندگان
- جهش تغییرات ایجاد می کند
- تکرار کردن
n
نسل ها
✅ چه موقع از این استفاده کنیم؟
می توانید از الگوریتم های ژنتیکی در PHP استفاده کنید:
- برنامه های پیچیده
- بهینه سازی منابع
- ترکیب محصول
- برنامه ریزی کار
- و بیشتر