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

时间:2022-09-06 11:35:35

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

------------------------------------------------------

1 SAT问题描写叙述

命题逻辑中合取范式 (CNF)的可满足性问题 (SAT)是当代理论计算机科学的核心问题,是一典型的NP全然问题.在定义可满足性问题SAT之前,先引进一些逻辑符号。

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

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秒。结果例如以下:

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

------------------------------------------------------

參考文献

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

【高级算法】模拟退火算法解决3SAT问题(C++实现)的更多相关文章

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

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

  2. 【高级算法】禁忌搜索算法解决3SAT问题&lpar;C&plus;&plus;实现&rpar;

    转载请注明出处:http://blog.csdn.net/zhoubin1992/article/details/46440389 近期梳理,翻出了当年高级算法课程做的题目.禁忌搜索算法解决3SAT问 ...

  3. OI骗分神器——模拟退火算法

    前言&&为什么要学模拟退火 最近一下子学了一大堆省选算法,所以搞一个愉快一点的东西来让娱乐一下 其实是为了骗到更多的分,然后证明自己的RP. 说实话模拟退火是一个集物理与IT多方面知识 ...

  4. 原创&colon;工作指派问题解决方案---模拟退火算法C实现

    本文忽略了对于模拟退火的算法的理论讲解,读者可参考相关的博文或者其他相关资料,本文着重于算法的实现: /************************************************ ...

  5. BZOJ 3680&colon; 吊打XXX【模拟退火算法裸题学习,爬山算法学习】

    3680: 吊打XXX Time Limit: 10 Sec  Memory Limit: 128 MBSec  Special JudgeSubmit: 3192  Solved: 1198[Sub ...

  6. 模拟退火算法 R语言

    0 引言 模拟退火算法是用来解决TSP问题被提出的,用于组合优化. 1 原理 一种通用的概率算法,用来在一个打的搜索空间内寻找命题的最优解.它的原理就是通过迭代更新当前值来得到最优解.模拟退火通常使用 ...

  7. PKU 1379 Run Away&lpar;模拟退火算法&rpar;

    题目大意:原题链接 给出指定的区域,以及平面内的点集,求出一个该区域内一个点的坐标到点集中所有点的最小距离最大. 解题思路:一开始想到用随机化算法解决,但是不知道如何实现.最后看了题解才知道原来是要用 ...

  8. 初探 模拟退火算法 POJ2420 HDU1109

    模拟退火算法来源于固体退火原理,更多的化学物理公式等等这里不再废话,我们直接这么来看 模拟退火算法简而言之就是一种暴力搜索算法,用来在一定概率下查找全局最优解 找的过程和固体退火原理有所联系,一般来讲 ...

  9. &lbrack;HDU1109&rsqb;模拟退火算法

    模拟退火的基本思想: (1) 初始化:初始温度T(充分大),初始解状态S(是算法迭代的起点),每个T值的迭代次数L (2) 对k=1,……,L做第(3)至第6步: (3) 产生新解$S\prime $ ...

随机推荐

  1. python通过函数改变变量取值

    严格讲应该是"通过函数调用,改变引用对象".python中,要区分"变量名"和"对象" 如果是类的对象,是引用类型的,那么可以通过函数调用, ...

  2. Tomcat的目录结构

    bin:该目录下存放的是二进制可执行文件,如果是安装版,那么这个目录下会有两个exe文件:tomcat6.exe.tomcat6w.exe,前者是在控制台下启动Tomcat,后者是弹出UGI窗口启动T ...

  3. 【iCore2双核心板】SRAM 读写实验(基于Verilog语言)

    _____________________________________ 深入交流QQ群: A: 204255896(1000人超级群,可加入) B: 165201798(500人超级群,满员) C ...

  4. 走进科学之WAF&lpar;Web Appllication Firewall&rpar;篇

    小编P.S:文章非常详尽对WAF领域进行了一次科普,能有让人快速了解当前WAF领域的相关背景及现状,推荐所有WAF领域的同学阅读本文. 1. 前言 当WEB应用越来越为丰富的同时,WEB 服务器以其强 ...

  5. SQL Server 查看死锁的存储过程&lpar;转载&rpar;

    if exists (select * from dbo.sysobjects where id = object_id(N'[dbo].[sp_who_lock]') and ) drop proc ...

  6. Centos6&period;5网络无法连接问题

    1. 先进入对应文件夹: cd /etc/sysconfig/network-scripts/ 2.获取root权限: su     然后输入root密码 3.修改ifcfg-eth0 vi ifcf ...

  7. ebs清除并法管理器所清除的表

    In this Document   Goal   Solution   References Applies to: Oracle Concurrent Processing - Version 1 ...

  8. Javascrip 入门第三节课

    一.location对象 location.href 获取当前网页的URLlocation.search() 获取?之后的请求信息 location.href="URL" // 跳 ...

  9. Mybatis调用PostgreSQL存储过程实现数组入参传递

    注:本文来源于 < Mybatis调用PostgreSQL存储过程实现数组入参传递  > 前言 项目中用到了Mybatis调用PostgreSQL存储过程(自定义函数)相关操作,由于Pos ...

  10. 分布式系统的BASE理论

    一.BASE理论 eBay的架构师Dan Pritchett源于对大规模分布式系统的实践总结,在ACM上发表文章提出BASE理论,BASE理论是对CAP理论的延伸,核心思想是即使无法做到强一致性(St ...