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
Wariant multiplikatywny – gdy udział efektów sezonowości jest stały w wartości zmiennej
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:
Rozłożenie opisów zostawiam wam do zrobienia. Po dodaniu opisów forma powinna wyglądać tak jak na obrazku:
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”:
Stronę graficzną mamy już z głowy. Zajmijmy się stroną techniczną. Na początek importujemy wymagane elementy i inicjujemy stałe zmienne:
1 2 3 4 5 6 7 8 9 10 11 |
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
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 |
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:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
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.:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
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.
1 2 3 4 5 6 7 8 9 10 11 12 13 |
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
2 Komentarze
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
Author
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.