Bagian 4 dari seri

Perhitungan SAW Laravel: Normalisasi dan Nilai Preferensi

Diterbitkan 21 September 2026

Pada bagian ini buat SawService. Salin kode berikut apa adanya.

Buat Folder Service

Buat folder:

app/Services

Lalu buat:

app/Services/SawService.php

SawService

<?php

namespace App\Services;

use InvalidArgumentException;

class SawService
{
    public function calculate(
        array $matrix,
        array $weights,
        array $attributes
    ): array {
        if (empty($matrix)) {
            throw new InvalidArgumentException(
                'Matriks keputusan tidak boleh kosong.'
            );
        }

        $alternativeIds = array_keys($matrix);
        $criteriaIds = array_keys(reset($matrix));

        $normalizedWeights = $this->normalizeWeights(
            $weights,
            $criteriaIds
        );

        $normalized = $this->normalizeMatrix(
            $matrix,
            $attributes,
            $alternativeIds,
            $criteriaIds
        );

        $preferences = $this->preferences(
            $normalized,
            $normalizedWeights,
            $alternativeIds,
            $criteriaIds
        );

        return [
            'weights' => $normalizedWeights,
            'normalized' => $normalized,
            'preferences' => $preferences,
        ];
    }

    public function normalizeWeights(
        array $weights,
        array $criteriaIds
    ): array {
        $total = 0.0;

        foreach ($criteriaIds as $criteriaId) {
            $weight = (float) ($weights[$criteriaId] ?? 0);

            if ($weight <= 0) {
                throw new InvalidArgumentException(
                    'Semua bobot kriteria harus lebih besar dari 0.'
                );
            }

            $total += $weight;
        }

        $result = [];

        foreach ($criteriaIds as $criteriaId) {
            $result[$criteriaId] =
                (float) $weights[$criteriaId] / $total;
        }

        return $result;
    }

    public function normalizeMatrix(
        array $matrix,
        array $attributes,
        array $alternativeIds,
        array $criteriaIds
    ): array {
        $normalized = [];

        foreach ($criteriaIds as $criteriaId) {
            $values = [];

            foreach ($alternativeIds as $alternativeId) {
                $values[] =
                    (float) $matrix[$alternativeId][$criteriaId];
            }

            $attribute =
                $attributes[$criteriaId] ?? null;

            if ($attribute === 'benefit') {
                $maxValue = max($values);

                if ($maxValue == 0.0) {
                    throw new InvalidArgumentException(
                        "Nilai maksimum kriteria ID {$criteriaId} adalah 0."
                    );
                }

                foreach ($alternativeIds as $alternativeId) {
                    $normalized[$alternativeId][$criteriaId] =
                        (float) $matrix[$alternativeId][$criteriaId]
                        / $maxValue;
                }
            } elseif ($attribute === 'cost') {
                $minValue = min($values);

                if ($minValue <= 0.0) {
                    throw new InvalidArgumentException(
                        "Nilai minimum kriteria cost ID {$criteriaId} harus lebih besar dari 0."
                    );
                }

                foreach ($alternativeIds as $alternativeId) {
                    $value =
                        (float) $matrix[$alternativeId][$criteriaId];

                    if ($value <= 0.0) {
                        throw new InvalidArgumentException(
                            "Nilai kriteria cost ID {$criteriaId} harus lebih besar dari 0."
                        );
                    }

                    $normalized[$alternativeId][$criteriaId] =
                        $minValue / $value;
                }
            } else {
                throw new InvalidArgumentException(
                    "Atribut kriteria ID {$criteriaId} tidak valid."
                );
            }
        }

        return $normalized;
    }

    public function preferences(
        array $normalized,
        array $weights,
        array $alternativeIds,
        array $criteriaIds
    ): array {
        $preferences = [];

        foreach ($alternativeIds as $alternativeId) {
            $score = 0.0;

            foreach ($criteriaIds as $criteriaId) {
                $score +=
                    $normalized[$alternativeId][$criteriaId]
                    * $weights[$criteriaId];
            }

            $preferences[$alternativeId] = $score;
        }

        return $preferences;
    }
}

Urutan Perhitungan

Service menjalankan:

1. Normalisasi bobot
2. Normalisasi matriks
3. Perhitungan nilai preferensi

Aturan normalisasi:

benefit:
r = nilai / nilai maksimum

cost:
r = nilai minimum / nilai

Nilai preferensi:

V = Σ (bobot × nilai normalisasi)

Nilai preferensi terbesar mendapat ranking tertinggi.

Data Detail yang Dihasilkan Service

weights
normalized
preferences

Data tersebut dipakai pada halaman hasil.

Menyiapkan Matriks dari Database

$kriteria = Kriteria::orderBy('kode')->get();
$alternatif = Alternatif::orderBy('kode')->get();
$penilaian = Penilaian::all();

$matrix = [];
$weights = [];
$attributes = [];

foreach ($kriteria as $itemKriteria) {
    $weights[$itemKriteria->id] =
        (float) $itemKriteria->bobot;

    $attributes[$itemKriteria->id] =
        $itemKriteria->atribut;
}

$nilaiMap = $penilaian->keyBy(function ($item) {
    return $item->alternatif_id
        . '-'
        . $item->kriteria_id;
});

foreach ($alternatif as $itemAlternatif) {
    foreach ($kriteria as $itemKriteria) {
        $key =
            $itemAlternatif->id
            . '-'
            . $itemKriteria->id;

        $matrix[$itemAlternatif->id][$itemKriteria->id] =
            (float) $nilaiMap[$key]->nilai;
    }
}

Memanggil Service

$hasil = $saw->calculate(
    $matrix,
    $weights,
    $attributes
);

Hasil:

[
    'weights' => ...,
    'normalized' => ...,
    'preferences' => ...,
]

Checkpoint

Pastikan:

  • bobot dinormalisasi;
  • atribut benefit dan cost dihitung berbeda;
  • matriks normalisasi terbentuk;
  • nilai preferensi dihitung;
  • nilai terbesar menjadi ranking tertinggi.

Lanjut: Hasil Ranking SAW