174 lines
5.2 KiB
PHP
174 lines
5.2 KiB
PHP
<?php
|
|
/*
|
|
* Metode Triple Exponential Smoothing Holt-Winter Multiplicative
|
|
*
|
|
* factors / parameters:
|
|
* alpha: data smoothing factor 0 < alpha < 1
|
|
* beta: trend smoothing factor 0 < beta < 1
|
|
* gamma: seasonal smoothing factor 0 < gamma < 1
|
|
* L: period length
|
|
* */
|
|
|
|
class ExponentialSmoothing
|
|
{
|
|
private $alpha;
|
|
private $beta;
|
|
private $gamma;
|
|
private $L; // periode bulan sebelumnya
|
|
private $series; // data aktual
|
|
private $levels;
|
|
private $trends;
|
|
private $seasonals;
|
|
|
|
// digunakan untuk instansiasi object
|
|
function __construct($alpha, $beta, $gamma, $L, $series)
|
|
{
|
|
$this->alpha = $alpha;
|
|
$this->beta = $beta;
|
|
$this->gamma = $gamma;
|
|
$this->L = $L;
|
|
$this->series = $series;
|
|
|
|
$this->build_model();
|
|
}
|
|
|
|
// digunakan untuk perhitungan pemulusan, peramalan
|
|
private function build_model()
|
|
{
|
|
// Memanggil fungsi untuk menentukan nilai awal
|
|
$this->initialize_levels();
|
|
$this->initialize_trends();
|
|
$this->initialize_seasonals();
|
|
|
|
// fungsi untuk menghitung pemulusan dan peramalan
|
|
for ($i = $this->L; $i < count($this->series); $i++) {
|
|
$x = $this->series[$i];
|
|
$s0 = $this->seasonals[$i-$this->L];
|
|
$l0 = $this->levels[$i-1];
|
|
$t0 = $this->trends[$i-1];
|
|
|
|
// perhitungan rumus Lt, Bt, St
|
|
$l = $this->alpha * $x / $s0 + (1 - $this->alpha) * ($l0 + $t0);
|
|
$t = $this->beta * ($l - $l0) + (1 - $this->beta) * $t0;
|
|
$s = $this->gamma * ($x / $l) + (1 - $this->gamma) * $s0;
|
|
|
|
$this->levels[$i] = $l;
|
|
$this->trends[$i] = $t;
|
|
$this->seasonals[$i] = $s;
|
|
}
|
|
}
|
|
|
|
// digunakan untuk mengambil nilai dari perhitungan pemulusan tren
|
|
public function get_trens(){
|
|
return $this->trends;
|
|
}
|
|
|
|
// digunakan untuk mengambil nilai dari perhitungan pemulusan level
|
|
public function get_levels(){
|
|
return $this->levels;
|
|
}
|
|
|
|
// digunakan untuk mengambil nilai dari perhitungan pemulusan seasonal
|
|
public function get_seasonals(){
|
|
return $this->seasonals;
|
|
}
|
|
|
|
// fungsi digunakan untuk menginisialisasi nilai awal level
|
|
private function initialize_levels()
|
|
{
|
|
$this->levels = array();
|
|
$sum = 0;
|
|
for ($i = 0; $i < $this->L - 1; $i++) {
|
|
$this->levels[] = null;
|
|
$sum += $this->series[$i];
|
|
}
|
|
$sum += $this->series[$this->L-1];
|
|
$this->levels[] = $sum / $this->L;
|
|
// echo "<br>level". $sum / $this->L;
|
|
}
|
|
|
|
// fungsi digunakan untuk menginisialisasi nilai awal tren
|
|
private function initialize_trends()
|
|
{
|
|
$this->trends = array();
|
|
for ($i = 0; $i < $this->L - 1; $i++) {
|
|
$this->trends[] = null;
|
|
}
|
|
|
|
$y = 0;
|
|
$sum = 0;
|
|
for ($i = 0; $i < $this->L; $i++) {
|
|
$y = $this->L+$i;
|
|
$sum += ($this->series[$y]-$this->series[$i])/$this->L;
|
|
// echo "<br>series y".($y+1).": ". $this->series[$y];
|
|
// echo "<br>series i".($i+1).": ". $this->series[$i];
|
|
}
|
|
|
|
|
|
$nilaiAwal = $sum/$this->L;
|
|
$this->trends[] = $nilaiAwal;
|
|
}
|
|
|
|
// fungsi digunakan untuk menginisialisasi nilai awal seasonal
|
|
private function initialize_seasonals()
|
|
{
|
|
$this->seasonals = array();
|
|
for ($i = 0; $i < $this->L; $i++) {
|
|
$this->seasonals[] = $this->series[$i] / $this->levels[$this->L-1];
|
|
// echo "<br>sesional".$i .": ". $this->series[$i] / $this->levels[$this->L-1];
|
|
}
|
|
}
|
|
|
|
// Fungsi untuk mengolah peramalan periode bulan selanjutnya
|
|
public function forecast($k)
|
|
{
|
|
$m = $k - count($this->series) + 1;
|
|
if ($m <= 0) {
|
|
throw new Exception("Supposed to forecast future series");
|
|
}
|
|
|
|
// Rumus : (Lt+bt*m)*St-s+m
|
|
$i = count($this->series)-1;
|
|
$j = $i - $this->L + (($m-1) % $this->L) + 1;
|
|
// echo "<br>j : ". $j;
|
|
// echo "<br>m : ". $m . "<br>";
|
|
$forecast = ($this->levels[$i] + $m * $this->trends[$i]) * $this->seasonals[$j];
|
|
|
|
return $forecast;
|
|
}
|
|
|
|
// Fungsi ini digunakan untuk perhitungan peralaman pada data aktual bulan sebelumnya
|
|
public function get_forecast()
|
|
{
|
|
/*
|
|
Keterangan :
|
|
Lt = Pemulusan Level
|
|
Bt = Pemulusan Trend
|
|
St = Pemulusan Musiman
|
|
Ft+m = Peramalan untuk periode ke depan.
|
|
|
|
Rumus : (Lt+bt*m)*St-s+m
|
|
*/
|
|
|
|
$data = array();
|
|
$m = 1;
|
|
for ($i = 0; $i < count($this->series); $i++) {
|
|
$j = ($i)-$this->L;
|
|
|
|
if ($i>=$this->L) {
|
|
// echo "<br>lt".($i).": ". $this->levels[$i-1];
|
|
// echo "<br>btm".($i).": ". $this->trends[$i-1];
|
|
// echo "<br>sts".($i).": ". $this->seasonals[$j];
|
|
$forecast = ($this->levels[$i-1] + $m * $this->trends[$i-1]) * $this->seasonals[$j];
|
|
// echo "<br>ft".($i+1).": ". $forecast;
|
|
// echo " <br>";
|
|
$data[] = $forecast;
|
|
}else{
|
|
$data[] = null;
|
|
}
|
|
}
|
|
|
|
return $data;
|
|
}
|
|
}
|