Chinaunix首页 | 论坛 | 博客
  • 博客访问: 20941
  • 博文数量: 4
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 65
  • 用 户 组: 普通用户
  • 注册时间: 2013-12-31 23:33
文章分类

全部博文(4)

文章存档

2014年(4)

我的朋友

分类: Python/Ruby

2014-01-02 20:18:57

    Lua程序设计第10章最后一节给出了一个利用马尔科夫链算法实现文本生成器的完整实例,第一次遇到这个算法有种不明觉厉的感觉,通过上网学习发现,这个算法不但实用并且原理很简单,当然这是排除了对算法本身数学推理方面的深究。(既然已经站在了巨人的肩膀上,那就让我多呆一会儿。)废话不多说,直接上代码。

点击(此处)折叠或打开

  1. -- read input line and split into words for return
  2. function returnWords ()
  3. local line = io.read()
  4. local pos = 1
  5. return function ()
  6. while line do
  7. local _start , _end = string.find(line , "%w+" , pos)
  8. if(_start) then
  9. pos = _end + 1
  10. return string.sub(line , _start , _end)
  11. else
  12. line = io.read()
  13. pos = 1
  14. end
  15. end
  16. return nil
  17. end
  18. end
  19. --generate a string in this style "w1 w2" (note: there is a blank between w1 and
  20. --w2)
  21. function genpairs(w1 , w2)
  22. return (w1.." "..w2)
  23. end
  24. stattable = {} --a global var which stands for the vocabulary table
  25. --insert (key ,values) in stattable
  26. function insert(index , value)
  27. if not stattable[index] then
  28. stattable[index] = {value}
  29. else
  30. table.insert(stattable[index] , value)
  31. end
  32. end
  33. --build stattable
  34. function init()
  35. local placeholers1 = "#"
  36. local placeholers2 = "#"
  37. for value in returnWords() do
  38. key = genpairs(placeholers1 , placeholers2)
  39. insert(key , value)
  40. placeholers1 = placeholers2
  41. placeholers2 = value
  42. end
  43. insert(genpairs(placeholers1 , placeholers2) , "#")
  44. end
  45. --return num of elements of a table
  46. function getn(table)
  47. local MAXNUM = 100
  48. local count = 0
  49. for num = 1 , MAXNUM do
  50. if table[num] ~= nil then
  51. count = count + 1
  52. else
  53. break;
  54. end
  55. end
  56. return count
  57. end
  58. --generate text
  59. local MAXWORDS = 100
  60. local word1 = "#"
  61. local word2 = "#"
  62. init()
  63. for i = 1 , MAXWORDS do
  64. local textunit = stattable[genpairs(word1 , word2)]
  65. local num = getn(textunit)
  66. local xx = math.random(num)
  67. local textword = textunit[xx]
  68. if "#" ~= textword then
  69. io.write(textword , " ")
  70. word1 = word2
  71. word2 = textword
  72. else
  73. io.write("\n")
  74. break
  75. end
  76. end

我会一边按照程序实际的执行流程一边讲解算法的原理,程序第102行是此脚本真正执行的开始,首先执行init函数,init函数负责生成马尔科夫链的词汇表,这个词汇表就是通常所说的前缀后缀表。马尔科夫链算法会根据指定前缀随机地选择一个后缀用于生成随机文本。这里我们的前缀长度设置为2,算法已经指出前缀的长度对于算法的执行无影响,但是文本生成的随机性和质量和后缀的数目是紧密相连的。init函数首先定义两个占位符(受Boost库的影响),当给定一段文本,第一个单词作为后缀的对应前缀是“# #”,接着程序利用Lua的泛型for返回用户输入文本的每个单词,即词汇表键值对中的值,通过genpairs函数生成词汇表的键,通过insert函数将键值对插入词汇表。insert函数很简单,函数的输入有两个,一个是键,一个是值。如果词汇表中还没有输入的键,就生成一个键值对,如果已经存在输入的键,那么将输入的值插入到该键所对应的值列表的尾端。genpairs返回形式为“w1空格w2”的键,不多介绍。init函数会以“链式”的方式进行:用前两个单词作键,读入的单词作值,完成词汇表插入后,用上次作为键的第二个单词和上次读入的单词组成新键,新读入的单词作为值进行词汇表的插入操作,如此链式般的进行下去,直到输入文本解析完毕。
    有了词汇表后,生成随机文本就一马平川了,我们按照下面的步骤生成随机文本,直到遇到自定义的结束符“#”。
   
    设置w1和w2为文本的前两个词
    Loop:
        用w1空格w2查词汇表,随机地选择一个后缀作为输出文本,记为w3
        如果w3是“#”
            退出循环        
        w1 = w2 , w2 = w3                                                                                    
    这样就完成了利用马尔科夫链算法根据输入文本,按照其统计规律生成一个可读的新文本的所有步骤。
    测试如下:

    执行程序输出的上面一行是用户输入的文本,下面一行则是程序自动生成的随机文本。                                                                                 




                   


阅读(2208) | 评论(1) | 转发(0) |
0

上一篇:没有了

下一篇:Boyer-Moore字符串匹配算法分析与实现

给主人留下些什么吧!~~

angel19915212014-01-02 20:32:42

lua顶楼主