转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46440389


近期梳理,翻出了当年高级算法课程做的题目。禁忌搜索算法解决3SAT问题。

吐槽:数学符号怎样在编辑器里打出来啊,为了保留符号,我直接截图了。

1 SAT问题描写叙述

定理4.4.1:

赋值v为使CNF可满足的充要条件是f(x1,x2,…,xm)达到最小值0。

2  禁忌搜索算法

禁忌搜索算法是在局部搜索的过程中引进了贪心选择机制。并利用禁忌表改动邻域,通过构造的候选邻域来控制解得选择和接受过程。

在搜索的过程中,禁忌搜索算法从上一步计算解的候选邻域里选择一个最好的解,即使这个解比上一步得到的解还差,也接受它,同一时候改动禁忌表,以避免该解在禁忌期限内再次被选择。

思路分析例如以下:

1 初始赋值

随机初始化变元值

2 候选邻域的构造:

对于当前的赋值X,从每个非零子句中选出一个变元,全部选出的变元构成一个子变元集SVS。从SVS里选择一个变元,改变它的值,其它的变元值保持不变,得到的解为X的一个邻解。

全部邻解的集合,就构成了候选邻域。降低搜索空间。提高了搜索效率。

3 禁忌表:

禁忌表记录着在近期L次迭代内扰动过得变元,这些变元在当前迭代范围内禁忌扰动。

禁忌表用数组iteration_age[i],i=1,2,…m来表示。iteration_age[i]的值为变元xi被扰动时的迭代序数

变元xi是不是被禁忌:

iteration_age[i]+L>=iteration

禁忌搜索算法解决3SAT问题的伪代码:

  1. 算法伪代码:
  2. initcnf();initialiteration_age[] //初始化CNF,禁忌表
  3. iteration = 1;flips = 1 //迭代次数和扰动次数初始化
  4. while(v_cnf(variable)!=0&&iteration< itera_max) //停止准则
  5. SVS[] //从每个非零子句中选出一个变元
  6. flag = 1;i = 0
  7. while(i<|SVS|&&flag==1)do
  8. for j i+1 to |SVS| do
  9. if((candidate(j)-v_cnf(variable))<(candidate(s)-v_cnf(variable))) //从SVS选择f'最小的变元 选择策略
  10. then swap SVS[i] andSVS[j]
  11. if(iteration_age[SVS[i]]+L>=iteration) //假设变元禁忌 if(candidate(i)-v_cnf(variable)<0) //吸引准则
  12. candidate(i) isflipped //接受该变元的扰动
  13. modify iteration_age[] //改动禁忌表
  14. flag=0 flips++
  15. else
  16. i++
  17. else
  18. candidate(i) isflipped //接受该变元的扰动
  19. modify iteration_age[] //改动禁忌表
  20. flag=0 flips++
  21. iteration++;

C++实现代码:

  1. // TS3SAT.cpp : 定义控制台应用程序的入口点。
  2.  
  3. //
  4. /*********************************
  5. -----------------------------------
  6. 禁忌搜索算法解决3SAT问题(C++代码实现)
  7. -----------------------------------
  8. Author:牧之丶 Date:2014年
  9. Email:bzhou84@163.com
  10. **********************************/
  11. #include "stdafx.h"
  12. #include "stdafx.h"
  13. #include <string>
  14. #include <time.h>
  15. #include <fstream>
  16. #include <iostream>
  17. #include <iterator>
  18. using namespace std;
  19.  
  20. const int n=129; //子句个数
  21. const int l=3;
  22. const int m=30; //变元个数
  23. const int L=20; //禁忌表长度
  24. const int N=1000;
  25. int clause[n+5][l+5]; //下标数组
  26. int sign[l*n+1]; //CNF变元符号
  27. int variable[m+1]; //变元数组
  28. //int neighbour[n]; //邻域
  29. int SVS[N]; //子变元集
  30. int vclause[n+5]; //子句的值
  31. int itera_max = 500000;
  32. int iteration_age[m]; //禁忌表
  33. int t;
  34. //int v; //f(x)目标函数
  35.  
  36. void initcnf() //CNF初始赋值
  37. {
  38. printf("\n");
  39. ifstream in("1.txt");
  40. for(int i =0;i<n+5;i++)
  41. {
  42. for(int j=0;j<=3;j++)
  43. {
  44. clause[i][j]=1;
  45. }
  46. }
  47. for (int i = 1; i <= n; i++)
  48. {
  49. in >> clause[i][1] >> clause[i][2] >> clause[i][3] >> t;
  50. }
  51. //下标变元随机赋值
  52. /*for(int i=0;i<n;i++)
  53. {
  54. for(int j=0;j<l;j++)
  55. {
  56. clause[i][j]=rand()%m+1; //1到m
  57. }
  58. }*/
  59. //各变元符号 0为反 1为正
  60. for(int i=1; i<=n; i++)
  61. for(int j=1; j <= l; j++)
  62. {
  63. //sign[i] == clause[i][j]/abs(clause[i][j]);
  64. if(clause[i][j]/abs(clause[i][j]) == 1)
  65. sign[i]=1;
  66. else
  67. sign[i]=0;
  68. }
  69.  
  70. for(int i=1;i<=m;i++)
  71. {
  72. iteration_age[i]=0;
  73. }
  74. for(int i=0;i<=N;i++)
  75. {
  76. SVS[i]=0;
  77. }
  78. }
  79.  
  80. int v_cnf(int var[]) //f(x)的值
  81. {
  82. int v=0;
  83. for(int i=1;i<=n;i++)
  84. {
  85. vclause[i]=1;
  86. }
  87. for(int i=1;i<=n;i++)
  88. {
  89. for(int j=1;j<=l;j++)
  90. {
  91. vclause[i] *= (sign[3*(i-1)+j]^var[abs(clause[i][j])]); //各个子句的值
  92. }
  93. v+=vclause[i];
  94. }
  95. return v;
  96. }
  97.  
  98. int candidate(int a) //邻解
  99. { int var1[m+1];
  100. //memcpy(var1,variable,m+1);
  101. for (int t = 0; t < m+1; t++)
  102. var1[t] = variable[t];
  103. int v=0;
  104. //v=v_cnf();
  105. var1[SVS[a]]=1-var1[SVS[a]];
  106. v=v_cnf(var1);
  107. return v;
  108. }
  109. void tssat() //禁忌搜索
  110. {
  111.  
  112. srand(double(time(NULL)));
  113. for(int i=1;i<=m;i++) //变元赋值
  114. {
  115. variable[i]=rand()%2; //0到1
  116. }
  117. printf("变元初始赋值为:");
  118. for(int i=1;i<=m;i++)
  119. {
  120. printf("%d ",variable[i]);
  121. }
  122. initcnf();
  123. int iteration=1;
  124. int flips=1;
  125. int c=v_cnf(variable);
  126. printf("初始f(X)=%d ",c);
  127. printf("\n");
  128.  
  129. while(v_cnf(variable)!=0&&iteration < itera_max)
  130. { int a=0;
  131. for(int i=0;i<n;i++) //从每个非零子句中选出一个变元
  132. {
  133. if(vclause[i]==1)
  134. { int svs=abs(clause[i][rand()%l]);
  135. SVS[a]=svs; //选出变元的下标
  136. int pos = 1;
  137. for(int i=0;i<a;i++)
  138. {
  139. if(SVS[a]==SVS[i])
  140. {
  141. pos = 0;
  142. break;
  143. }
  144. }
  145. if (pos == 1)
  146. {
  147. a++;
  148. }
  149. }
  150.  
  151. int flag=1;
  152. int s=0;
  153. while(s<a&&flag==1)
  154. {
  155. for(int j=s+1;j<a;j++)
  156. {
  157. if((candidate(j)-v_cnf(variable))<(candidate(s)-v_cnf(variable))) //选择f'最小的变元
  158. {
  159. /*int temp=candidate(i);
  160. candidate(i)=candidate(j);
  161. candidate(j)=temp;*/
  162. int temp=SVS[s];
  163. SVS[s]=SVS[j];
  164. SVS[j]=temp;
  165. }
  166. }
  167. if(iteration_age[SVS[s]]+L>=iteration) //变元是否禁忌
  168. {
  169. if(candidate(s)-v_cnf(variable)<0) //吸引准则
  170. {
  171. variable[SVS[s]]=1-variable[SVS[s]];
  172. iteration_age[SVS[s]]=iteration;
  173. flag=0;
  174. flips++;
  175. }
  176. else
  177. {
  178.  
  179. //flag=0;
  180. s++;
  181. }
  182. }
  183. else
  184. {
  185. variable[SVS[s]]=1-variable[SVS[s]];
  186. iteration_age[SVS[s]]=iteration;
  187. flips++;
  188. flag=0;
  189. }
  190. }
  191. iteration++;
  192. }
  193. printf("扰动次数为:%d ",flips);
  194. printf("\n");
  195. printf("变元终于取值为:");
  196. for(int i=0;i<m;i++)
  197. {
  198. printf("%d ",variable[i]);
  199. }
  200. printf("\n");
  201. int v=v_cnf(variable);
  202. printf("终于f(X)=%d\n ",v);
  203. }
  204. }
  205.  
  206. int _tmain(int argc, _TCHAR* argv[])
  207. { time_t start,end;
  208. start = clock();
  209. tssat();
  210. end = clock();
  211.  
  212. printf("\n");
  213. printf("执行时间为:%f\n",double(end - start)/(CLOCKS_PER_SEC));
  214. system("pause");
  215. return 0;
  216. return 0;
  217. }

測试全部给出的例子,执行20次可得结果例如以下:

CNF(l=3)

平均时间

成功/失败次数

N        m

TS

TS

30       129

0.8200

20/0

40       172

0.9500

20/0

50       215

0.1500

20/0

100      430

0.2600

20/0

測试用例(1.txt):http://download.csdn.net/detail/zhoubin1992/8794893

參考文献

[1]  张德富.算法设计与分析(高级教程)[M].国防工业出版社。2007.

【高级算法】禁忌搜索算法解决3SAT问题(C++实现)的更多相关文章

  1. 【高级算法】遗传算法解决3SAT问题(C++实现)

    转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46910079 1 SAT问题描写叙述 命题逻辑中合取范式 (CNF) 的可满足性问 ...

  2. 原创:TSP问题解决方案-----禁忌搜索算法C实现

    本文着重于算法的实现,对于理论部分可自行查看有关资料可以简略参考该博文:http://blog.csdn.net/u013007900/article/details/50379135 本文代码部分基 ...

  3. 【高级算法】模拟退火算法解决3SAT问题(C++实现)

    转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46453761 ---------------------------------- ...

  4. 【算法】禁忌搜索算法(Tabu Search,TS)超详细通俗解析附C++代码实例

    01 什么是禁忌搜索算法? 1.1 先从爬山算法说起 爬山算法从当前的节点开始,和周围的邻居节点的值进行比较. 如果当前节点是最大的,那么返回当前节点,作为最大值 (既山峰最高点):反之就用最高的邻居 ...

  5. FreeCodeCamp 高级算法(个人向)

    freecodecamp 高级算法地址戳这里. freecodecamp的初级和中级算法,基本给个思路就能完成,而高级算法稍微麻烦了一点,所以我会把自己的解答思路写清楚,如果有错误或者更好的解法,欢迎 ...

  6. js 高级算法 - 动态规划

    主要是看了<数据结构与算法>有所感悟,虽然这本书被挺多人诟病的,说这有漏洞那有漏洞,但并不妨碍我们从中学习知识. 其实像在我们前端的开发中,用到的高级算法并不多,大部分情况if语句,for ...

  7. 禁忌搜索算法TSA 旅行商问题TSP python

    import math import random import numpy as np import matplotlib.pyplot as plt from mpl_toolkits.mplot ...

  8. C++实现禁忌搜索解决TSP问题

    C++实现禁忌搜索解决TSP问题 使用的搜索方法是Tabu Search(禁忌搜索) 程序设计 1) 文件读入坐标点计算距离矩阵/读入距离矩阵 for(int i = 0; i < CityNu ...

  9. 【优化算法】变邻域搜索算法解决0-1背包问题(Knapsack Problem)代码实例 已

    01 前言 经过小编这几天冒着挂科的风险,日日修炼,终于赶在考试周中又给大家更新了一篇干货文章.关于用变邻域搜索解决0-1背包问题的代码.怎样,大家有没有很感动? 02 什么是0-1背包问题? 0-1 ...

随机推荐

  1. Cosine Similarity of Two Vectors

    #include <iostream>#include <vector>#include <cmath>#include <numeric> templ ...

  2. JavaWEB开发入门

    1.WEB开发的相关知识 WEB,在英语中web即表示网页的意思,它用于表示Internet主机上供外界访问的资源. Internet上供外界访问的Web资源分为: •静态web资源(如html 页面 ...

  3. linux下sh语法(转载)

    介绍: 1 开头 程序必须以下面的行开始(必须方在文件的第一行): #!/bin/sh 符号#!用来告诉系统它后面的参数是用来执行该文件的程序. 在这个例子中我们使用/bin/sh来执行程序. 当编写 ...

  4. Vue Element-ui table只展开一行

    直接上代码了哈~ <template> <div class="app-content"> <div class="table_expand ...

  5. SLAM: VSLAM扫盲之旅

    在<机器人手册> 第2卷,这本书里面,第23章讲述了:三维视觉和基于视觉的实时定位于地图重建.在第37章里面,讲述了 同时定位与建图.指出了SLAM的三种基本方法. 一种是EKF的方法,但 ...

  6. 蛮好用的局域网测试工具iperf

    公司局域网总是莫名其妙的和一台机器网速很慢,虽然无法解决也无人解决,但是能有个有效的测试至少也会心里有数. 咱干不了网络硬件布线的活,就测测网速吧. 网上找了下,开始有文章介绍NetIQ Chario ...

  7. 【sqli-labs】 less16 POST - Blind- Boolian/Time Based - Double quotes (基于bool型/时间延迟的双引号POST型盲注)

    ' or 1=1# -->失败 1" or 1=1# -->失败 1') or 1=1# -->失败 1") or 1=1# -->成功 判断为双引号变形注 ...

  8. dataGridView 设置

    //窗体加载事件 //内容居中 dataGridView1.RowsDefaultCellStyle.Alignment = DataGridViewContentAlignment.MiddleCe ...

  9. 团体程序设计天梯赛-练习集-L1-046. 整除光棍

    L1-046. 整除光棍 这里所谓的“光棍”,并不是指单身汪啦~ 说的是全部由1组成的数字,比如1.11.111.1111等.传说任何一个光棍都能被一个不以5结尾的奇数整除.比如,111111就可以被 ...

  10. 测试模式 windows2008 内部版本7601

    win server 2008 r2 enterprise 64位系统. 最近手贱,对服务器进行了一下更新,结果傻叉了,这是什么鬼,明明显示已经激活的,但就是有这么一串碍眼的字幕. 电脑右下角居然出现 ...