Model multiplikatywny/addytywny Wintersa

Jest to model który używany jest w przypadku gdy w szeregu czasowym pojawia się: trend, wahania sezonowe (addytywne lub multiplikatywne) oraz wahania przypadkowe. Dla osób zainteresowanych tylko programem można go pobrać tutaj:

metoda-wintersa-wersja-1-2

 

(Program działa na systemach operacyjnych windows 7+)

 


Metod Wintersa jest pełną metodą wykorzystującą w prognozie wahania losowe, trend(liniowy) oraz sezonowość(addytywną lub multiplikatywną). Wygładzaniu ulegają zatem trzy elementy:

  • Poziom zmiennej, reprezentowany przez parametr α (alfa) wygładza wahania przypadkowe, α∈<0,1>
  • Przyrost, reprezentowany przez parametr β  (beta) wygładza trend, β∈<0,1>
  • Sezonowość, reprezentowany przez parametr γ  (gamma) wygładza trend, γ ∈<0,1>

Jeśli chodzi o sezonowość możemy wybrać dwa warianty:

Wariant addytywny- wykorzystywany gdy efekt danego sezonu jest stały w czasie

winters_1Wariant multiplikatywny – gdy udział efektów sezonowości jest stały w wartości zmiennej

winters_2Za wartość

winters_33

 

 

 

Zaczynamy standardowo od utworzenia nowego projektu. Elementy do lozlokowania podaje poniżej:

Rodzaj elementu Nazwa elementu ustawienia
Form ModelBrowna Name: ModelBrowna
Text: Model Browna
Size: 1081; 716
DataGridView dgv_dane Name: dgv_dane
AllowUserToAddRows: False
AllowUserToDeleteRows: False
AllowUserToOrderColumn: True
AllowUserToResizeColumns: False
AllowUserToResizeRows: False
AutoSizeColumnsMode: Fill
Size: 566; 320
Location: 12; 29
label ie Text: „0”
Location: 105;380
Name: ie
label SumaRoznic Text: „0”
Location: 105;407
Name: SumaRoznic
label SumaKwadratow Text: „0”
Location: 105;435
Name: SumaKwadratow
label Prognoza Text: „0”
Location: 105;380
Name: Prognoza
label Mape Text: „0”
Location: 293;380
Name: Mape
label Mse Text: „0”
Location: 293;409
Name: Mse
label Rmse Text: „0”
Location: 293;436
Name: Rmse
label WspTheila Text: „0”
Location: 293;460
Name: WspTheila
label me_ Text: „0”
Location: 293;484
Name: me_
label Rmspe Text: „0”
Location: 293;508
Name: Rmspe
label MAE Text: „0”
Location: 293; 547
Name: MAE
label MPE Text: „0”
Location: 240; 572
Name: MPE
MenuStrip1 MenuStrip1 Name: MenuStrip1Dodano w menu:
Dane
– Dodaj dane
– Zakończ
Textbox FilePath Name: FilePath
Location: 123;3
Size: 560;20
Button Odswiez Name: Odswiez
Location: 108; 630
Size: 75; 37
Enabled: false
Chart Wykres1 Name: Wykres1
Location: 785; 35
Size: 268; 187
Ilość serii danych: 2
OpenFileDialog WczytajDane Name: WczytajDane
Chart wykres2 Name: Wykres2
Location: 587; 228
Size: 466; 280
Ilość serii: 2
Chart wykres3 Name: Wykres3
Location: 587; 514
Size: 466; 153
Ilość serii: 2
label Mape_dla_prognozy Text: „0”
Location: 411; 630
Name: Mape_dla_prognozy
TextBox Beta Name: Beta
Location: 58; 539
Size: 43; 20
TextBox Alfa Name: Alfa
Location: 56; 498
Size: 43; 20
TextBox Gamma Name: Gamma
Location: 58; 575
Size: 43; 20
TextBox DlugoscCyklu Name: DlugoscCyklu
Location: 54; 639
Size: 43; 20
RadioButton MultiplikatywnyRB Name: MultiplikatywnyRB
Location: 414; 447
Text: Multiplikatywny
RadioButton AddytywnyRB Name: AddytywnyRB
Location: 414; 471
Text: Addytywny

Po rozłożeniu wszystkich elementów na formę powinna ona wyglądać tak:

metoda_wintersa1

Rozłożenie opisów zostawiam wam do zrobienia. Po dodaniu opisów forma powinna wyglądać tak jak na obrazku:

metoda_wintersa2

Należy pamiętać aby nasze dwa wykresy miały ustawione dwie serie danych, aby to zrobić wybieramy nasz wykres i w jego właściwościach znajdujemy „Series”:

mtbrowna2

Stronę graficzną mamy już z głowy. Zajmijmy się stroną techniczną. Na początek importujemy wymagane elementy i inicjujemy stałe zmienne:

Imports System.Windows.Forms.DataVisualization.Charting

Public Class Metoda_Wintersa
    Private filename As String ''przechowuje ścieżkę naszego pliku 
    Dim wartoscAlfa As Double = 0.45 ''początkowa wartość Alfa
    Dim wartoscBeta As Double = 0.8 ''początkowa wartość Beta
    Dim wartoscGamma As Double = 0.19 ''początkowa wartość Gamma
    Dim LiczbaFaz As Integer = 3 ''początkowa liczba faz
    Dim dane As New List(Of Double) ''przechowuje nasze dane w formie tablicy
    Dim kontroler As Boolean = True 'sprawdza czy dane są wczytane
(....)

Stworzymy teraz sobie obsługę przycisku wczytującego dane do programu z pliku *.txt, *.csv

 

    Private Sub DodajDaneToolStripMenuItem_Click(sender As Object, e As EventArgs) Handles DodajDaneToolStripMenuItem.Click
        Odswiez.Enabled = True 'Odblokowuje przycisk
        MultiplikatywnyRB.Checked = True 'Wybiera rodzaj początkowego modelu
        'filtr danych
        WczytajDane.Filter = "csv files|;*.csv;*.txt"
        WczytajDane.Title = "Select a csv file"
        WczytajDane.FileName = ""
        Try
            With WczytajDane
                If .ShowDialog() = DialogResult.OK Then
                    '' kontroler posłuży nam do zaznaczania czy dane są wczytanie czy też nie,
                    '' daje to możliwość załadowania innych danych jeśli te nam już nie będą potrzebna.
                    If kontroler = False Then 'jeśli jakieś dane są załadowane to ....
                        dane.Clear() 'czyści tablice
                        dgv_dane.Rows.Clear() 'czyści datagridview
                        filename = .FileName 'ładuje ścieżkę pliku do zmiennej string
                        FilePath.Text = filename 'wizualizuje ścieżkę pliku w textboxie
                        alfa.Text = wartoscAlfa.ToString ' wizualizuje wzsłczynnik alfa
                        Beta.Text = wartoscBeta.ToString ' wizualizuje wzsłczynnik beta
                        Gamma.Text = wartoscGamma.ToString ' wizualizuje wzsłczynnik Gamma
                        DlugoscCyklu.Text = LiczbaFaz '' wizualizuje ilość cykli
                        TworzTabele(filename) ' funkcja przetwarzająca nasze dane z 
                        'pliku txt i ładujące je do tablicy (nie gotowa na tym etapie)
                        Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz) ' funkcja tworząca metode Browna (nie gotowa na tym etapie)
                        tworz_wykres() ' funkcja ładująca dane do wykresu (nie gotowa na tym etapie)
                    Else
                        'pierwsze załadowanie danych
                        filename = .FileName
                        FilePath.Text = filename
                        alfa.Text = wartoscAlfa.ToString
                        Beta.Text = wartoscBeta.ToString
                        Gamma.Text = wartoscGamma.ToString
                        DlugoscCyklu.Text = LiczbaFaz
                        TworzTabele(filename)
                        Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
                        tworz_wykres()
                        kontroler = False
                    End If
                End If
            End With
        Catch ex As Exception
        End Try
    End Sub

Teraz należy nasze załadowane dane przenieść do tablicy „dane” robimy to za pomocą metody:

    Private Sub TworzTabele(ByVal sciezkaDoPliku As String)
        Dim i As Integer
        Dim wartosc As String() 'przechowuje dane z pliku
        Dim f As IO.File = Nothing
        Dim rodzajkodu As New IO.StreamReader(sciezkaDoPliku, System.Text.Encoding.UTF8)
        Try
            wartosc = rodzajkodu.ReadLine().Split(ControlChars.Tab) 'rodzaj separatora w tym wypadku "Enter"
            For i = 0 To wartosc.Length() - 1
                dane.Add(wartosc(i).ToString)
            Next
            While rodzajkodu.Peek() <> -1
                wartosc = rodzajkodu.ReadLine().Split()
                For i = 0 To wartosc.Length() - 1
                    dane.Add(wartosc(i).ToString) 'Ładuje dane do tablicy dane
                Next
            End While
        Catch ex As Exception
            MsgBox("Error: " & ex.Message)
        Finally
            rodzajkodu.Close()
        End Try
    End Sub

Teraz Stworzymy sobie kod naszej metody:

    Private Sub Metoda_Wintersa(ByVal alfa As Double, ByVal beta As Double, ByVal gamma As Double, ByVal r As Integer)
        Dim dane1 As Double = 0
        Dim dane2 As Double = 0
        Dim dane3 As Double = 0
        Dim dane4 As Double = 0
        Dim dane5 As Double = 0
        Dim dane6 As Double = 0
        Dim dane7 As Double = 0
        Dim Srednia As Double = 0
        Dim PierwszyWyrazSt As Double = 0
        Dim wartosciPoczatkowe As Double = 0
        'Adby dodać wartości Ft i Ct 
        'Potrzebujemy zmiennych 
        'Średniej
        For i As Integer = 0 To r - 1
            Srednia += (dane(i))
        Next
        Srednia = Srednia / (r)
        'Średnich z wyrazów r+1,r+2,....
        For i As Integer = 0 To r - 1
            PierwszyWyrazSt += dane(i + r)
        Next
        PierwszyWyrazSt = PierwszyWyrazSt / (r) - Srednia
        Try
            dgv_dane.ColumnCount = 10
            dgv_dane.Columns(0).Name = "t"
            dgv_dane.Columns(1).Name = "yt"
            'Wygładzenia
            dgv_dane.Columns(2).Name = "Ft"
            dgv_dane.Columns(3).Name = "St"
            dgv_dane.Columns(4).Name = "Ct"
            'Prognozy wygasłe
            dgv_dane.Columns(5).Name = "yt*"
            'błąd bezwzględny
            dgv_dane.Columns(6).Name = "yt-y*t"
            'błąd do kwadratu
            dgv_dane.Columns(7).Name = "(yt-y*t)^2"
            'błąd względny
            dgv_dane.Columns(8).Name = "|(yt-y*t)/yt|"
            dgv_dane.Columns(9).Name = "yt^2"

            '' Dodaje t (numeracje wierszy powiększoną o ilość cykli)
            For i As Integer = 0 To dane.Count + r - 1
                dgv_dane.Rows.Add()    'wypełnia datagridview wierszami
                dgv_dane.Rows(i).Cells(0).Value = i + 1   ' dodaje numeracje
                dgv_dane.Rows(i).Cells(0).Style.Alignment = DataGridViewContentAlignment.MiddleCenter

            Next
            '' Dodaje yt (nasze dane)
            For i As Integer = 0 To dane.Count - 1
                dgv_dane.Rows(i).Cells(1).Value = dane(i)
            Next
            '' Początkowe warości Ft,St,Ct
            '' Ft, St i metoda Ct muszą być tworzone jednocześnie
            'Wartość początkowa Ft
            dgv_dane.Rows(r - 1).Cells(2).Value = Math.Round(Srednia, 2)
            dgv_dane.Rows(r - 1).Cells(2).Style.BackColor = Color.Yellow 'kolor żółty dla pierwszego elementu
            'Wartość początkowa St
            dgv_dane.Rows(r - 1).Cells(3).Value = Math.Round(PierwszyWyrazSt, 2)
            dgv_dane.Rows(r - 1).Cells(3).Style.BackColor = Color.Yellow 'kolor żółty dla pierwszego elementu
            'Wartości początkowe Ct
            For i As Integer = 0 To r - 1
                wartosciPoczatkowe = 0
                For j As Integer = 0 To r - 1
                    wartosciPoczatkowe += (dane(j + i))
                Next
                wartosciPoczatkowe = wartosciPoczatkowe / (r)
                dgv_dane.Rows(i).Cells(4).Value = Math.Round(dane(i) / wartosciPoczatkowe, 4)
                dgv_dane.Rows(i).Cells(4).Style.BackColor = Color.LightCoral 'kolor LightCoral dla pierwszych elementów
            Next

            ''''''
            'Reszta wartości Ft,St,Ct
            For i As Integer = r To dane.Count - 1
                'Ft
                If MultiplikatywnyRB.Checked = True Then
                    dgv_dane.Rows(i).Cells(2).Value = Math.Round(wartoscAlfa * (dane(i) / dgv_dane.Rows(i - r).Cells(4).Value) + (1 - wartoscAlfa) * (dgv_dane.Rows(i - 1).Cells(2).Value + dgv_dane.Rows(i - 1).Cells(3).Value), 2)
                    dgv_dane.Rows(i).Cells(2).Style.BackColor = Color.LightSkyBlue
                Else
                    dgv_dane.Rows(i).Cells(2).Value = Math.Round(wartoscAlfa * (dane(i) - dgv_dane.Rows(i - r).Cells(4).Value) + (1 - wartoscAlfa) * (dgv_dane.Rows(i - 1).Cells(2).Value + dgv_dane.Rows(i - 1).Cells(3).Value), 2)
                    dgv_dane.Rows(i).Cells(2).Style.BackColor = Color.LightPink
                End If
                'St
                dgv_dane.Rows(i).Cells(3).Value = Math.Round(wartoscBeta * (dgv_dane.Rows(i).Cells(2).Value - dgv_dane.Rows(i - 1).Cells(2).Value) + (1 - wartoscBeta) * dgv_dane.Rows(i - 1).Cells(3).Value, 2)
                dgv_dane.Rows(i).Cells(3).Style.BackColor = Color.LightSkyBlue
                'Ct
                If MultiplikatywnyRB.Checked = True Then
                    dgv_dane.Rows(i).Cells(4).Value = Math.Round(gamma * (dane(i) / dgv_dane.Rows(i).Cells(2).Value) + (1 - gamma) * dgv_dane.Rows(i - r).Cells(4).Value, 4)
                    dgv_dane.Rows(i).Cells(4).Style.BackColor = Color.LightGreen
                Else
                    dgv_dane.Rows(i).Cells(4).Value = Math.Round(gamma * (dane(i) - dgv_dane.Rows(i).Cells(2).Value) + (1 - gamma) * dgv_dane.Rows(i - r).Cells(4).Value, 4)
                    dgv_dane.Rows(i).Cells(4).Style.BackColor = Color.LightPink
                End If
            Next
            '' dodaje yt*
            For i As Integer = r To dane.Count + r - 1
                If MultiplikatywnyRB.Checked = True Then
                    If i > dane.Count - 1 Then
                        'Dodaje naszą prognoze
                        dgv_dane.Rows(i).Cells(5).Value = Math.Round((dgv_dane.Rows(dane.Count - 1).Cells(2).Value + (i + 1 - dane.Count) * dgv_dane.Rows(dane.Count - 1).Cells(3).Value) * dgv_dane.Rows(i - r).Cells(4).Value, 2)
                        dgv_dane.Rows(i).Cells(5).Style.BackColor = Color.LightGray
                    Else
                        'Dodaje prognozy wygasłe
                        dgv_dane.Rows(i).Cells(5).Value = Math.Round((dgv_dane.Rows(i - 1).Cells(2).Value + dgv_dane.Rows(i - 1).Cells(3).Value) * dgv_dane.Rows(i - r).Cells(4).Value, 2)
                        dgv_dane.Rows(i).Cells(5).Style.BackColor = Color.LightGray
                    End If
                Else
                    If i > dane.Count - 1 Then
                        'Dodaje naszą prognoze
                        dgv_dane.Rows(i).Cells(5).Value = Math.Round(dgv_dane.Rows(dane.Count - 1).Cells(2).Value + (i + 1 - dane.Count) * dgv_dane.Rows(dane.Count - 1).Cells(3).Value + dgv_dane.Rows(i - r).Cells(4).Value, 2)
                        dgv_dane.Rows(i).Cells(5).Style.BackColor = Color.LightGray
                    Else
                        'Dodaje prognozy wygasłe
                        dgv_dane.Rows(i).Cells(5).Value = Math.Round(dgv_dane.Rows(i - 1).Cells(2).Value + dgv_dane.Rows(i - 1).Cells(3).Value + dgv_dane.Rows(i - r).Cells(4).Value, 2)
                        dgv_dane.Rows(i).Cells(5).Style.BackColor = Color.LightGray
                    End If

                End If
            Next
            '' dodaje yt-y*t
            For i As Integer = r To dane.Count - 1
                dgv_dane.Rows(i).Cells(6).Value = Math.Round(dane(i) - dgv_dane.Rows(i).Cells(5).Value, 3)
            Next
            '' Dodaje (yt-y*t)^2
            For i As Integer = r To dane.Count - 1
                dgv_dane.Rows(i).Cells(7).Value = Math.Round(dgv_dane.Rows(i).Cells(6).Value ^ 2, 3)
            Next
            '' Dodaje |(yt-y*t)/yt|
            For i As Integer = r To dane.Count - 1
                dgv_dane.Rows(i).Cells(8).Value = Math.Round(Math.Abs(dgv_dane.Rows(i).Cells(6).Value / dane(i)), 6)
            Next
            '' Dodaje yt^2
            For i As Integer = 0 To dane.Count - 1
                dgv_dane.Rows(i).Cells(9).Value = Math.Round(dane(i) ^ 2, 3)
            Next
            ''Przygotowanie zmiennych do Obliczeń
            '' Suma (yt-y*t)
            For i As Integer = 0 To dane.Count - 1
                dane1 += dgv_dane.Rows(i).Cells(6).Value
            Next
            '' Suma (yt-y*t)^2
            For i As Integer = 0 To dane.Count - 1
                dane2 += dgv_dane.Rows(i).Cells(7).Value
            Next
            '' suma |(yt-y*t)/yt|
            For i As Integer = 0 To dane.Count - 1
                dane3 += dgv_dane.Rows(i).Cells(8).Value
            Next
            '' Suma ((yt-y*t)/yt)^2
            For i As Integer = 0 To dane.Count - 1
                dane4 += dgv_dane.Rows(i).Cells(8).Value ^ 2
            Next
            '' Suma yt^2
            For i As Integer = 0 To dane.Count - 1
                dane5 += dgv_dane.Rows(i).Cells(9).Value
            Next
            'suma ((yt-y*t)/yt)
            For i As Integer = r To dane.Count - 1
                dane6 += dgv_dane.Rows(i).Cells(6).Value / dane(i)
            Next
            'suma |(yt-y*t)|
            For i As Integer = 0 To dane.Count - 1
                dane7 += Math.Abs(dgv_dane.Rows(i).Cells(6).Value)
            Next

            ''Wyświetlanie obliczeń
            Rmspe.Text = Math.Round(Math.Sqrt(((1 / (dane.Count - r)) * (dane4))) * 100, 2) 'RMSPE
            me_.Text = Math.Round((1 / (dane.Count - 1)) * dane1, 2) 'ME
            Mse.Text = Math.Round((dane2) / (dane.Count - r), 2) ' MSE
            MAE.Text = Math.Round((dane7) / (dane.Count - r), 2) ' MAE
            Rmse.Text = Math.Round(Math.Sqrt(Mse.Text), 2) 'RMSE, musi być pod Mmse
            MPE.Text = Math.Round((dane6) / (dane.Count - r) * 100, 2)
            Mape.Text = Math.Round((((dane3) / (dane.Count - r))) * 100, 2) 'MAPE
            ie.Text = dane.Count  'ilość elementów
            SumaRoznic.Text = dane2 'suma (yt-y*t)^2
            SumaKwadratow.Text = Math.Round(dane5, 2) 'suma yt^2
            WspTheila.Text = Math.Round(SumaRoznic.Text / SumaKwadratow.Text, 6)
            Mape_dla_prognozy1.Text = Math.Round(Rmse.Text / (dgv_dane.Rows(dgv_dane.Rows.Count - r + 1).Cells(5).Value) * 100, 2)
        Catch ex As Exception
            MsgBox("Error building datatable: " & ex.Message)
        End Try
    End Sub

Teraz dodamy metodę tworzącą wykresy naszego modelu:

    Private Sub tworz_wykres()
        'Wykres prezentujący nasze dane i prognoze
        wykres2.ChartAreas(0).AxisX.MajorGrid.LineColor = Color.LightGray
        wykres2.ChartAreas(0).AxisY.MajorGrid.LineColor = Color.LightGray
        wykres2.Series(0).ChartType = DataVisualization.Charting.SeriesChartType.Line
        wykres2.Series(0).Points.Clear()
        wykres2.Series(0).Name = "yt"
        wykres2.Series(0).BorderWidth = 2
        For Count As Integer = 0 To dgv_dane.Rows.Count - 1
            wykres2.Series(0).Points.AddXY(dgv_dane.Item(0, Count).Value, dgv_dane.Item(1, Count).Value)
        Next
        wykres2.Series(1).ChartType = DataVisualization.Charting.SeriesChartType.Line
        wykres2.Series(1).Points.Clear()
        wykres2.Series(1).Color = Color.Red
        wykres2.Series(1).Name = "y*t"
        wykres2.Series(1).BorderWidth = 2
        For Count As Integer = 0 To dgv_dane.Rows.Count - 1
            wykres2.Series(1).Points.AddXY(dgv_dane.Item(0, Count).Value, dgv_dane.Item(5, Count).Value)
        Next
        wykres2.Legends(0).Docking = Docking.Top
        'wykres prezentujące ostatnie pięć zmiennych
        Wykres1.ChartAreas(0).AxisX.MajorGrid.LineColor = Color.LightGray
        Wykres1.ChartAreas(0).AxisY.MajorGrid.LineColor = Color.LightGray
        Wykres1.Series(0).ChartType = DataVisualization.Charting.SeriesChartType.Line
        Wykres1.Series(0).Points.Clear()
        Wykres1.Series(0).Name = "yt"
        Wykres1.Series(0).BorderWidth = 2
        Wykres1.Series(0).IsValueShownAsLabel = True
        Wykres1.Series(0).LabelBorderColor = Color.LightBlue

        For Count As Integer = dgv_dane.Rows.Count - 8 To dgv_dane.Rows.Count - 1
            Wykres1.Series(0).Points.AddXY(dgv_dane.Item(0, Count).Value, dgv_dane.Item(1, Count).Value)
        Next
        Wykres1.Series(1).ChartType = DataVisualization.Charting.SeriesChartType.Line
        Wykres1.Series(1).Points.Clear()
        Wykres1.Series(1).Color = Color.Red
        Wykres1.Series(1).Name = "y*t"
        Wykres1.Series(1).BorderWidth = 2
        Wykres1.Series(1).IsValueShownAsLabel = True
        Wykres1.Series(1).LabelBorderColor = Color.LightCoral

        For Count As Integer = dgv_dane.Rows.Count - 8 To dgv_dane.Rows.Count - 1
            Wykres1.Series(1).Points.AddXY(dgv_dane.Item(0, Count).Value, Math.Round(dgv_dane.Item(5, Count).Value))
        Next
        Wykres1.Legends(0).Docking = Docking.Top
        'Wykres prezentujący sezonowość naszych danych
        wykres3.Series(0).ChartType = DataVisualization.Charting.SeriesChartType.Line
        wykres3.Series(0).Points.Clear()
        wykres3.Series(0).Name = "Ct"
        wykres3.Series(0).BorderWidth = 2
        wykres3.ChartAreas(0).AxisX.MajorGrid.LineColor = Color.LightGray
        wykres3.ChartAreas(0).AxisY.MajorGrid.LineColor = Color.LightGray
        For Count As Integer = 0 To dgv_dane.Rows.Count - 5
            wykres3.Series(0).Points.AddXY(dgv_dane.Item(0, Count).Value, dgv_dane.Item(4, Count).Value)
        Next
        wykres3.Legends(0).Docking = Docking.Top
    End Sub

Następnie dodajemy funkcjonalność naszego przycisku „Odśwież”, dodałem tu taką właściwość przycisku, że jeśli do textboxa zostaną wpisane inne cyfry/litery niż te należące do zestawu liczb całkowitych dodatnich program wyświetli komunikat i ustawi tą wartość standardowo na 4:

    Private Sub Odswiez_Click(sender As Object, e As EventArgs) Handles Odswiez.Click

        If IsDBNull(DlugoscCyklu.Text) OrElse Not (IsNumeric(DlugoscCyklu.Text)) Or Not Integer.TryParse(DlugoscCyklu.Text, LiczbaFaz) Then
            MsgBox("Możesz wpisać tylko liczba całkowite")
            LiczbaFaz = 4
            DlugoscCyklu.Text = LiczbaFaz
        ElseIf DlugoscCyklu.Text <= 0 Or DlugoscCyklu.Text > dane.Count / 2 Then
            MsgBox("Liczba faz nie może być taka duża/mała.")
            LiczbaFaz = 4
            DlugoscCyklu.Text = LiczbaFaz
        End If

        wartoscAlfa = alfa.Text
        wartoscBeta = Beta.Text
        wartoscGamma = Gamma.Text
        LiczbaFaz = DlugoscCyklu.Text
        dgv_dane.Rows.Clear()
        Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
        tworz_wykres()
    End Sub

Teraz dodamy sobie funkcjonalność klawiszy góra, dół  które będą nam w zależności od textboxa w którym się znajdujemy zmieniać wartości alfa, beta, gamma o +0,01 albo -0,01.:

    Private Sub alfa_KeyDown(sender As Object, e As KeyEventArgs) Handles alfa.KeyDown
        Select Case e.KeyCode
            Case Keys.Up
                wartoscAlfa += 0.01
                alfa.Text = wartoscAlfa
                dgv_dane.Rows.Clear()
                Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
                tworz_wykres()
            Case Keys.Down
                wartoscAlfa -= 0.01
                alfa.Text = wartoscAlfa
                dgv_dane.Rows.Clear()
                Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
                tworz_wykres()
        End Select
    End Sub

    Private Sub beta_KeyDown(sender As Object, e As KeyEventArgs) Handles Beta.KeyDown
        Select Case e.KeyCode
            Case Keys.Up
                wartoscBeta += 0.01
                Beta.Text = wartoscBeta
                dgv_dane.Rows.Clear()
                Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
                tworz_wykres()
            Case Keys.Down
                wartoscBeta -= 0.01
                Beta.Text = wartoscBeta
                dgv_dane.Rows.Clear()
                Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
                tworz_wykres()
        End Select
    End Sub

    Private Sub gamma_KeyDown(sender As Object, e As KeyEventArgs) Handles gamma.KeyDown
        Select Case e.KeyCode
            Case Keys.Up
                wartoscGamma += 0.01
                Gamma.Text = wartoscGamma
                dgv_dane.Rows.Clear()
                Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
                tworz_wykres()
            Case Keys.Down
                wartoscGamma -= 0.01
                Gamma.Text = wartoscGamma
                dgv_dane.Rows.Clear()
                Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
                tworz_wykres()
        End Select
    End Sub

Następnie musimy dodać tylko obsługę RadioButtonów i wszystko będziemy mieli gotowe. Pierwszy RadioButton który przełącza na model multiplikatywny musi mieć dodaną dodatkową pętle if, ponieważ jego obsługa może być realizowana tylko wtedy gdy wykres jest już załadowany.

    Private Sub MultiplikatywnaRB_CheckedChanged(sender As Object, e As EventArgs) Handles MultiplikatywnyRB.CheckedChanged
        If kontroler = False Then
            dgv_dane.Rows.Clear()
            Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
            tworz_wykres()
        End If
    End Sub

    Private Sub AddytywnaRB_CheckedChanged(sender As Object, e As EventArgs) Handles AddytywnyRB.CheckedChanged
        dgv_dane.Rows.Clear()
        Metoda_Wintersa(wartoscAlfa, wartoscBeta, wartoscGamma, LiczbaFaz)
        tworz_wykres()
    End Sub

To na tyle. Większość informacji tak jak widać udzieliłem w samym kodzie. Filmik z programem prezentuje poniżej:

Plik z kodem:  Metoda_winters

Plik z danymi: multiplikatywny

Permalink do tego artykułu: https://visualmonsters.cba.pl/model-multiplikatywnyaddytywny-wintersa/

2 Komentarze

    • michał on 24 stycznia 2017 at 12:27
    • Odpowiedz

    Dlaczego jak np wybiorę wartość dla r=5 ft liczone jest dopiero od dla 6 t .. Z tego co pamiętam i zawsze liczyłem dla np r=5 to Ft5 jest średnią średniej Ft1-5 ? czy robiłem to w sposób nieprawidłowy

    1. Witam Pana, dziękuje za komentarz. Projekt umieszczony na stronie jest dosyć stary, dlatego może zawierać jakieś błędy. Nie do końca rozumiem w czym jest problem, ale jeśli jest Pan zainteresowany tylko programem do obliczania tej metody, to zapraszam na stronę:
      https://visualmonsters.cba.pl/index.php/model-multiplikatywnyaddytywny-wintersa2/
      W której dostępny jest program działający poprawnie. Jeśli dobrze zrozumiałem w czym jest problem, to jeśli model zaczynał by się tak jak Pan napisał wtedy nie został by wygenerowany pierwszy element Ct i nie dało by się wtedy obliczyć:
      Ft = α *(yt-Ct-r)+(1-α)(Ft-1+St-1) // ponieważ dla C(1-1) element nie istnieje. Również dalsze elementy Ct były by niemożliwe do obliczenia, ponieważ nie istniałby by element C(1-1).
      Z tego co zauważyłem to program opisany na stronie liczy źle ponieważ dla r=1 występuje błąd. Jednakże wszystko opisane jest w programie i łatwo można zmienić tą opcję.
      Sprawdzę i poprawię wpis, dziękuje za czujność i komentarz.

Dodaj komentarz

Twój adres email nie będzie publikowany.