【高级算法】模拟退火算法解决3SAT问题(C++实现)
转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46453761
------------------------------------------------------
1 SAT问题描写叙述
命题逻辑中合取范式 (CNF)的可满足性问题 (SAT)是当代理论计算机科学的核心问题,是一典型的NP全然问题.在定义可满足性问题SAT之前,先引进一些逻辑符号。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhvdWJpbjE5OTI=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
------------------------------------------------------
2 模拟退火算法
模拟退火算法来源于固体退火原理,将固体加温至充分高。再让其徐徐冷却,加温时。固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每一个温度都达到平衡态。最后在常温时达到基态,内能减为最小。用固体退火模拟组合优化问题,将内能E模拟为目标函数值f,温度T演化成控制參数t,即得到解组合优化问题的模拟退火算法:由初始解i和控制參数初值t開始。对当前解反复“产生新解→计算目标函数差→接受或舍弃”的迭代,并逐步衰减t值,算法终止时的当前解即为所得近似最优解,这是基于蒙特卡罗迭代求解法的一种启示式随机搜索过程。
模拟退火算法能够分解为解空间、目标函数和初始解3部分。其基本思想是:
(1)初始化:初始温度T(充分大),初始解状态s(是算法迭代的起点)。每一个T值的迭代次数L(Markov链长),衰减准则α,停止准则。
(2)对k=1,……,L做第(3)至第(6)步。
(3)产生新解s′。
(4)计算增量cost=cost(s′)-cost(s),当中cost(s)为评价函数;
(5)若t′<0则接受s′作为新的当前解,否则以概率exp(-t′/T)接受s′作为新的当前解。
(6)假设满足终止条件则输出当前解作为最优解,结束程序。否则T逐渐降低,并转第2步运算。
模拟退火算法伪代码例如以下:
- <span style="font-size:14px;">choose an initial solution X0 randomly //随机的选择一个初始解X0
- give an initial temperature T0 , X ← X0, T ← T0 //初始化温度T0
- while the stop criterion is not yet satisfied do //停止准则不满足则
- { for i ← 1 to L do //Markov 链的长度 L
- { pick a solution X'∈N(X) randomly //随机选择临域内一个解X'
- Δf ← f(X')-f(X)
- if Δf<0 then X ← X'
- else X ← X' with probability exp(- Δf/T) }
- // 以exp(- Δf/T)的接受概率接受X'
- T← g(T) //generally, T ← aT } //温度下降
- return X
- </span>
------------------------------------------------------
3 C++实现代码
- // SA3Sat.cpp : 定义控制台应用程序的入口点。
- //
- /*********************************
- -----------------------------------
- 模拟退火解决3SAT问题(C++实现代码)
- -----------------------------------
- Author:牧之丶 Date:2014年
- Email:bzhou84@163.com
- **********************************/
- #include "stdafx.h"
- #include <iostream>
- #include <time.h>
- #include <fstream>
- #include <math.h>
- using namespace std;
- #define ANSSIZE 100
- int ans[ANSSIZE];
- int new_ans[ANSSIZE];
- int **x;
- int n=100;
- int m=430;
- int randomi(int a, int b)
- {
- int c=rand()%(b-a+1)+a;
- return c;
- }
- double randomf(double a, double b)
- {
- double c = (double)(rand()%((int)b-(int)a)) + a + (double)(rand()/(RAND_MAX + 1.0));
- return c;
- }
- void Johnson(int n)
- {
- for (int i = 0 ; i<n ; i++)
- {
- if ((double)rand()/(RAND_MAX)>0.5)
- {
- ans[i] = 1;
- }
- else
- {
- ans[i] = 0;
- }
- }
- }
- int satisfied_ans(int m)
- {
- int count = 0;
- int i,j;
- for (i = 0 ; i<m ; i++)
- {
- for (j = 0 ; j<3 ; j++)
- {
- if (x[i][j]<0)
- {
- int temp= (-1)*x[i][j];
- if (ans[temp-1]==0)
- {
- count++;
- break;
- }
- }
- else if (x[i][j]>0)
- {
- if (ans[x[i][j]-1]==1)
- {
- count++;
- break;
- }
- }
- }
- }
- return count;
- }
- int satisfied_new_ans(int m)
- {
- int count = 0;
- int i,j;
- for (i = 0 ; i<m ; i++)
- {
- for (j = 0 ; j<3 ; j++)
- {
- if (x[i][j]<0)
- {
- int temp= (-1)*x[i][j];
- if (new_ans[temp-1]==0)
- {
- count++;
- break;
- }
- }
- else if (x[i][j]>0)
- {
- if (new_ans[x[i][j]-1]==1)
- {
- count++;
- break;
- }
- }
- }
- }
- return count;
- }
- void disturb(int n)
- {
- for (int j = 0 ; j<n ;j++)
- {
- new_ans[j] = ans[j];
- }
- int i = rand()%n;
- new_ans[i] = 1-new_ans[i];
- }
- bool accept(int deta,float T)
- {
- if (deta>0)
- {
- return 1;
- }
- else if(((deta<0)&&(exp(deta/T)>randomf(0,1))))
- {
- return 1;
- }
- return 0;
- }
- void SA3Sat(int n,int m)
- {
- int i;
- Johnson(n); //初始解
- float T = 1000; //初始温度
- int L = 100*n;
- float T_time=0.001;
- while(T>T_time&&satisfied_ans(m)!=m)
- {
- for (i= 0 ; i<L ; i++)
- {
- disturb(n);
- // for (i = 0 ; i<n ; i++)
- // {
- // cout<<ans[i]<<" ";
- // }
- int deta = satisfied_new_ans(m)-satisfied_ans(m);
- if (accept(deta,T))
- {
- for (int j = 0 ; j<n ; j++)
- {
- ans[j] = new_ans[j];
- }
- }
- }
- T = 0.98*T;
- }
- }
- int _tmain(int argc, _TCHAR* argv[])
- {
- // int n,m,i,j;
- // cin>>n>>m; //3SAT问题
- // x = new int*[m];
- // for (i = 0 ; i<m ; i++)
- // {
- // x[i] = new int[3];
- // }
- // for (i = 0 ; i<m ; i++) //子句
- // {
- // for (j = 0 ; j<3 ; j++)
- // {
- // cin>>x[i][j];
- // }
- // }
- double run_time = 0.0; //执行时间
- time_t start,end;
- start = clock();
- ifstream fin;
- fin.open("10.txt");
- int i,j,t;
- x = new int*[m];
- for (i = 0 ; i<m ; i++)
- {
- x[i] = new int[3];
- }
- for (i = 0 ; i<m ; i++)
- {
- for (j = 0 ; j<3 ; j++)
- {
- fin>>x[i][j];
- }
- fin>>t;
- }
- fin.close();
- srand((unsigned)time(NULL));
- SA3Sat(n,m);
- cout<<"可满足的子句个数:"<<satisfied_ans(m)<<endl;
- cout<<"变元的终于取值为:";
- for (i = 0 ; i<n ; i++)
- {
- cout<<ans[i]<<" ";
- }
- // if (satisfied_ans(m)==m)
- // {
- // cout<<"Yes";
- // }
- // else
- // {
- // cout<<"No";
- // }
- end = clock();
- run_time = (end - start)/CLOCKS_PER_SEC;
- printf("执行时间为 : %f\n", run_time);
- system("pause");
- return 0;
- }
------------------------------------------------------
4 实验结果
4.1 參数设置
控制參数初值:t0=1000。
停止准则:温度达到设置的下限时即停止算法执行或达到最大可满足子句条件。
冷却进度表中的控制參数t的衰减函数:a(t)=0.98*t;
Mapkob链长:定长100*m。
4.2 实验结果
測试用例(1.txt):http://download.csdn.net/detail/zhoubin1992/8794893
样本为1.txt。变元个数n=30,子句个数m=129时,可满足的子句数为128,执行时间为19.0000秒。结果例如以下:
------------------------------------------------------
參考文献
[1] 张德富.算法设计与分析(高级教程)[M].国防工业出版社,2007.
【高级算法】模拟退火算法解决3SAT问题(C++实现)的更多相关文章
- 【高级算法】遗传算法解决3SAT问题(C++实现)
转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46910079 1 SAT问题描写叙述 命题逻辑中合取范式 (CNF) 的可满足性问 ...
- 【高级算法】禁忌搜索算法解决3SAT问题(C++实现)
转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46440389 近期梳理,翻出了当年高级算法课程做的题目.禁忌搜索算法解决3SAT问 ...
- OI骗分神器——模拟退火算法
前言&&为什么要学模拟退火 最近一下子学了一大堆省选算法,所以搞一个愉快一点的东西来让娱乐一下 其实是为了骗到更多的分,然后证明自己的RP. 说实话模拟退火是一个集物理与IT多方面知识 ...
- 原创:工作指派问题解决方案---模拟退火算法C实现
本文忽略了对于模拟退火的算法的理论讲解,读者可参考相关的博文或者其他相关资料,本文着重于算法的实现: /************************************************ ...
- BZOJ 3680: 吊打XXX【模拟退火算法裸题学习,爬山算法学习】
3680: 吊打XXX Time Limit: 10 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 3192 Solved: 1198[Sub ...
- 模拟退火算法 R语言
0 引言 模拟退火算法是用来解决TSP问题被提出的,用于组合优化. 1 原理 一种通用的概率算法,用来在一个打的搜索空间内寻找命题的最优解.它的原理就是通过迭代更新当前值来得到最优解.模拟退火通常使用 ...
- PKU 1379 Run Away(模拟退火算法)
题目大意:原题链接 给出指定的区域,以及平面内的点集,求出一个该区域内一个点的坐标到点集中所有点的最小距离最大. 解题思路:一开始想到用随机化算法解决,但是不知道如何实现.最后看了题解才知道原来是要用 ...
- 初探 模拟退火算法 POJ2420 HDU1109
模拟退火算法来源于固体退火原理,更多的化学物理公式等等这里不再废话,我们直接这么来看 模拟退火算法简而言之就是一种暴力搜索算法,用来在一定概率下查找全局最优解 找的过程和固体退火原理有所联系,一般来讲 ...
- [HDU1109]模拟退火算法
模拟退火的基本思想: (1) 初始化:初始温度T(充分大),初始解状态S(是算法迭代的起点),每个T值的迭代次数L (2) 对k=1,……,L做第(3)至第6步: (3) 产生新解$S\prime $ ...
随机推荐
- Oracle 创建分页存储过程(转帖)
原贴地址:http://19880614.blog.51cto.com/4202939/1316560 ps:源代码还有很多错误,我修改了 ------------------------------ ...
- SQL中varchar和nvarchar有什么区别?
varchar(n)长度为 n 个字节的可变长度且非 Unicode 的字符数据.n 必须是一个介于 1 和 8,000 之间的数值.存储大小为输入数据的字节的实际长度,而不是 n 个字节.nvarc ...
- 2D简单图形相关算法罗列
因为平常在Qt开发过程中经常会与一些简单的2D几何图形打交道,因此学习和掌握一些基本的2D几何计算还是很有必要的,在这里罗列一些常用的基本情况,之后会适时补充. [1] 两点之间距离,根据两个点的差值 ...
- CentOS6.5 下 Mysql5.7主从复制
包下载http://url.cn/WrNg5S 主数据库:192.168.161.129 从数据库1:192.168.161.130 从数据库1:192.168.161.138 MySQL安装地址:/ ...
- Oracle高级查询,事物,过程及函数
一 数值函数 数值 abs,ceil,floor,round,trunc字符串 instr,substr SQL>SELECT 'ABS':'|| ABS(-12.3) FROM DUAL; 运 ...
- VSS迁移
今天花了一上午的时间,对VSS源代码库从一个服务器A上迁移到另一个服务器B上,包括修改历史.用户.以及权限.具体方法如下: 1.在服务器B上安装vss程序后,创建一database,并设置创建后的文件 ...
- 百度地图api窗口信息自定义
百度地图加载完后,完全可以用dom方法操作,比较常用的就是点击mark的弹窗,利用jQuery可以很快的创建弹窗,需要注意的就是地图都是异步加载,所以绑定时间要用 jQuery 事件 - delega ...
- java 获取页面中的 a 标签 的 href 实例
Pattern p = Pattern.compile("<a\\s+href\\s*=\\s*(\"|\')?(.*?)[\"|\'|>]", P ...
- 周赛A题
A Time Limit:2000MS Memory Limit:32768KB 64bit IO Format:%lld & %llu Description By d ...
- Android4.2增加新键值
这里添加新的键值,不是毫无凭据凭空创造的一个键值, 而是根据kernel中检测到的按键值,然后转化为android所需要的数值: 以添加一个linux键值为217,把它映射为android的键值Bro ...