马尔科夫链马尔可夫过程.docx
- 文档编号:27633112
- 上传时间:2023-07-03
- 格式:DOCX
- 页数:18
- 大小:24.25KB
马尔科夫链马尔可夫过程.docx
《马尔科夫链马尔可夫过程.docx》由会员分享,可在线阅读,更多相关《马尔科夫链马尔可夫过程.docx(18页珍藏版)》请在冰豆网上搜索。
马尔科夫链马尔可夫过程
马尔科夫链_马尔可夫过程
一、引言
1、马尔科夫链的数学背景马尔可夫链,因安德烈?
马尔可夫(A.A.Markov,1856-1922)得名,是数学中具有马尔可夫性质的离散时间随机过程。
该过程中,在给定当前知识或信息的情况下,过去(即当期以前的历史状态)对于预测将来(即当期以后的未来状态)是无关的。
马尔可夫链是随机变量X_1,X_2,X_3...的一个数列。
这些变量的范围,即他们所有可能取值的集合,被称为“状态空间”,而X_n的值则是在时间n的状态。
如果X_{n+1}对于过去状态的条件概率分布仅是X_n的一个函数,则
PX_{n+1}=x|X_0,X_1,X_2,\ldots,X_n=PX_{n+1}=x|X_n.这里x为过程中的某个状态。
上面这个恒等式可以被看作是马尔可夫性质。
2、马尔科夫链的典型应用
①马尔科夫链在股指期货投资中的应用
马尔科夫链转移矩阵的有效状态以近时点动量策略原时点反转策略为主,有效抓住了上涨和下跌的中期和初期.从而准确的抓住了日内股指波动.②马尔科夫链在天气预报中的应用
通过对马尔科夫链理论和切普曼-柯尔莫哥洛夫方程方程的探讨,,结合天气情况不确定等诸多特点,构想了天气情况预报的马尔科夫链预测模型,给出了马尔科夫链的初始概率和多重转移概率的计算方法,根据此算法可以预报短期天气情况,同时扩展到对未来天气情况趋势的预测。
③马尔科夫链在环境预测中的应用
鉴于目前环境质量预测在理论方法和实践上的缺乏,把马尔科夫链引入环境质量的预测中,将各种污染物的浓度变化过程视作马尔科夫过程,通过预测各种污染物的污染负荷系数来推知其浓度值/
④马尔科夫链在桥梁状态预测中的研究与应用
马尔科夫链以矩阵的形式来表达桥梁状况,通过求解状态转移矩阵,进一步预测桥梁未来数年内的基本状况。
综合考虑了桥梁检修的影响,给出了桥梁检修后不同状态的状态转移矩阵,为进一步引入实际数据做了充分的准备。
3、相关文献
《程序设计实践》作者BrianW.Kernighan
程序设计实践并不是只是写代码。
程序员必须评价各种折中方案,在许多可能性之中做出选择,排除错误,做测试和改进程序性能,还要维护自己和其他人写的软件。
在满足规范的同时还必须关注许多问题,包括兼容性,坚固性和可靠性等等。
该书从排错,测试,性能,可移植性,设计,界面,风格和记法等方面,讨论了程序设计中的实际的同时又是非常深刻和具有广泛意义的思想,技术和方法。
本书值得每个梦想并努力成为优秀程序员的人参考,值得每个计算机专业的学生和IT从业者阅读,也可作为程序设计高级课程的教材或参考书。
其他书籍:
MatthewAustern的《类属程序设计与STL》GenericProgrammingandtheSTL,Addison-Wesley,1998
对C++语言本身的参考文献当
然是BjarneStroustrup的《C++程序设计语言》C++ProgrammingLanguage第3版,Addison-Wesley,1997,LarryWall、TomChristiansen和RandalSchwartz的《Perl程序设计》ProgrammingPerl第2版,O’Reilly,1996等等。
4、国内外现状
自我国数学家教育家中科院王梓坤院士在上世纪中期将马尔科夫链引进入我国后,取得了很大的成就,尤其是在天气短期预测方面。
二、哈希表介绍
一般的线性表、树中,记录在结构中的相对位置是随机的即和记录的关键字之间不存在确定的关系,在结构中查找记录时需进行一系列和关键字的比较。
这一类查找方法建立在“比较”的基础上,查找的效率与比较次数密切相关。
理想的情况是能直接找到需要的记录,因此必须在记录的存储位置和它的关键字之间建立一确定的对应关系f,使每个关键字和结构中一个唯一的存储位置相对应。
因而查找时,只需根据这个对应关系f找到给定值K的像fK。
若结构中存在关键字和K相等的记录,则必定在fK的存储位置上,由此不需要进行比较便可直接取得所查记录。
在此,称这个对应关系f为哈希函数,按这个思想建立的表为哈希表(又称为杂凑法或散列表)。
三﹑编写的C程序
⒈总体思路
解决马尔科夫链的思维
,马尔科夫链是根据不同的前缀,随机选择后缀,从而生成句子,我们可以单独储存文章中的每个词,每个词后跟一个链表,当查询到这个词的时候,也能查询到与它关联的链表,从而从与它相关的链表中随机选取一个词输出,我们可以做一种哈希表,让前缀做关键字,它的值是与前缀相关联的所有词的集合。
定义一个数据结构,由一个前缀和一个后缀链表组成。
所有这些信息存在一个散列表里,前缀是关键码。
每个前缀由两个组成。
如果一个后缀在给定前缀下的出现
多于一次,则每个出现都单独包含在有关链表里。
⒉程序分析:
⑴程序开始,用的是宏定义和枚举类型,用typedef声明新类型State和Suffix,把每个词储存成独立的字符串。
⑵hash函数对数组里所有字符串的拼接做散列,lookup向sp->pref[]里存入一个指针。
利用sprintf动态地建立格式串用来维护缓冲区导出的两个常数之间的关系。
⑶函数build有两个参数,一个是prefix数组,用来保存前面的所有的输入词;一个是个FILE指针。
函数把prefix和读入词的一个拷贝送给add,该函数在散列表里加入一个新项,并更新前缀数组:
对memmove的调用是在数组里做删除。
这个操作把前缀数组里从1到NPREF-1的元素向下搬,移到从0到NPREF-
2的位置。
这也就删去了第一个前缀词,并为新来的一个在后面腾出了位置。
函数addsuffix把一个新后缀加进去,add完成给有关前缀加入一个后缀的一般性工作,addsuffix做的是把一个词具体地加进后缀链表里。
函数add由build调用,而addsuffix只在add内部使用这就完成了输入。
⑷对于输出,如果输出非常长,我们可以在产生了一定数目的词之后终止程序;另一种情况是程序遇
到了后缀NONWORD。
最终看哪个情况先出现。
函数generate产生每行一个词的输出,用文字处理程序可以把它们汇成长的行。
⑸把所有东西放到一起,装进一个main函数里,它从标准输入流读入,生成至多有指定个数的词序列。
⑹程序结束。
⒊其他应用的知识:
下程序还用到了链表,结构体以及处理动态链表的函数,特作说明。
malloc函数
其作用是在内存的动态存储区中分配一个长度size的连续空间。
此函数的值(“即返回值”)是一个指向分配域其实地址的指针类型为void。
如果此函数未能成功地执行,则返回空指针。
结构体:
C语言允许用户自己指定这样一种结构,它相当于高级语言中的“记录”,struct用来声明结构体类型时所必须用到的关键字,它向编译系统声明这是一个“结构体类型”。
⒋程序源代码
#include个
#include
#include
#include
#include
enum
{
NPREF=2,/*前缀中词的个数*/
NHASH=4093,/*散列表数组的大小*/
MAXGEN=10000,/*生成词数的上届*/
MULTIPLIER=31
};
charNONWORD[]=
typedefstructStateState;/*定义新类型State*/
typedefstructSuffixSuffix;/*定义新类型Suffix*/
structState{/*前缀和后缀表*/
char*pref[NPREF];/*前缀单词*/
Suffix*suf;/*后缀表*/
State*next;
};
structSuffix{/*后缀表*/
char*word;/*后缀单词*/
Suffix*next;
};
State*statetab[NHASH];
unsignedinthashchar*s[NPREF]/*hash函数对数组里所有字符串的拼接做散列*/
{
unsignedinth;
unsignedchar*p;
inti;
h=0;
fori=0;i
{
forp=unsignedchar*s[i];*p!
="\0";p++{
h=MULTIPLIER*h+*p;
}
}
returnh%NHASH;
}
State*lookupchar*prefix[NPREF],intcreate/*lookup函数向sp->pref[]里存入一个指针。
*/
{
inti,h;
State*sp;
h=hashprefix;
forsp=statetab[h];sp!
=NULL;sp=sp->next
{
fori=0;i
{
ifstrcmpprefix[i],sp->pref[i]!
=0
{
peak;
}
}
ifNPREF==i
{
returnsp;
}
}
ifcreate
{
sp=State*mallocsizeofState;
ifNULL==sp
{
perror
return0;
}
fori=0;i
{
sp->pref[i]=prefix[i];
}
sp->suf=NULL;
sp->next=statetab[h];
statetab[h]=sp;
}
returnsp;
}
voidaddsuffixState*sp,char*suffix/*函数addsuffix把一个新后缀加进去*/
{
Suffix*suf;
suf=Suffix*mallocsizeofSuffix;
suf->word=suffix;
suf->next=sp->suf;
sp->suf=suf;
}
/*add:
增添后缀单词,更新前缀*/
voidaddchar*prefix[NPREF],char*suffix
{
State*sp;
sp=lookupprefix,1;
ifNULL==sp
{
return;
}
addsuffixsp,suffix;
memmoveprefix,prefix+1,NPREF-1*sizeofprefix[0];
prefix[NPREF-1]=suffix;
}
/*build:
读取输入,建立后缀表*/
voidbuildchar*prefix[NPREF],FILE*fp
{
charbuf[100],fmt[10];
sprintffmt,
whilefscanffp,fmt,buf!
=EOF
{
addprefix,strdupbuf;
}
}
/*generate:
汇成行输出*/
voidgenerateintnwords
{
State*sp;
Suffix*suf;
char*prefix[NPREF],*w;
inti,nmatch;
srandtimeNULL;
fori=0;i
{
prefix[i]=NONWORD;
}
fori=0;i
{
sp=lookupprefix,0;
nmatch=0;
forsuf=sp->suf;suf!
=NULL;suf=suf->next{
ifrand%++nmatch==0
w=suf->word;
}
ifstrcmpw,NONWORD==0
peak;
printf
memmoveprefix,prefix+1,NPREF-1*sizeofprefix[0];prefix[NPREF-1]=w;
}
}
intmainintargc,char*argv[]
{
inti,nwords=MAXGEN;
char*prefix[NPREF];
fori=0;i
{
prefix[i]=NONWORD;
}
buildprefix,stdin;
addprefix,NONWORD;
generatenwords;
return0;
}
四﹑调试出现的问题
(1)在不该加分号的地方加了分号
fori=0;i
{
forp=unsignedchar*s[i];*p!
="\0";p++{
h=MULTIPLIER*h+*p;
}
}
由于在第一个for语句后加了分号,使循环体变成了空语句,运行没有成功,执行的是当i=2时的值,而不是i=0,1,2时的值。
(2)括号不配对。
再编写多重循环时,最后落下了一个大括号,一定要注
意括号的配对问题。
(3)引用数组元素时误用了圆括号。
prefix[i]=NONWORD时本来应该引
用方括号,结果引用了圆括号,导致编译错误。
(4)unsignedinth;
unsignedchar*p;
inti;
一开始对h定义的是带符号的整型数,不满足条件,改为不带符号数。
五﹑测试马尔科夫程序(参考《程序设计实践第六章的关于马尔科夫程序的测试》)
第一个测试集由几个很小的文件组成,用于测试边界条件,目标是保证程序对只包含几个词的输入能正确产生输出。
对于前缀长度为2的情况,我们用了五个文件,它们分别包含第一个测试集由几个很小的文件组成,用于测试边界条件,目标是保证程序对只包含几个词的输入能正确产生输出。
对于前缀长度为2的情况,我们用了五个文件,它们分别包含一行是一个文件:
(空文件)
a
ab
abc
abcd
对于这里的每个文件,程序的输出都应该与输入完全相同。
这些测试揭示出几个在表的初始化、生成程序的开始、结束等地方的“超出一个”错误。
第二项测试检验某些必须保持的特征。
对于两词前缀的情况,一次运行中输出的每个词,每个词对、以及每个三词序列都必然也出现在输入里。
我们写了一个Aw
k程序,用它把原始输入读进一个巨大的数组,构造出所有两个词和三个词的序列的数组,再把马尔可夫程序的输出读入另一个数组,然后对它们做比较。
第三步测试是统计性的,输入由下面的序列构成:
abcabc?
abd?
这里每十个abc有一个abd。
如果随机选择部分工作得很好,那么在输出中c的数目大约应该是d的十倍。
我们用freq检验这个性质.
六、C的测试结果
编译成功后,
输入原始文本:
Showmeyourflowcharsandconcealyourtables,andIshallcontinuetobemystified.Showmeyourtables,andIwon’tusuallyneedyourflowcharts;they’llbeobvious.
编译后输出文本:
Showmeyourtables,andIshallcontinuetobemystified.Showmeyourtables,andIshallcontinuetobe
mystified.Showmeyourflowcharsandconcealyourtables,andIwon"tusuallyneedyourflowcharts;they"llbeobvious.
七﹑编写的C++程序
⒈C++、STL简介
C++是一种使用非常广泛的计算机编程语言。
它是一种静态数据类型检查的,支持多重编程范式的通用程序设计语言。
它支持过程化程序设计、数据抽象、面向对象程序设计、制作图标等等泛型程序设计等多种程序设计风格。
STLSTL=StandardTemplateLipary,标准模板库.在C++标准中,STL
被组织为下面的13个头文件:
、、、、、、、、、、、和。
STL容器允许我们重复利用已有的实现构造自己的特定类型下的数据结构,通过设置一些模版类,STL容器对最常用的数据结构提供了支持,这些模板的参数允许我们指定容器中元素的数据类型,可以将我们许多重复而乏味的工作简化。
容器部分主要由头文件
,,,,和组成。
对于常用的一些容器和容器适配器(可以看作由其它容器实现的容器),可以通过下表总结一下它们和相应头文件的对应关系。
数据结构描述实现头文件
向量vector连续存储的元素
列表list由节点组成的双向链表,每个结点包含着一个元素
双队列deque连续存储的指向不同元素的指针所组成的数组
集合set由节点组成的红黑树,每个节点都包含着一个元素,节点之间以某种作用于元素对的谓词排列,没有两个不同的元素能够拥有相同的次序
多重集合multiset允许存在两个次序相等的元素的集合栈stack后进先出的值的排列
队列queue先进先出的值的排列
优先队列priority_queue元素的次序是由作用于所存储的值对上的某种谓词决定的的一种队列
映射map由{键,值}对组成的集合,以某种作用于键对上的谓词排列
多重映射multimap允许键对有相等的次序的映射
⒊deque容器,map容器的简介
deque是个动态数组,随机存取任何元素都能在常数时间完成但次vector,有在两端增删元素具有较佳的性能,和vector的区别多push_front
pop_front,少了capacityreserve。
实现时,deque是动态的以分段
连续空间组合而成,随时可以增加一段新的空间并连接起来,从而导致reserve没有意义。
STL还提供了一个map容器,其内部实现基于平衡的树。
在map中可以存储关键码—值对。
map的实现方式保证,从任何关键码出发提取相关值的操作都是Ologn。
虽然map可能不如O1的散列表效率高,但是,直接使用它就可以不必写任何代码。
⒋程序分析
STL提供了deque的模板,记法deque将它指定为以字符串为元素的deque。
由于这个类型将在程序里多次出现,在这里用一个typedef声明,将它另外命名为Prefix。
声明了一个map类型的变量statetab,它是从前缀到后缀向量的映射。
add函数添加单词到后缀序列,更新前缀。
函数build使用iostre
am库,一次读入一个词。
函数generate的作用是成行输出。
把所有东西放到一起,装进一个main函数里,它从标准输入流读入,生成至多有指定个数的词序列。
程序结束。
⒌C++源程序
//Function:
包含头文件和函数声明
#include//deque
#include//map>#include//vector
#include
#include
#include//rand
#include//timeNULL
#include//fin
usingnamespacestd;
constintNPREF=2;//前缀数
conststringNONWORD=
constintMAXGEN=10000;//最大输出单词数
typedefdequePrefix;
map>statetab;/
voidaddPrefix&prefix,conststring&s//添加单词到后缀序列,更新前缀
{
ifprefix.size==NPREF
{
statetab[prefix].push_backs;
prefix.pop_front;
}
prefix.push_backs;
}
voidbuildPrefix&prefix,istream&in
{
stringbuf;
whilein>>buf
{
addprefix,buf;
}
}
voidgenerateintnwords
{
srandunsignedtimeNULL;
Prefixprefix;
forinti=0;i
{
addprefix,NONWORD;//读取单词//成行输出
}
fori=0;i&suf=statetab[prefix];conststring&w=suf[rand%suf.size];ifw==NONWORD{}peak;}cout
intmain//main函数,从标准输入流读入,生成至多有指定个数的词序列。
{
forinti=0;i
}}buildprefix,fin;addprefix,NONWORD;generatenwords;fin.close;statetab.clear;return0;
八﹑调试C++出现的问题
⑴在需要加头文件时没有用#include命令去包含文件。
一开始把#include这个引用给落下了。
⑵在需要加分号的地方没加分号。
constintMAXGEN=10000;是句完整语句,语句后面应该加分号。
⑶编译系统将大写字母和小写字母认为是两个不同的字符。
因此,i和I是两个文件名,注意区分。
⑷类的声明应当只包含函数的声明,永远不要进行函数定义实现。
因为C++不熟悉,我在前面类声明的时候顺便定义了函数,后来编译出现问题。
改在后面定义函数。
九﹑C++测试结果
编译成功后,
输入原始文本:
Showmeyourflowcharsandconcealyourtables,andIshallcontinuetobemystified.Showmeyourtables,andIwon’tusuallyneedyourflowcharts;they’llbeobvious.
编译后输出文本:
Showmeyourtables,andIwon"tusuallyneedyourflowcharts;they"llbeobvious.
十﹑两种语言对比
①编程思想C++与C语言最大的区别在于编程思想的截然不同,前者是面向对象(OOP)
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 马尔科夫链马尔可夫 过程
![提示](https://static.bdocx.com/images/bang_tan.gif)