拟人退火算法解3SAT
拟人退火算法解3SAT
一、问题描述
3-SAT是SAT问题的一个特殊例子,当所有子句都刚好包含三个变量时,此类问题叫3-SAT问题。该问题相对于SAT问题,看似复杂度降低,但仍为NPC问题。由于其苛刻的条件(子句由三个变量组成),使其更容易归约到其他问题,因此比起SAT问题,3-SAT在NPC问题的证明中用得更加广泛。
二、算法
模拟退火算法:模拟退火算法来源于固体退火原理,将固体加温至充分高,再让其徐徐冷却,加温时,固体内部粒子随温升变为无序状,内能增大,而徐徐冷却时粒子渐趋有序,在每个温度都达到平衡态,最后在常温时达到基态,内能减为最小。根据Metropolis准则,粒子在温度T时趋于平衡的概率为e-ΔE/(kT),其中E为温度T时的内能,ΔE为其改变量,k为Boltzmann常数。用固体退火模拟组合优化问题,将内能E模拟为目标函数值f,温度T演化成控制参数t,即得到解组合优化问题的模拟退火算法:由初始解i和控制参数初值t开始,对当前解重复“产生新解→计算目标函数差→接受或舍弃”的迭代,并逐步衰减t值,算法终止时的当前解即为所得近似最优解,这是基于蒙特卡罗迭代求解法的一种启发式随机搜索过程。退火过程由冷却进度表(Cooling Schedule)控制,包括控制参数的初值t及其衰减因子Δt、每个t值时的迭代次数L和停止条件S。
拟人退火算法:在组合优化领域里, 当算法搜索到局部极小点时, 一般来说, 就不再往下搜索了。 但是对于 SAT 问题, 就这样停止搜索是不可取的, 其原因在于我们只对 SA T 问题的全局最优点感兴趣。 因为只有全局最优点才能回答该问题是否可满足。 因此我们必须采取有效的策略尽可能的避免陷入局部极小点, 或者到了局部极小点, 能够有效地跳出。 人类在长期的实践中, 积累了丰富的经验, 受他们启发, 我们可以找到一些解决问题的方法。 我们把从人类社会或自然现象中学习到的经验和方法称之为拟人策略。
我们知道, SA 算法能否找到 E (X ) 的全局最优解,取决于 T 0 是否足够高和 T 0 下降得是否足够慢,而这些正好与计算时间相反。虽然合理选择参数可以使得算法的实现只需问题规模的多项式时间,但是随着问题规模的增大,所需时间也随之增长,合理选择参数并不能从根本上提高算法的效率。怎样合理地产生状态 X 1,才是提高效率的关键。为了提高退火过程的效率,根据 SAT 问题的特点,我们提出如下拟人策略,即在每一个迭代步对每个非零子句都随机选择一个变元,将其取反, 来合理地产生状态X 1, 当然, 这里我们必须注意不能选择重复的变元,即在一个子句里随机选择一个变元后, 即使该变元再在其它非零子句里出现, 也不能被选择。 这就像一所学校最初制定一项分配政策, 总有满意和不满意的单位, 然后根据具体情况, 修改令某个单位不满意的一条规则, 使其满意。 当然这条规则在一个时期应统一, 不能这个单位一套, 对别的单位又是另一套。这样才能成为规则, 政策也才得以实施。 该策略可以避免盲目搜索以及减少陷入局部极小的机会, 而且具有一定的并行性。 此外, 给定一个具体的退火机制后, SA 算法并不保证能够找到全局最优点, 例如在SA T 问题里, 能找到一组赋值, 使它满足所有的子句。 前面说过, 我们只对 SA T 问题的全局最优点感兴趣, 当搜索过程陷入局部陷阱时, 就需要某种策略使搜索过程能够跳出, 从而使搜索过程尽可能的找到全局最优。
为了显示采用拟人策略的效果,我们将提出的PA 算法与改进前的 SA 算法作了比较。后者在每一个迭代步只随机选择一个变元,退火结束后, 如没有达到全局最
PA( ) 1 choose an initial solution X0 randomly 2 give an initial temperature T0, X<-X0, T<- T0 3 loop:while the stop criterion is not yet satisfied do 4 for i<- 1 to L do 5 Pick a solution X’ ∈ N(X) randomly 6 △f <-f(X’) – f(X) 7 If △f < 0 then X <- X’ 8 else X<- X’ with probability exp(-△f/T) 9 T <- g(T) 10 If f(X) ! = 0 then T = T1 goto loop; 11 Return X |
优, 则重新随机初始化变元的初值,再开始模拟退火过程。
三、 实验结果
数据集 |
变量个数 |
字句个数 |
运行时间(ms) |
L= 50;T =50; T_min = 1; r = 0.5; |
|||
1.txt |
30 |
129 |
242 |
2.txt |
30 |
129 |
1948 |
3.txt |
30 |
129 |
5185 |
4.txt |
40 |
172 |
12134 |
5.txt |
40 |
172 |
388 |
6.txt |
40 |
172 |
23304 |
7.txt |
50 |
215 |
810 |
8.txt |
50 |
215 |
73692 |
四、总结
在使用模拟退火算法求解Sat问题时算法需要注意的地方:
1)温度的设定及其变化函数;
2)在每个温度值下,进行尝试的次数;
3)评估函数选取问题。
但是本实验根据这三点修改跑出来的实验结果都没有达到文献[1]的效果。
参考
[1] 张德富, 黄文奇, 汪厚祥. 求解 SAT 问题的拟人退火算法[J].计算机学报, 2002, 25(2): 148-152.
模拟退火博客参考:
http://www.cnblogs.com/growing/archive/2010/12/16/1908255.html
http://www.bkjia.com/ASPjc/1015625.html
// 3SAT.cpp : 定义控制台应用程序的入口点。
//#include "stdafx.h"
#include"stdlib.h"
#include <algorithm>
#include <vector>
#include<math.h>
#include<time.h>
#include <iostream>
#include <fstream>
#include<ctime>using namespace std;
#define SOURCE 1 //0:LAS VEGAS 1:拟人退火 2:拟人退火 3:模拟退火#if SOURCE == 0
#define PRINTF_DEBUG printf
//#define PRINTF_DEBUG ////#define USE_BACKTRACK//宏打开表示结合回溯算法。#define RETURN_POSITIVE_VALUE(x) ((x >= 0)?x:(-x))#define TRUE 1
#define FALSE 2int m,n,l=3;//1. m=3(变元的个数),n=5(子句的个数),l=3(子句的长度)int input[430][4];//start from 0
bool input_delete[430];//start from 0
int xValue[201] = { 0 };
int trueNum = 0;//true counter;
int falseNum = 0;//false counter
int stopLV = 0;void SetXvalueZero(void )
{for (int i = 1; i <= m; i++)xValue[i] = 0;for (int i = 0; i < n; i++)input_delete[i] = false;
}
void checkAndDelete(void)
{for (int j = 0; j < n; j++)//calulate whole sentence{int count_tt1 = 0;int count_tt2 = 0;for (int i = 0; i < l; i++)//caculate every sentence{int index = RETURN_POSITIVE_VALUE(input[j][i]);if (((xValue[index] == TRUE) && (input[j][i] < 0)) || \((xValue[index] == FALSE) && (input[j][i] > 0)))count_tt1++;if (((xValue[index] == TRUE) && (input[j][i] > 0)) || \((xValue[index] == FALSE) && (input[j][i] < 0)))count_tt2++;}if ((count_tt1 == 2) && (count_tt2 == 0)){for (int i = 0; i < l; i++)//caculate every sentence{int index = RETURN_POSITIVE_VALUE(input[j][i]);if (xValue[index] == 0){if (input[j][i] > 0)xValue[index] = TRUE;elsexValue[index] = FALSE;}}input_delete[j] = true;}else if (count_tt2 > 0)input_delete[j] = true;}
}
bool satisfy(void)//flag: 返回当前[k] =true 赋值时子句满足的个数;false同理;trick:是否用技巧
{for (int j = 0; j < n; j++)//calulate whole sentence{if (input_delete[j] == false){int count_tt = 0;for (int i = 0; i < l; i++)//caculate every sentence{int index = RETURN_POSITIVE_VALUE(input[j][i]);if (((xValue[index] == TRUE) && (input[j][i] < 0)) || \((xValue[index] == FALSE) && (input[j][i] > 0)))count_tt++;}if (count_tt == 3)return false;}}return true;
}
int CaluteTrueNum(void)
{if (satisfy()){ int count_tt = 0;for (int j = 0; j < n; j++)//calulate whole sentence{//if (input_delete[j] == false){for (int i = 0; i < l; i++)//caculate every sentence{int index = RETURN_POSITIVE_VALUE(input[j][i]);if (((xValue[index] == TRUE) && (input[j][i] > 0)) || \((xValue[index] == FALSE) && (input[j][i] < 0))){count_tt++;break;}}}}return count_tt;}return -1;
}int CaluteTrueNum1(void)
{int count_tt = 0;for (int j = 0; j < n; j++)//calulate whole sentence{{for (int i = 0; i < l; i++)//caculate every sentence{int index = RETURN_POSITIVE_VALUE(input[j][i]);if (((xValue[index] == TRUE) && (input[j][i] > 0)) || \((xValue[index] == FALSE) && (input[j][i] < 0))){count_tt++;break;}}}}return count_tt;
}
int GetrandTF(void)
{long i = rand() * (trueNum + falseNum) / RAND_MAX;int retValue = TRUE;if (i <= trueNum)retValue = TRUE;elseretValue = FALSE;PRINTF_DEBUG("random = %d trueNum = %d falseNum = %d (trueNum + falseNum) = %d\n", i, trueNum, falseNum, (trueNum + falseNum));return retValue;
}
void Backtrack(int k)
{if (k > m){;;// return true;}else{xValue[k] = FALSE;if (satisfy())Backtrack(k + 1);xValue[k] = TRUE;if (satisfy())Backtrack(k + 1);}
}
bool LV(void)
{SetXvalueZero();for (int k = 1; k < stopLV; k++){PRINTF_DEBUG("########## k = %d\n", k);if (xValue[k] == 0){ xValue[k] = FALSE;falseNum = CaluteTrueNum();xValue[k] = TRUE;trueNum = CaluteTrueNum();if ((falseNum < 0) && (trueNum < 0))return false;else if(falseNum < 0)xValue[k] = TRUE;else if (trueNum < 0)xValue[k] = FALSE;else xValue[k] = GetrandTF();checkAndDelete();PRINTF_DEBUG("xValue[%d] = %d\n", k, xValue[k]);}}return true;
}
int _tmain(int argc, _TCHAR* argv[])
{srand((unsigned)time(NULL));ofstream fout("output.txt");for (int fileNum = 1; fileNum <= 1; fileNum++){char str[10];sprintf(str, "3SAT\\%d.txt", fileNum);freopen(str, "r", stdin);int i = 0;while (scanf("%d%d%d%d", &(input[i][0]), &(input[i][1]), &(input[i][2]), &(input[i][3])) != EOF){m = max(max(max(max(abs(input[i][0]), abs(input[i][1])), abs(input[i][2])), abs(input[i][3])), m);i++;}n = i;stopLV = m + 1;
#ifdef USE_BACKTRACKstopLV = m - 10;
#elsestopLV = m + 1;
#endifclock_t now_time = clock(); //long t1 = time(NULL);while (LV() == false);Backtrack(stopLV);clock_t finish = clock();long t = finish - now_time; //前后之差即程序运行时间 (ms)PRINTF_DEBUG("variable_num = %d\nsentence_num = %d\nstopLV = %d\n", m, n, stopLV);PRINTF_DEBUG("satisfy sentence num = %d\n", CaluteTrueNum1());PRINTF_DEBUG("consume time = %d\n", t);PRINTF_DEBUG("variable_num = %d\nsentence_num = %d\nstopLV = %d\n", m, n, stopLV);fout << str << " " << m << " " << n << " " << t<< endl; // fout用法和cout一致, 不过是写到文件里面去}return 0;
}
#elif SOURCE == 1int Caculate(vector<vector<int> > vec, vector<int > xValue)
{int retValue = 0;for (int i = 0; i < vec.size(); i++){int clause = 1;//子句内部相乘;for (int j = 0; j < vec[i].size(); j++){int temp;//cout << abs(vec[i][j]) << endl;if (vec[i][j]>0)temp = 1 - xValue[abs(vec[i][j])];elsetemp = xValue[abs(vec[i][j])];clause = clause * temp;}retValue = retValue + clause;}return retValue;
}
int Caculate1(vector<vector<int> > vec, vector<int > xValue)
{int retValue = 0;for (int i = 0; i < vec.size(); i++){for (int j = 0; j < vec[i].size(); j++){//cout << abs(vec[i][j]) << endl;if (((vec[i][j] > 0) && (xValue[abs(vec[i][j])] > 0)) ||((vec[i][j] < 0) && (xValue[abs(vec[i][j])] < 1)) ){retValue++; break;}}}return retValue;
}
bool CaculateBool(vector<vector<int> > vec, vector<int > xValue)
{int retValue = 0;for (int i = 0; i < vec.size(); i++){for (int j = 0; j < vec[i].size(); j++){//cout << abs(vec[i][j]) << endl;if (((vec[i][j] > 0) && (xValue[abs(vec[i][j])] > 0)) ||((vec[i][j] < 0) && (xValue[abs(vec[i][j])] < 1))){retValue++; break;}}}return (retValue == vec.size());
}
vector<int > GenerateX(vector<vector<int> > vec, vector<int > xValue)
{vector<int > retValue(xValue);vector<bool> flag(xValue.size(),false);for (int i = 0; i < vec.size(); i++){int clause = 1;//子句内部相乘;for (int j = 0; j < vec[i].size(); j++){int temp;//cout << abs(vec[i][j]) << endl;if (vec[i][j]>0)temp = 1 - retValue[abs(vec[i][j])];elsetemp = retValue[abs(vec[i][j])];clause = clause * temp;}if (clause != 0){vector<int > temp;if (flag[abs(vec[i][0])] == false) temp.push_back(vec[i][0]);if (flag[abs(vec[i][1])] == false) temp.push_back(vec[i][1]);if (flag[abs(vec[i][2])] == false) temp.push_back(vec[i][2]);if (!temp.empty()){int index = rand() % temp.size();index = abs(temp[index]);retValue[index] = 1 - retValue[index];flag[index] = true;}}}return retValue;
}
vector<int > GenerateX1(vector<vector<int> > vec, vector<int > xValue)
{vector<int > retValue(xValue);vector<bool> flag(xValue.size(), false);vector<int > unsatisfied;for (int i = 0; i < vec.size(); i++){int clause = 1;//子句内部相乘;for (int j = 0; j < vec[i].size(); j++){int temp;//cout << abs(vec[i][j]) << endl;if (vec[i][j]>0)temp = 1 - retValue[abs(vec[i][j])];elsetemp = retValue[abs(vec[i][j])];clause = clause * temp;}if (clause != 0){unsatisfied.push_back(i);}}for (int i = 0; i < unsatisfied.size(); i++){int temp;int randow = rand() % (unsatisfied.size() - i) + i;temp = unsatisfied[i];unsatisfied[i] = unsatisfied[randow];unsatisfied[randow] = temp;}for (int i = 0; i < unsatisfied.size(); i++){vector<int > temp;if (flag[abs(vec[unsatisfied[i]][0])] == false) temp.push_back(vec[unsatisfied[i]][0]);if (flag[abs(vec[unsatisfied[i]][1])] == false) temp.push_back(vec[unsatisfied[i]][1]);if (flag[abs(vec[unsatisfied[i]][2])] == false) temp.push_back(vec[unsatisfied[i]][2]);if (!temp.empty()){int index = rand() % temp.size();index = abs(temp[index]);retValue[index] = 1 - retValue[index];flag[index] = true;}}return retValue;
}
vector<int > GenerateX2(vector<vector<int> > vec, vector<int > xValue)
{vector<int > retValue(xValue);vector<bool> flag(xValue.size(), false);vector<int > unsatisfied;for (int i = 0; i < vec.size(); i++){int clause = 1;//子句内部相乘;for (int j = 0; j < vec[i].size(); j++){int temp;//cout << abs(vec[i][j]) << endl;if (vec[i][j]>0)temp = 1 - retValue[abs(vec[i][j])];elsetemp = retValue[abs(vec[i][j])];clause = clause * temp;}if (clause != 0){unsatisfied.push_back(i);}}int row = rand() % unsatisfied.size();int column = rand() %3;int index = abs(vec[row][column]);retValue[index] = 1 - retValue[index];return retValue;
}
void Johnson(vector<int > &ans)
{for (int i = 0; i<ans.size(); i++){if ((double)rand() / (RAND_MAX)>0.5){ans[i] = 1;}else{ans[i] = 0;}}
}
#define TYPE 1int _tmain(int argc, _TCHAR* argv[])
{srand((unsigned)time(NULL));ofstream fout("output1.txt", ios::app);//ofstream debug("debug.txt");//for (int fileNum = 1; fileNum <= 12; fileNum++){char str[10];sprintf(str, "3SAT\\%d.txt", fileNum);freopen(str, "r", stdin);vector<vector<int> > vec;int a, b, c,d;int maxX = 0;while (scanf("%d%d%d%d", &(a), &(b), &(c), &(d)) != EOF){vector<int > temp;temp.push_back(a);temp.push_back(b);temp.push_back(c);vec.push_back(temp);//vec[i][3] = d;maxX = max(max(max(abs(a), abs(b)), abs(c)), maxX);}vector<int > xValue(maxX+1, 0);/** J(y):在状态y时的评价函数值* Y(i):表示当前状态* Y(i+1):表示新的状态* r: 用于控制降温的快慢* T: 系统的温度,系统初始应该要处于一个高温的状态* T_min :温度的下限,若温度T达到T_min,则停止搜索*/bool runFlag = true; int tt = 0;//double T, T0 = vec.size(), T_min = 0.1;//double r = 0.5; int L = 10;double T = 100, T_min = 1;double r = 0.5; int L = 50, T0 = 100;clock_t now_time = clock(); //long t1 = time(NULL);loop:T = T0; tt = 0; Johnson(xValue);while ((T > T_min) && runFlag){for (int i = 0; i < maxX*L; i++){
#if TYPE == 1vector<int > newX = GenerateX(vec, xValue); int y1 = Caculate(vec, xValue);if (y1 == 0) { runFlag = false; break; }int y2 = Caculate(vec, newX);if (y2 == 0) { xValue = newX; runFlag = false; break; }int dE = (y2 - y1);debug << " ++++ newX: " << y2 << " ---- y1: " << y1 << endl;if (dE < 0) //表达移动后得到更优解,则总是接受移动{//cout << "dE < 0 xValue = newX;" << endl;xValue = newX; //接受从Y(i)到Y(i+1)的移动}else if (dE == 0){double i = rand()*1.0 / RAND_MAX;//cout << exp(-(1.001 - T / T0) * 6) << endl;//if (exp(-(1.001 - T / T0) * 6) > i){//cout << "dE > 0 xValue = newX;" << endl;//xValue = newX; //接受从Y(i)到Y(i+1)的移动}}else{// 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也double i = rand()*1.0 / RAND_MAX;debug << " ++++ deta: " << dE << " ---- T: " << T << " ---- exp : " << exp(-dE / T) << endl;if (exp(-dE / T) > i){//cout << "dE > 0 xValue = newX;" << endl;xValue = newX; //接受从Y(i)到Y(i+1)的移动}}}tt++;cout << T << endl;//T = T0 / (log(1 + tt) / log(2)); //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快,若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值T = T0 / (1 + 1.5*tt);// T = T * r;
#elif TYPE == 2vector<int > newX = GenerateX(vec, xValue);int y1 = Caculate1(vec, xValue);if (y1 == vec.size()) { runFlag = false; break; }int y2 = Caculate1(vec, newX);if (y2 == vec.size()) { xValue = newX; runFlag = false; break; }int dE = (y2 - y1);debug << " ++++ newX: " << y2 << " ---- y1: " << y1 << endl;if (dE > 0) //表达移动后得到更优解,则总是接受移动{//cout << "dE < 0 xValue = newX;" << endl;xValue = newX; //接受从Y(i)到Y(i+1)的移动}else if (dE == 0){double i = rand()*1.0 / RAND_MAX;//cout << exp(-(1.001 - T / T0) * 6) << endl;//if (exp(-(1.001 - T / T0) * 6) > i){//cout << "dE > 0 xValue = newX;" << endl;//xValue = newX; //接受从Y(i)到Y(i+1)的移动}}else{// 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也double i = rand()*1.0 / RAND_MAX;debug << " ++++ deta: " << dE << " ---- T: " << T << " ---- exp : " << exp(dE / T) << endl;if (exp(dE / T) > i){//cout << "dE > 0 xValue = newX;" << endl;xValue = newX; //接受从Y(i)到Y(i+1)的移动}}}tt++;cout << " ---- T: " << T << " ---- exp : " << exp(-5 / T) << endl;T = T0 / (log(1 + tt) / log(2)); //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快,若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值//T = T0 / (1 + tt);T = T * r;
#endif}if(CaculateBool(vec, xValue) == false){//cout << "<><><><>"<<endl;T0 = vec.size(); goto loop;//T = 10; goto loop;}clock_t finish = clock();long t = finish - now_time; //前后之差即程序运行时间 (ms)
#if TYPE == 1cout << str << " Caculate " << maxX << " " << vec.size() << " " << L << " " << r << " " << t << endl; // fout用法和cout一致;fout << str << " Caculate " << maxX << " " << vec.size() << " " << L << " " << r << " " << t << endl; // fout用法和cout一致;
#elif TYPE == 2cout << str << " Caculate1 GenerateX" << maxX << " " << vec.size() << " " << L << " " << r << " " << t << endl; // fout用法和cout一致;fout << str << " Caculate1 GenerateX" << maxX << " " << vec.size() << " " << L << " " << r << " " << t << endl; // fout用法和cout一致;
#endifvec.clear();}return 0;
}
#elif SOURCE == 2int Caculate(vector<vector<int> > vec, vector<int > xValue)
{int count = 0;for (int i = 0; i < vec.size(); i++){int clause = 1;//子句内部相乘;for (int j = 0; j < vec[i].size(); j++){if (vec[i][j]<0){int temp = (-1)*vec[i][j];if (xValue[temp] == 0){count++;break;}}else if (vec[i][j]>0){if (xValue[vec[i][j]] == 1){count++;break;}}}}return count;
}
bool CaculateBool(vector<vector<int> > vec, vector<int > xValue)
{int retValue = 0;for (int i = 0; i < vec.size(); i++){for (int j = 0; j < vec[i].size(); j++){int temp;//cout << abs(vec[i][j]) << endl;if (((vec[i][j] > 0) && (xValue[abs(vec[i][j])] > 0)) ||((vec[i][j] < 0) && (xValue[abs(vec[i][j])] < 1))){retValue++; break;}}}return (retValue == vec.size());
}
vector<int > GenerateX(vector<vector<int> > vec, vector<int > xValue)
{vector<int > retValue(xValue);int i = rand() % (xValue.size() - 1);retValue[i + 1] = 1 - retValue[i + 1];return retValue;
}
void Johnson(vector<int > &ans)
{for (int i = 0; i<ans.size(); i++){if ((double)rand() / (RAND_MAX)>0.5){ans[i] = 1;}else{ans[i] = 0;}}
}int _tmain(int argc, _TCHAR* argv[])
{srand((unsigned)time(NULL));ofstream fout("output.txt", ios::app);for (int fileNum = 1; fileNum <= 12; fileNum++){char str[10];sprintf(str, "%d.txt", fileNum);freopen(str, "r", stdin);vector<vector<int> > vec;int i = 0;int a, b, c, d;int maxX = 0;while (scanf("%d%d%d%d", &(a), &(b), &(c), &(d)) != EOF){vector<int > temp;temp.push_back(a);temp.push_back(b);temp.push_back(c);vec.push_back(temp);//vec[i][3] = d;maxX = max(max(max(abs(a), abs(b)), abs(c)), maxX);i++;}vector<int > xValue(maxX + 1, 0);/** J(y):在状态y时的评价函数值* Y(i):表示当前状态* Y(i+1):表示新的状态* r: 用于控制降温的快慢* T: 系统的温度,系统初始应该要处于一个高温的状态* T_min :温度的下限,若温度T达到T_min,则停止搜索*/int T = 1000, T_min = 0.001;double r = 0.98;Johnson(xValue);clock_t now_time = clock(); //long t1 = time(NULL);while (T > T_min){vector<int > newX = GenerateX(vec, xValue);int y1 = Caculate(vec, xValue);if (y1 == 0) break;int y2 = Caculate(vec, newX);if (y2 == 0) { xValue = newX; break; }int dE = y2 - y1;if (dE >= 0) //表达移动后得到更优解,则总是接受移动xValue = newX; //接受从Y(i)到Y(i+1)的移动else{// 函数exp( dE/T )的取值范围是(0,1) ,dE/T越大,则exp( dE/T )也double i = rand()*1.0 / RAND_MAX;if (exp(dE / T) > i)xValue = newX; //接受从Y(i)到Y(i+1)的移动}T = r * T; //降温退火 ,0<r<1 。r越大,降温越慢;r越小,降温越快,若r过大,则搜索到全局最优解的可能会较高,但搜索的过程也就较长。若r过小,则搜索的过程会很快,但最终可能会达到一个局部最优值//i++;}clock_t finish = clock();long t = finish - now_time; //前后之差即程序运行时间 (ms)cout << str << CaculateBool(vec, xValue) << endl;fout << str << " " << maxX << " " << vec.size() << " " << t << endl; // fout用法和cout一致;vec.clear();}return 0;
}
#elif SOURCE == 3
#include "stdafx.h"
#include <iostream>
#include <time.h>
#include <fstream>
#include <math.h>
using namespace std;#define ANSSIZE 100int ans[ANSSIZE];
int new_ans[ANSSIZE];
vector<vector<int> > x;
int n = 40;
int m = 172;int filename = 6;
char str[100];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, ofstream &fout)
{fout << " ++++ deta: " << deta << " ---- T: " << T << " ---- exp : " << exp(deta / T) << endl;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;sprintf(str, "output_%d.txt", filename);ofstream fout(str, ios::app);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, fout)){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];// }// }srand((unsigned)time(NULL));double run_time = 0.0; //执行时间time_t start, end;start = clock();ifstream fin;for (filename = 1; filename <= 12; filename++){
char str[100];
sprintf(str, "3SAT\\%d.txt", filename);
freopen(str, "r", stdin);int i = 0;
int a, b, c, d;
int maxX = 0;
while (scanf("%d%d%d%d", &(a), &(b), &(c), &(d)) != EOF)
{vector<int > temp;temp.push_back(a);temp.push_back(b);temp.push_back(c);x.push_back(temp);//vec[i][3] = d;maxX = max(max(max(abs(a), abs(b)), abs(c)), maxX);i++;
}m = i;n = maxX;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;
}
#endif
拟人退火算法解3SAT相关推荐
- 退火算法 贪婪算法_算法贪婪策略简介
退火算法 贪婪算法 介绍 (Introduction) The solution is determined by a sequence of steps each step has given a ...
- 使用绝热演化/量子退火算法求解矩阵本征态
问题定义 定义一个\(N\times N\)大小的矩阵\(H\),找到该矩阵的本征态.已知:若态矢量\(\left|\psi\right>\)为哈密顿矩阵\(H\)的本征矢,则有: \[H\le ...
- 量子计算机原理与退火算法的通俗解释
摘 要 量子理论自其产生就充满了争议,其抽象.不确定的特点使得其难以被大众理解.但随着科学的发展,量子理论的巨大潜能越来越多的被发掘出来,并被应用到了多种领域.本文的目的是尽力用基础易懂的语言来解释 ...
- Matlab--模拟退火算法优化指派问题
1.引言 之前二狗已经分别介绍过了,如何用模拟退火算法和遗传算法,进行背包问题的求解.其实背包问题是可以看成是一个可以看成是一个比较特殊的,有线性约束的,0-1规划问题.在数学中还有很多其他特殊的问题 ...
- 基于改进遗传退火算法的0-1背包问题设计与实现
JISHOUUNIVERSITY 本科生毕业设计 题 目: 基于改进遗传退火算法的0-1背包问题设计与实现 作 者: 秦峰 学 号: 20144042001 所属学院: 信息科学与工程 ...
- 粒子群算法和遗传算法的比较 退火算法
粒子群优化算法(PSO:Particle swarm optimization) 是一种进化计算技术(evolutionary computation).源于对鸟群捕食的行为研究.粒子群优化算法的基本 ...
- 爬山算法、退火算法、遗传算法
几种常用算法1:爬山算法.退火算法.遗传算法 文章目录 目录 前言 一.爬山算法( Hill Climbing ) 二.模拟退火算法(SA,Simulated Annealing) 2.1 模拟退火算 ...
- 退火算法解决简单优化问题
退火算法基本思想在此不再赘述,可参考本文.模板如下: T0 = 1000; % 初始温度 T = T0; % 迭代中温度会发生改变,第一次迭代时温度就是T0 maxgen = 500; % 最大迭代次 ...
- 动态规划算法解最长公共子序列LCS问题
动态规划算法解LCS问题 作者 July 二零一零年十二月三十一日 本文参考:微软面试100题系列V0.1版第19.56题.算法导论.维基百科. 第一部分.什么是动态规划算法 ok,咱们先来了解下什么 ...
最新文章
- AAAI 2019 《LiveBot: Generating Live Video Comments Based on Visual and Textual Contexts》论文笔记
- 身份验证和授权作为开源解决方案服务
- JAVA 内部类(innerclasses)
- node -v 突然显示 killed 9 处理历程
- php指令,php命令行下的常用命令
- 直接修改gba_gba修改教程完全版
- ubuntu 黑体_Ubuntu 10.04下安装字体最简单的方法
- 【源码分享】-c++界面源代码分享
- javscricpt基础
- 潭州教育学python怎么样_在潭州教育学原画两个月的感受
- 树莓派homebridge开机启动和后台运行
- yarn : 无法加载文件 C:\Users\Administrator\AppData\Roaming\npm\yarn.ps1
- [转]软件开发基本原则(二)典型错误
- WSL2连接调用USB设备
- ubuntu下的python的diango环境安装
- 【数字、字母、汉字组合字符串拆分处理】
- 第一课——进制转换学习实例
- 网站首页实战教程html,Python实战课程1-1练习:创建一个网页
- 给你的Zeit page自定义404页面
- DarkNet网络结构
热门文章
- python遍历替换字典的key_Python遍历字典去key和value需要注意的点→enumerate和items()...
- 兄弟Brother HL-2260D 驱动
- FPGA开发与ARM(单片机)开发的区别
- [转载] 童裕孙老师谈“如何学好数学基础课”
- 嵌入式 Linux 应用软件知识体系框架
- NOR Flash擦写和原理分析
- 少年之死的思考:AI能颠覆互联网招聘平台吗?
- java如何调用父类的实例对象_java子类调用父类的方法中包含子类重写的实例方法...
- class与Class的区别
- 记一次 leetcodeEdit Pro 利用力扣官网调试(二叉树题目)的代码 进行的成功调试