penjadwalan-ga/app/Console/Commands/TestGaEngineCommand.php

247 lines
9.5 KiB
PHP

<?php
namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Services\Scheduling\DatasetLoader;
use App\Services\Scheduling\GeneticAlgorithmEngine;
class TestGaEngineCommand extends Command
{
protected $signature = 'ga:test-parameters
{--semester= : Semester dataset}
{--tahun= : Tahun ajaran dataset}';
protected $description = 'Jalankan pengujian otomatis hyperparameter GA (Populasi, Crossover, Mutasi, Iterasi, & Pengujian Akhir) dan tampilkan tabel Bab 4';
public function handle()
{
$this->info("================================──────────────────────────");
$this->info("🚀 MEMULAI OTOMASI PENGUJIAN ALGORITMA GENETIKA (BAB 4)");
$this->info("================================──────────────────────────");
$semester = $this->option('semester');
$tahun = $this->option('tahun');
$datasetLoader = new DatasetLoader();
$dataset = $datasetLoader->load($semester, $tahun);
$this->comment("Dataset berhasil dimuat: " . count($dataset->kelasList) . " Kelas, " . count($dataset->guruList) . " Guru, " . count($dataset->ruanganRobotkuIds) . " Ruangan.");
// 1. TAHAP 1: UJI POPULASI
$this->newLine();
$this->info("📌 1. MENJALANKAN TABEL 4.1: PENGUJIAN JUMLAH POPULASI");
$popVariations = [10, 20, 30, 40, 50];
$tabel1 = [];
$bestPop = 20;
$bestPopFitness = -1;
foreach ($popVariations as $idx => $pop) {
$engine = new GeneticAlgorithmEngine(
populationSize: $pop,
crossoverRate: 0.5,
mutationRate: 0.5,
maxGenerations: 500,
tournamentSize: 3,
elitismCount: 2
);
$res = $engine->run($dataset);
$fitness = $res['bestChromosome']->fitness;
if ($fitness > $bestPopFitness) {
$bestPopFitness = $fitness;
$bestPop = $pop;
}
$tabel1[] = [
'Uji Ke-' => $idx + 1,
'Populasi' => $pop,
'Pc' => 0.5,
'Pm' => 0.5,
'Iterasi' => 500,
'Fitness Max' => round($fitness, 6),
'Total Penalti' => $res['bestChromosome']->totalPenalty,
'Waktu (s)' => round($res['executionTime'], 4),
];
}
$this->table(['Uji Ke-', 'Populasi', 'Pc', 'Pm', 'Iterasi', 'Fitness Max', 'Penalti', 'Waktu (s)'], $tabel1);
$this->info("✅ Populasi Terbaik Terpilih: {$bestPop} (Fitness: {$bestPopFitness})");
// 2. TAHAP 2: UJI CROSSOVER RATE
$this->newLine();
$this->info("📌 2. MENJALANKAN TABEL 4.2: PENGUJIAN CROSSOVER RATE (Pc)");
$pcVariations = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
$tabel2 = [];
$bestPc = 0.6;
$bestPcFitness = -1;
foreach ($pcVariations as $idx => $pc) {
$engine = new GeneticAlgorithmEngine(
populationSize: $bestPop,
crossoverRate: $pc,
mutationRate: 0.5,
maxGenerations: 500,
tournamentSize: 3,
elitismCount: 2
);
$res = $engine->run($dataset);
$fitness = $res['bestChromosome']->fitness;
if ($fitness > $bestPcFitness) {
$bestPcFitness = $fitness;
$bestPc = $pc;
}
$tabel2[] = [
'Uji Ke-' => $idx + 1,
'Populasi' => $bestPop,
'Pc' => $pc,
'Pm' => 0.5,
'Iterasi' => 500,
'Fitness Max' => round($fitness, 6),
'Total Penalti' => $res['bestChromosome']->totalPenalty,
'Waktu (s)' => round($res['executionTime'], 4),
];
}
$this->table(['Uji Ke-', 'Populasi', 'Pc', 'Pm', 'Iterasi', 'Fitness Max', 'Penalti', 'Waktu (s)'], $tabel2);
$this->info("✅ Crossover Rate Terbaik Terpilih: {$bestPc} (Fitness: {$bestPcFitness})");
// 3. TAHAP 3: UJI MUTATION RATE
$this->newLine();
$this->info("📌 3. MENJALANKAN TABEL 4.3: PENGUJIAN MUTATION RATE (Pm)");
$pmVariations = [0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9];
$tabel3 = [];
$bestPm = 0.3;
$bestPmFitness = -1;
foreach ($pmVariations as $idx => $pm) {
$engine = new GeneticAlgorithmEngine(
populationSize: $bestPop,
crossoverRate: $bestPc,
mutationRate: $pm,
maxGenerations: 500,
tournamentSize: 3,
elitismCount: 2
);
$res = $engine->run($dataset);
$fitness = $res['bestChromosome']->fitness;
if ($fitness > $bestPmFitness) {
$bestPmFitness = $fitness;
$bestPm = $pm;
}
$tabel3[] = [
'Uji Ke-' => $idx + 1,
'Populasi' => $bestPop,
'Pc' => $bestPc,
'Pm' => $pm,
'Iterasi' => 500,
'Fitness Max' => round($fitness, 6),
'Total Penalti' => $res['bestChromosome']->totalPenalty,
'Waktu (s)' => round($res['executionTime'], 4),
];
}
$this->table(['Uji Ke-', 'Populasi', 'Pc', 'Pm', 'Iterasi', 'Fitness Max', 'Penalti', 'Waktu (s)'], $tabel3);
$this->info("✅ Mutation Rate Terbaik Terpilih: {$bestPm} (Fitness: {$bestPmFitness})");
// 4. TAHAP 4: UJI ITERASI / GENERASI
$this->newLine();
$this->info("📌 4. MENJALANKAN TABEL 4.4: PENGUJIAN JUMLAH ITERASI");
$iterVariations = [100, 200, 300, 400, 500, 600, 700, 800, 900, 1000];
$tabel4 = [];
$bestIter = 500;
$bestIterFitness = -1;
foreach ($iterVariations as $idx => $iter) {
$engine = new GeneticAlgorithmEngine(
populationSize: $bestPop,
crossoverRate: $bestPc,
mutationRate: $bestPm,
maxGenerations: $iter,
tournamentSize: 3,
elitismCount: 2
);
$res = $engine->run($dataset);
$fitness = $res['bestChromosome']->fitness;
if ($fitness > $bestIterFitness && $bestIterFitness < 1.0) {
$bestIterFitness = $fitness;
$bestIter = $iter;
}
$tabel4[] = [
'Uji Ke-' => $idx + 1,
'Populasi' => $bestPop,
'Pc' => $bestPc,
'Pm' => $bestPm,
'Iterasi' => $iter,
'Fitness Max' => round($fitness, 6),
'Total Penalti' => $res['bestChromosome']->totalPenalty,
'Waktu (s)' => round($res['executionTime'], 4),
];
}
$this->table(['Uji Ke-', 'Populasi', 'Pc', 'Pm', 'Iterasi', 'Fitness Max', 'Penalti', 'Waktu (s)'], $tabel4);
$this->info("✅ Iterasi Terbaik Terpilih: {$bestIter} (Fitness: {$bestIterFitness})");
// 5. TAHAP 5: PENGUJIAN AKHIR (RUN 10 KALI)
$this->newLine();
$this->info("📌 5. MENJALANKAN TABEL 4.5: PENGUJIAN AKHIR (10 KALI EKSEKUSI)");
$tabel5 = [];
$totalFitness = 0;
$totalTime = 0;
for ($run = 1; $run <= 10; $run++) {
$engine = new GeneticAlgorithmEngine(
populationSize: $bestPop,
crossoverRate: $bestPc,
mutationRate: $bestPm,
maxGenerations: $bestIter,
tournamentSize: 3,
elitismCount: 2
);
$res = $engine->run($dataset);
$fitness = $res['bestChromosome']->fitness;
$time = $res['executionTime'];
$totalFitness += $fitness;
$totalTime += $time;
$tabel5[] = [
'Uji Ke-' => $run,
'Populasi' => $bestPop,
'Pc' => $bestPc,
'Pm' => $bestPm,
'Iterasi' => $bestIter,
'Fitness Terbaik' => round($fitness, 6),
'Total Penalti' => $res['bestChromosome']->totalPenalty,
'Run Time (s)' => round($time, 4),
];
}
$avgFitness = round($totalFitness / 10, 6);
$avgTime = round($totalTime / 10, 4);
$tabel5[] = [
'Uji Ke-' => 'Rata-rata',
'Populasi' => $bestPop,
'Pc' => $bestPc,
'Pm' => $bestPm,
'Iterasi' => $bestIter,
'Fitness Terbaik' => $avgFitness,
'Total Penalti' => 0,
'Run Time (s)' => $avgTime,
];
$this->table(['Uji Ke-', 'Populasi', 'Pc', 'Pm', 'Iterasi', 'Fitness Terbaik', 'Penalti', 'Run Time (s)'], $tabel5);
$this->newLine();
$this->info("================================──────────────────────────");
$this->info("🎉 PENGUJIAN GA SELESAI DENGAN SUKSES!");
$this->info("⭐ KOMBINASI TERBAIK: Populasi = {$bestPop}, Pc = {$bestPc}, Pm = {$bestPm}, Iterasi = {$bestIter}");
$this->info("⭐ RATA-RATA FITNESS : {$avgFitness}");
$this->info("⭐ RATA-RATA WAKTU : {$avgTime} detik");
$this->info("================================──────────────────────────");
}
}