论马尔可夫链的稳定状态与MFC结合在天气预测中的应用

来源:互联网 发布:tk的域名 编辑:程序博客网 时间:2024/05/21 04:18

摘要:在《线性代数》课程中学习了“天气马尔可夫链的稳定状态”。马尔可夫模型(HiddenMarkovModel,HMM)是统计模型,它用来描述一个含有隐含未知参数的马尔可夫过程。其难点是从可观察的参数中确定该过程的隐含参数。然后利用这些参数来做进一步的分析,例如模式识别。在正常的马尔可夫模型中,状态对于观察者来说是直接可见的。这样状态的转换概率便是全部的参数。而在隐马尔可夫模型中,状态并不是直接可见的,但对于受到状态影响的某些变量则是可见的。每一个状态在可能输出的符号上都有一概率分布。因此输出符号的序列能够透露出状态序列的一些信息。在这里,我运用计算机科学与技术专业中所用的微软基础类库(英语:Microsoft Foundation Classes,简称MFC),并使用C++语言知识进行编程,深入探究马尔可夫链的稳定状态与MFC结合在天气预测中的应用。

 

关键字:马尔可夫链;转移概率矩阵;MFCC++;天气预测。

 

引言:马尔可夫链模型(Markov Chain Model)是一种常用的概率模型也叫马尔可夫分析(Markov Chain Analysis),其原理为利用概率转移矩阵所进行的模拟分析。此模型为一动态模型,参数可随时间而变,故可以用来预测未来事物变化状态的趋势。

 

 

应用案例介绍


该应用案例中,使用ω0三维列向量来存今日晴、阴、雨的概率,

                      ╭0.75, 0.5, 0.25,  ╮

转移矩阵A =│ 0.125, 0.25, 0.5,  │

                    ╰ 0.125, 0.25, 0.25 ╯

运用公式:ωk = Ak*ω0,k=1,2,3…

即可依次得到第k天的晴、阴、雨天气状态概率,最终得到天气马尔可夫链的稳定状态时的天气状态概率。

在使用MFC编程前,我预先用C语言进行了一个小实验。先用VisualC++6.0新建Win32 Console Aplication的工程编程,定义三维数组w[k][i][j](k=11,i=3,j=1),编写马尔可夫链中矩阵运算,其中“k”表示包括 “今天”在内的从今天起第k天的状态,“i”和“j”表示i行j列的矩阵,定义m_dSunny,m_dCloudy,m_dRainy三个double型变量分别存“晴”、“阴”、“雨”三种天气状态的概率,假设今日天气的三种概率分别为:晴20%,阴30%,雨50%。则先由以下代码简单计算一下未来10天(包括今天)的天气状态概率。

#include<stdio.h> int main(){  int i, j, k;  double w[11][3][1] = {0.0};  double A[3][3] = {0.75, 0.5, 0.25,                    0.125, 0.25, 0.5,                    0.125, 0.25, 0.25};  //初始化今日天气:晴20%,阴30%,雨50%。  double m_dSunny = 20, m_dCloudy = 30, m_dRainy= 50;  w[0][0][0] =100*m_dSunny/(m_dSunny+m_dCloudy+m_dRainy);  w[0][1][0] =100*m_dCloudy/(m_dSunny+m_dCloudy+m_dRainy);  w[0][2][0] =100*m_dRainy/(m_dSunny+m_dCloudy+m_dRainy);   for(k = 0; k < 10; k ++)  //10天  {      for(i = 0; i < 3; i ++) //行      {          for(j = 0; j < 3; j++)  //列          {              w[k+1][i][0] += A[i][j] *w[k][j][0];          }      }  }  for(k = 0; k <= 10; k ++)  //10天  {      for(i = 0; i < 3; i ++) //行      {          printf("%d\t", (int)w[k][i][0]);      }      printf("\n\n");  }  return 0;}

控制台窗口打印结果如下:


即包括 “今天”在内的从今天起第k天的状态概率:


这里用的是C语言编写Win32 Console Aplication控制台程序进行的预先实验,可以看到天气状态概率随天数增加逐步趋近于一组常数:晴60%,阴21%,雨17%。即马尔可夫链的稳定状态。

接下来用MFC写对话框程序,部分关键代码如下:

 

voidCMyDlg::OnButtonSubmit(){    // TODO: Add your control notificationhandler code here/***************天气马尔可夫链运算*******************///X轴刻度值 0(20, 360)->10(320,360)  Y轴刻度值 0(20,360)->10(20, 60)  单位长度30    UpdateData(TRUE);    int i, j, k;    double w[11][3][1] = {0.0}, m;    double A[3][3] = {0.75, 0.5, 0.25,                      0.125, 0.25, 0.5,                      0.125, 0.25, 0.25};     m = m_dSunny+m_dCloudy+m_dRainy;    w[0][0][0] = 100*m_dSunny/m;    w[0][1][0] = 100*m_dCloudy/m;    w[0][2][0] = 100*m_dRainy/m;     for(k = 0; k < 10; k ++)  //10天    {        for(i = 0; i < 3; i ++) //行        {            for(j = 0; j < 3; j++)  //列            {                w[k+1][i][0] += A[i][j] *w[k][j][0];            }        }    }/*************天气马尔可夫链曲线绘制********************/    //Sunny        //强制更新绘图, 不可少, 否则绘图会出错            //使static控件区域无效    pWnd->Invalidate();            //更新窗口    pWnd->UpdateWindow();    CDC *pDC = pWnd->GetDC();                   //获取控件的CDC指针    CPen *pPenLine = new CPen(); //创建画笔对象    pPenLine ->CreatePen(PS_SOLID, 3,RGB(255, 255, 0)); //黄色画笔    CPen *pPen = NULL;    //选中当前黄色画笔,并保存以前的画笔    CGdiObject *pOldPen = pDC->SelectObject(pPenLine);    //画线    pDC ->MoveTo(20, 360 - 3 * w[0][0][0]);    for(i = 1; i <=10; i++)    {        pDC ->LineTo(20 + 30 * i, 360 - 3 *w[i][0][0]);    }    //恢复以前的画笔    pDC ->SelectObject(pOldPen);    delete pPenLine;    if(pPen != NULL)    delete pPen;    ReleaseDC(pDC);     //Cloudy    pWnd->Invalidate();    //更新窗口    pWnd->UpdateWindow();    CDC *pDC2 = pWnd->GetDC();                   //获取控件的CDC指针    CPen *pPenLine2 = new CPen(); //创建画笔对象    pPenLine2 ->CreatePen(PS_SOLID, 3,RGB(153, 217, 234)); //蓝色画笔    CPen *pPen2 = NULL;        //选中当前蓝色画笔,并保存以前的画笔    CGdiObject *pOldPen2 = pDC->SelectObject(pPenLine2);    //画线    pDC ->MoveTo(20, 360 - 3 * w[0][1][0]);    for(i = 1; i <=10; i++)    {        pDC ->LineTo(20 + 30 * i, 360 - 3 *w[i][1][0]);    }    //恢复以前的画笔    pDC ->SelectObject(pOldPen);    delete pPenLine2;    if(pPen2 != NULL)    delete pPen2;    ReleaseDC(pDC);     //Rainy    pWnd->Invalidate();    //更新窗口    pWnd->UpdateWindow();    CDC *pDC3 = pWnd->GetDC();                   //获取控件的CDC指针    CPen *pPenLine3 = new CPen(); //创建画笔对象    pPenLine3 ->CreatePen(PS_SOLID, 3, RGB(0,255, 128)); //绿色画笔    CPen *pPen3 = NULL;        //选中当前绿色画笔,并保存以前的画笔    CGdiObject *pOldPen3 = pDC->SelectObject(pPenLine3);    //画线    pDC ->MoveTo(20, 360 - 3 * w[0][2][0]);    for(i = 1; i <=10; i++)    {        pDC ->LineTo(20 + 30 * i, 360 - 3 *w[i][2][0]);    }    //恢复以前的画笔    pDC ->SelectObject(pOldPen);    delete pPenLine3;    if(pPen3 != NULL)    delete pPen3;    ReleaseDC(pDC);}

该函数用于当用户填写好“今日天气比例”后,点击提交按钮时,绘制天气马尔科夫链。

绘制后界面效果如下:


0 0
原创粉丝点击