@extends('layout.app') @section('content') @php // GENERATE PASANGAN KRITERIA SECARA DINAMIS SESUAI DATABASE $dynamicPairs = []; for ($i = 0; $i < count($kriterias); $i++) { for ($j = $i + 1; $j < count($kriterias); $j++) { $dynamicPairs[] = [ 'kiri_kode' => $kriterias[$i]->kode, 'kiri_nama' => $kriterias[$i]->nama, 'kanan_kode' => $kriterias[$j]->kode, 'kanan_nama' => $kriterias[$j]->nama, ]; } } // Kelompokkan data kuesioner berdasarkan pakar $groupedKuesioner = $dataKuesioner->groupBy('pakar_ke'); $pakarList = $groupedKuesioner->keys()->sort(); // Fungsi Helper untuk merapikan tampilan angka di Matriks function formatCrispMatrix($val) { if ($val == 1) return '1'; if ($val < 1 && $val > 0) { $pembagi = round(1 / $val); return "1/$pembagi"; } if ($val > 1 && floor($val) != $val) { $bulat = round($val); return "" . number_format($val, 2) . " ($bulat)"; } return "" . round($val) . ''; } // Fungsi Helper untuk tabel ringkasan function formatSkalaKuesioner($val) { if ($val == 1) return '1'; if ($val < 1) { $pembagi = round(1 / $val); return "1/$pembagi"; } return round($val); } @endphp
{{-- BAGIAN 1: REFERENSI TFN --}}
Referensi Skala TFN (Chang)
Rumus Konversi Bilangan Fuzzy Segitiga (Triangular Fuzzy Number):
M = (l, m, u) → l = lower (batas bawah), m = medium (nilai tengah/puncak), u = upper (batas atas)
Skala Saaty Linguistik TFN (l, m, u) Nilai Kebalikan (1/u, 1/m, 1/l)
1Sama Penting(1, 1, 1)(1.000, 1.000, 1.000)
2Mendekati Sedikit Lebih Penting(0.5, 1, 1.5)(0.667, 1.000, 2.000)
3Sedikit Lebih Penting(1, 1.5, 2)(0.500, 0.667, 1.000)
4Mendekati Lebih Penting(1.5, 2, 2.5)(0.400, 0.500, 0.667)
5Lebih Penting(2, 2.5, 3)(0.333, 0.400, 0.500)
6Mendekati Sangat Penting(2.5, 3, 3.5)(0.286, 0.333, 0.400)
7Sangat Penting(3, 3.5, 4)(0.250, 0.286, 0.333)
8Mendekati Mutlak Penting(3.5, 4, 4.5)(0.222, 0.250, 0.286)
9Mutlak Lebih Penting(4, 4.5, 4.5)(0.222, 0.222, 0.250)
{{-- BAGIAN 2: RINGKASAN KUESIONER MULTI-PAKAR & KONSENSUS --}}
Ringkasan Kuesioner & Konsensus
@foreach ($pakarList as $p)
@foreach ($groupedKuesioner[$p] as $item) @endforeach
Pasangan Kriteria Skala Asli Representasi TFN
{{ $item->kriteriaKiri->kode }} vs {{ $item->kriteriaKanan->kode }} {{ formatSkalaKuesioner($item->nilai_skala) }} ({{ number_format($item->tfn[0], 2) }}, {{ number_format($item->tfn[1], 2) }}, {{ number_format($item->tfn[2], 2) }})
@endforeach
@foreach ($dynamicPairs as $pair) @php $kiri = $pair['kiri_kode']; $kanan = $pair['kanan_kode']; $crispVal = $crispMatrix[$kiri][$kanan]; $tfnVal = $matrix[$kiri][$kanan]; if ($crispVal == 1) $displayGeo = '1'; elseif ($crispVal < 1) $displayGeo = '1/' . round(1 / $crispVal); else $displayGeo = number_format($crispVal, 2) . ' (' . round($crispVal) . ')'; @endphp @endforeach
Pasangan Kriteria Nilai GeoMean (Bulat) TFN Konsensus
{{ $kiri }} vs {{ $kanan }} {{ $displayGeo }} ({{ number_format($tfnVal[0], 3) }}, {{ number_format($tfnVal[1], 3) }}, {{ number_format($tfnVal[2], 3) }})
{{-- TAHAP AWAL: MATRIKS CRISP --}}
Tahap Awal: Matriks Crisp (Rata-rata Ukur / GeoMean)
Rumus Rata-rata Ukur (Geometric Mean):
Digunakan untuk menggabungkan penilaian dari banyak pakar menjadi satu matriks konsensus (Matriks Crisp).
GM = n√(x1 × x2 × ... × xn)
@foreach ($kodes as $k) @endforeach @foreach ($kodes as $i) @foreach ($kodes as $j) @endforeach @endforeach
Kriteria{{ $k }}
{{ $i }}{!! formatCrispMatrix($crispMatrix[$i][$j]) !!}
{{-- end --}} {{-- TAHAP TAMBAHAN: UJI KONSISTENSI AHP (EIGEN & CR) --}}
Tahap Validasi: Uji Konsistensi (AHP Klasik)
Sesuai kaidah AHP, matriks perbandingan harus diuji konsistensinya sebelum dikonversi ke Fuzzy. Matriks dinyatakan konsisten dan valid jika nilai Consistency Ratio (CR) ≤ 0.10 (10%).
{{-- Tabel Nilai Eigen --}}
1. Priority Vector (Nilai Eigen)
@foreach ($kodes as $k) @endforeach
Kriteria Total Kolom Matriks Nilai Eigen (Priority Vector)
{{ $k }} {{ number_format($colSums[$k], 4) }} {{ number_format($priorityVector[$k], 4) }}
{{-- Perhitungan CR --}}
2. Hasil Uji Konsistensi (CR)
  • λMax (Lambda Maksimum) {{ number_format($lambdaMax, 4) }}
  • n (Jumlah Kriteria) {{ $nKriteria }}
  • CI = (λMax - n) / (n - 1) {{ number_format($ci, 4) }}
  • RI (Random Index n={{ $nKriteria }}) {{ number_format($ri, 2) }}
@php $crPersen = $cr * 100; @endphp
Consistency Ratio (CR)

{{ number_format($crPersen, 2) }}%

@if($cr <= 0.10) MATRIKS KONSISTEN & VALID @else MATRIKS TIDAK KONSISTEN @endif
{{-- TAHAP 1: MATRIKS F-AHP --}}
Tahap 1: Matriks Perbandingan Berpasangan Fuzzy (F-AHP)
Langkah Konversi (Fuzzifikasi): Matriks perbandingan AHP yang telah dinyatakan konsisten (CR ≤ 0.1) di atas, kemudian dikonversikan ke dalam bilangan Fuzzy (l, m, u) menggunakan skala TFN Chang. Untuk nilai di bawah garis diagonal, digunakan matriks kebalikan: M-1 = (1/u, 1/m, 1/l).
@foreach ($kodes as $k) @endforeach @foreach ($kodes as $i) @foreach ($kodes as $j) @php $val = $matrix[$i][$j]; @endphp @endforeach @endforeach
Kriteria{{ $k }}
{{ $i }}({{ number_format($val[0], 3) }}, {{ number_format($val[1], 3) }}, {{ number_format($val[2], 3) }})
{{-- TAHAP 2 --}}
Tahap 2: Nilai Sintesis Fuzzy (Si)
Rumus Sintesis Extent (Chang):
Menjumlahkan nilai TFN pada tiap baris, lalu dikalikan dengan invers dari grand total matriks.
Si = ∑ Mgi ⊗ [ ∑ ∑ Mgi ]-1
@foreach ($si as $kode => $val) @endforeach
Kriteria Vektor Si (l, m, u)
{{ $kode }} ({{ number_format($val[0], 4) }}, {{ number_format($val[1], 4) }}, {{ number_format($val[2], 4) }})
{{-- TAHAP 3 --}}
Tahap 3: Derajat Kemungkinan (V)
Rumus Derajat Kemungkinan:
Mencari nilai probabilitas irisan antar bilangan Fuzzy.
• Jika m2 ≥ m1 maka V = 1.
• Jika l1 ≥ u2 maka V = 0.
V = (l1 - u2)
((m2 - u2) - (m1 - l1))
@foreach ($kodes as $k) @endforeach @foreach ($vMatrix as $i => $rows) @foreach ($rows as $val) @endforeach @endforeach
V(SBaris ≥ SKolom){{ $k }}
{{ $i }} {{ number_format($val, 3) }}
{{-- TAHAP 4: NORMALISASI DAN SKALA 1000 --}}
Tahap 4: Vektor Bobot (d') & Normalisasi Global (W)
Rumus Nilai Bobot & Normalisasi:
Nilai awal d' diambil dari nilai V terkecil (Minimum) pada baris tersebut: d'(Ai) = min V(Si ≥ Sk).
Kemudian dinormalisasi agar total keseluruhan = 1. Terakhir, dikonversi ke skala pasti (1000).
Wi = d'(Ai)
∑ d'(Ak)
{{-- Kolom baru untuk menonjolkan fungsi proteksi Zero-Weight kamu --}} @php $sumDPrime = array_sum($dPrime); @endphp @foreach ($dPrime as $kode => $minV) @php $w = ($sumDPrime > 0) ? ($minV / $sumDPrime) : 0; @endphp {{-- Memanggil data $bobot1000 dari Controller --}} @endforeach {{-- Total pasti 1000 berkat fungsi Largest Remainder --}}
Kriteria Nilai Minimal (d' = min V) Bobot Normalisasi (W) Tingkat Kepentingan (%)Bobot Final (Skala 1000)
{{ $kode }} - {{ $kriterias->where('kode', $kode)->first()->nama }} {{ number_format($minV, 4) }} {{ number_format($w, 4) }}
{{ number_format($w * 100, 2) }}%
{{ isset($bobot1000[$kode]) ? $bobot1000[$kode] : '-' }}
Total {{ number_format($sumDPrime, 4) }} 1.0000 100% {{ isset($bobot1000) ? array_sum($bobot1000) : '-' }}
@endsection