SAT

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<map>
#include<time.h>
#include<set>
#include<queue>
#include<stack>
using namespace std;
const int MAXN=505;
//test
bool DEBUG1=false;
int testvar=50;
int TIME=0;

struct node{
	set<int> F;
	int fd;
};
bool find(set<int> C,int x){
//input:clause C and literal x
//output:1 denotes literal x is in C
//      0 denotes literal x is not in C
	return C.find(x)!=C.end();//C.find(x)返回值: x在C中则返回x的位置,否则返回C.end
}
void copy(int *tTP,set<int> *C,int *TP,set<int> *tC,int n,int m,int &tn,int &tm){
//input:把TP的数据存到tTP里去
//output:no exist
	tn=n,tm=m;
	for (int i=1;i<MAXN;i++) tTP[i]=TP[i];
	for (int i=1;i<MAXN;i++) tC[i]=C[i];
}
void back(int *tTP,set<int> *C,int *TP,set<int> *tC,int &n,int &m,int tn,int tm){
//input:把tTP的数据还原到TP里去
//output:no exist
	n=tn,m=tm;
	for (int i=1;i<MAXN;i++) TP[i]=tTP[i]; //注意
	for (int i=1;i<MAXN;i++) C[i]=tC[i];
}
void find3clause(int &c1,int &c2,int &c3,int x,int m,set<int> *C){
//input:找到degree 为3的variable x的3个子句
//output:0
	for (c1=1;c1<=m;c1++)
		if (find(C[c1],x)) break;
	for (c2=1;c2<=m;c2++)
		if (find(C[c2],-x)) break;
	for (c3=1;c3<=m;c3++)
		if (c3!=c1 && c3!=c2 && (find(C[c3],x) || find(C[c3],-x))) break;
}
bool reFrash(int &m,int *X,int *TP,node *H,set<int> *C,int &Upbound){
//input: 子句数m X是存当前赋值, TP是每个X的当前状态, H是递推关系, C是当前所有的子句
//output:1 至少做了一次操作:{1.子句为空,去掉子句;2.如果一个子句的字符值为1,去掉该子句; 如果为0,删去该子句中的字符}
//      0 无操作
	set<int>::iterator it;
	for (int i=1;i<=m;i++){ //一个个clause看,是否为空,是否有值确定了
		if (C[i].size()==0){
			C[i]=C[m--]; 
			Upbound--;
			return true;
		}
		for (it=C[i].begin();it!=C[i].end();it++){
			if (TP[abs(*it)]!=0) continue; //要值确定了才
			if (X[abs(*it)]==1){
				if (*it>0) C[i]=C[m--];
					  else C[i].erase(*it);
			}else{
				if (*it<0) C[i]=C[m--];
					  else C[i].erase(*it);
			}
			return true;
		}
	}
	return false;
}
void initial(int &n,int &m,set<int> *C){ //读取数据
//input:读入数据
  scanf("%d%d",&n,&m);
  for (int t=1;t<=m;t++){
  	int x;
    C[t].clear();
    while (~scanf("%d",&x) && x){
      C[t].insert(x);
    }
  }
}
bool rule1(int n,int &m,int *X,int *TP,node *H,set<int> *C){
	set<int>::iterator it;
	bool f=false;
	for (int i=1;i<=m;i++)
		for (it=C[i].begin();it!=C[i].end();it++){
			if (!find(C[i],-*it)) continue; // ~x x 别和X[i]=0,1弄混
			C[i--]=C[m--];
			f=true;
			break;
		}
	for (int x=1;x<=n;x++){
		if (TP[x]!=-1) continue;
		int p1=0,p2=0;
		for (int i=1;i<=m;i++){
			if (C[i].size()!=1) continue;
			if (find(C[i],x)) p1=i;
			if (find(C[i],-x)) p2=i;
		}
		if (!p1 || !p2) continue; //找不到包含~x的unit clause
		if (p1>p2) //多个删除注意顺序
		   C[p1]=C[m--],C[p2]=C[m--]; //出问题
		else
		   C[p2]=C[m--],C[p1]=C[m--];
		f=true;
	}
	return f;
}
bool rule2(int n,int &m,int *X,int *TP,node *H,set<int> *C){  //不用管dgree
	for (int z=1;z<=n;z++){
		if (TP[z]!=-1) continue;
		int p1=0,p2=0,h1=0,h2=0; //p1= x个数   p2= -x个数  h1= x unit  h2= -x unit
		for (int i=1;i<=m;i++){
			if (find(C[i],z)) {
				p1++;
			    if (C[i].size()==1) h1++;
			}
			if (find(C[i],-z)) {
				p2++;
				if (C[i].size()==1) h2++;
			}
		}
		if (h1>=p2){
			TP[z]=0; //z可以直接赋值
			X[z]=1;
			return true;
		}
		if (h2>=p1){
			TP[z]=0; //z可以直接赋值
			X[z]=0;
			return true;
		}
	}
	return false;
}
bool rule3(int n,int &m,int *X,int *TP,node *H,set<int> *C){
	int degree[MAXN];
	set<int>::iterator it;
	memset(degree,0,sizeof(degree));
    for (int i=1;i<=m;i++)
    	for (it=C[i].begin();it!=C[i].end();it++)
			degree[abs(*it)]++;
	for (int x=1;x<=n;x++){
		if (TP[x]!=-1 || degree[x]!=2) continue;
		int c1,c2;
		for (int i=1;i<=m;i++){ // x,x  ~x,~x在rule2会过滤掉
			if (find(C[i],x)) c1=i;
			if (find(C[i],-x)) c2=i;
		}
		C[c1].insert(C[c2].begin(),C[c2].end()); //合并set
		C[c1].erase(x),C[c1].erase(-x);
		TP[x]=1,H[x].F=C[c2],H[x].F.erase(-x);// x由c2得来
		C[c2]=C[m--]; //删掉c2
		return true;
	}
	return false;
}
bool rule5(int n,int &m,int *X,int *TP,node *H,set<int> *C){ //在实现的时候只需要让x=1
	int degree[MAXN];
	set<int>::iterator it;
	memset(degree,0,sizeof(degree));
    for (int i=1;i<=m;i++)
    	for (it=C[i].begin();it!=C[i].end();it++)
			degree[abs(*it)]++;
	for (int x=1;x<=n;x++){
		if (TP[x]!=-1 || degree[x]!=3) continue;
		int c1,c2,c3;
		find3clause(c1,c2,c3,x,m,C); //找到这三个clause
		int y=0;
		for (it=C[c1].begin();it!=C[c1].end();it++){
			if (degree[abs(*it)]!=3 || TP[abs(*it)]!=-1) continue; //是否出问题
			if (*it==x) continue;
			if (!find(C[c2],*it) && !find(C[c2],-*it)) continue;
			if (!find(C[c3],*it) && !find(C[c3],-*it)) continue;
			y=abs(*it);
			break;
		}
		if (!y) continue;
		if (find(C[c3],x)){ // x为(2,1)
			TP[x]=0;
			X[x]=1;
		}else{		// x为(1,2)
			TP[x]=0;
			X[x]=0;
		}
		return true;
	}
	return false;
}
bool rule6(int n,int &m,int *TP,node *H,set<int> *C){ //注意m为变参
	int degree[MAXN];
	set<int>::iterator it;
	memset(degree,0,sizeof(degree));
    for (int i=1;i<=m;i++)
    	for (it=C[i].begin();it!=C[i].end();it++)
			degree[abs(*it)]++;
	for (int x=1;x<=n;x++){
		if (TP[x]!=-1 || degree[x]!=3) continue;
		int c1,c2,c3,y=0;
		find3clause(c1,c2,c3,x,m,C); //找到这三个clause
		for (it=C[c1].begin();it!=C[c1].end();it++){
			if (*it==x) continue; //注意
			if (TP[abs(*it)]!=-1) continue; //需要么
			if (degree[abs(*it)]!=3) continue; //注意限制y的degree=3  *it的正负不用限制
			if (find(C[c2],-*it)){
				y=*it;
				break;
			}
			if (find(C[c3],-x) && find(C[c3],-*it)){ //注意C3必须是包含-x的才可以
				y=*it;
				swap(c2,c3);
				break;
			}
		}
		if (!y) continue; //找不到对应的y
		if (find(C[c3],x)){ //x为(2,1)
			TP[x]=1; //x的值由c2推出
			H[x].F=C[c2],H[x].F.erase(-x);
			C[c2].insert(C[c3].begin(),C[c3].end());
			C[c2].erase(x),C[c2].erase(-x);
			if (c1>c3) //多个删除注意顺序
				C[c1]=C[m--],C[c3]=C[m--]; //注意先改clause再删除clause
			else
				C[c3]=C[m--],C[c1]=C[m--];
		}else{				//x为(1,2)
			TP[x]=1; //x的值由c1推出
			H[x].F=C[c1],H[x].F.erase(x);
			C[c1].insert(C[c3].begin(),C[c3].end());
			C[c1].erase(x),C[c1].erase(-x);
			if (c2>c3)  //多个删除注意顺序
				C[c2]=C[m--],C[c3]=C[m--]; //注意先改clause再删除clause
			else
				C[c3]=C[m--],C[c2]=C[m--];
		}  
		return true;
	}
	return false;
}
bool rule7(int n,int &m,int *X,int *TP,node *H,set<int> *C){
	int degree[MAXN];
	set<int>::iterator it;
	memset(degree,0,sizeof(degree));
    for (int i=1;i<=m;i++)
    	for (it=C[i].begin();it!=C[i].end();it++)
			degree[abs(*it)]++;
	for (int z2=1;z2<=n;z2++){
		if (TP[z2]!=-1 || degree[z2]!=3) continue;
		int c1,c2,c3;
		find3clause(c1,c2,c3,z2,m,C); //找到这三个clause
		//找到了degree=3的z2三个clause c1,c2,c3
		int z1=0;
		for (it=C[c1].begin();it!=C[c1].end();it++)
			if (find(C[c2],*it) && TP[abs(*it)]==-1){ //是否需要限制TP[*it]
				z1=*it;
				break;
			}
		if (!z1) continue;
		if (find(C[c3],z2)){ //z2为(2,1)
			C[c1].erase(z1);
		}else{				 //z2为(1,2)
			C[c2].erase(z1);
		}
		return true;
	}
	return false;
}
bool rule8(int &n,int &m,int *X,int *TP,node *H,set<int> *C){ // (~x',D1,D2)
	int degree[MAXN];
	set<int>::iterator it;
	memset(degree,0,sizeof(degree));
    for (int i=1;i<=m;i++)
    	for (it=C[i].begin();it!=C[i].end();it++)
			degree[abs(*it)]++;
	for (int x=1;x<=n;x++){
		if (TP[x]!=-1 || degree[x]!=3) continue;
		int c1,c2,d1,d2;
		find3clause(c1,c2,d1,x,m,C);
		if (find(C[d1],x)){ //x,y为(2,1)
			swap(c2,d1);
			int y=0;
			for (it=C[c1].begin();it!=C[c1].end();it++){
				if (*it<0 || TP[*it]!=-1 || degree[*it]!=3) continue;
				if (*it==x) continue;
				if (find(C[c2],*it)){
					y=*it; //y满足: 正的在c1,c2中出现  y未赋值  y的degree=3  y!=x
					break;
				}
			}
			if (!y) continue; //找不到对应的y
			int yc1,yc2;
			find3clause(yc1,d2,yc2,y,m,C);
			H[y].F.clear(),H[y].F.insert(-x);
			H[x].F=C[d1],H[x].F.erase(-x);
			TP[++n]=-1;
			TP[x]=TP[y]=n;
			H[x].fd=H[y].fd=0;//x,y的值将由n来决定
			C[c1].erase(x),C[c1].erase(y),C[c1].insert(n);
			C[c2].erase(x),C[c2].erase(y),C[c2].insert(n);
			C[d1].insert(C[d2].begin(),C[d2].end());
			C[d1].erase(-x),C[d1].erase(-y),C[d1].insert(-n);
			C[d2]=C[m--];   //删去d2
		}else{				//x,y为(1,2)
			swap(c1,d1);
			int y=0;
			for (it=C[c1].begin();it!=C[c1].end();it++){
				if (*it>0 || TP[-*it]!=-1 || degree[-*it]!=3) continue;
				if (-*it==x) continue;
				if (find(C[c2],*it)){
					y=-*it;
					break;
				}
			}
			if (!y) continue; //找不到对应的y
			int yc1,yc2;
			find3clause(d2,yc2,yc1,y,m,C);
			H[x].F.clear(),H[x].F.insert(-y);
			H[y].F=C[d1],H[y].F.erase(x);
			TP[++n]=-1;
			TP[x]=TP[y]=n;
			H[x].fd=H[y].fd=1;//x,y的值将由n来决定
			C[c1].erase(-x),C[c1].erase(-y),C[c1].insert(n);
			C[c2].erase(-x),C[c2].erase(-y),C[c2].insert(n);
			C[d1].insert(C[d2].begin(),C[d2].end());
			C[d1].erase(x),C[d1].erase(y),C[d1].insert(-n);
			C[d2]=C[m--];
		}
		return true;
	}
	return false;
}
bool rule9(int &m,set<int> *C){
	set<int>::iterator it;
	for (int i=1;i<=m;i++){
		if (C[i].size()!=2) continue;
		int x[2],t=0;
		for (it=C[i].begin();it!=C[i].end();it++) x[t++]=*it;
		int p0=0,p1=0;
		for (int j=1;j<=m;j++){
			if (C[j].size()!=1) continue;
			if (find(C[j],-x[0])) p0=j;
			if (find(C[j],-x[1])) p1=j;
		}
		if (!p0 || !p1) continue;
		C[p1].insert(-x[0]); //先插入 后删除
		if (i>p0)
			C[i]=C[m--],C[p0]=C[m--];
		else
			C[p0]=C[m--],C[i]=C[m--];
		return true;
	}
	return false;
}

bool used[MAXN];


void searchH(int i,int n,int *TP,node *H,int *X){
//展开递推关系
//判断第i个变量的值, 通过H
//input:i is the existing extentable variableclause C and literal x
//output:1 denotes literal x is in C
//      0 denotes literal x is not in C
	set<int>::iterator it;
    if (TP[i]==0) return; //值是确定的 
	if (TP[i]>1){ //其值依赖于H[i].fx与H[i].F的值
		searchH(TP[i],n,TP,H,X);
		if (X[TP[i]]==0){    //根据rule8规则
			TP[i]=0,X[i]=H[i].fd; //根据rule8规则
			return;
		}
	}
	int t=0;  //只看H[i].F的值
	for (it=H[i].F.begin();it!=H[i].F.end();it++){
		int x=*it;
		searchH(abs(x),n,TP,H,X);
		if ((x>0 && X[x]==1) || (x<0 && X[-x]==0)){
			t=1;
			break;
		}
	}
	TP[i]=0,X[i]=t;
}
void consH(int n,int *TP,node *H,int *tTP,int *X){
//根据H,把X的值全构造出来
//input:clause C and literal x
//output:1 denotes literal x is in C
//      0 denotes literal x is not in C
	for (int i=1;i<=n;i++) tTP[i]=TP[i]; 
	for (int i=1;i<=n;i++) searchH(i,n,TP,H,X);
}
void reTP(int n,int *TP,int *tTP){
//还原tp
	for (int i=1;i<=n;i++) TP[i]=tTP[i];
}
void branch(int &n,int &m,int n0,int m0,int *X,int &maxNum,int *ans,set<int> *C,set<int> *C0,int *TP,node* H,int Upbound){
	while (1){
		while (reFrash(m,X,TP,H,C,Upbound)); //done
		if (Upbound<=maxNum) return;
		if (rule1(n,m,X,TP,H,C)) continue; //done
		if (rule2(n,m,X,TP,H,C)) continue; //done
		if (rule3(n,m,X,TP,H,C)) continue; //done
		if (rule5(n,m,X,TP,H,C)) continue; //done
		if (rule6(n,m,TP,H,C))   continue; //done
		if (rule7(n,m,X,TP,H,C)) continue; //done
		if (rule8(n,m,X,TP,H,C)) continue; //done
		if (rule9(m,C))          continue; //done
		break;
	}
	set<int> tC[MAXN];
	int tn,tm,tTP[MAXN],degree[MAXN],k=0;
	set<int>::iterator it;
	memset(degree,0,sizeof(degree));
    for (int i=1;i<=m;i++)
    	for (it=C[i].begin();it!=C[i].end();it++)
			degree[abs(*it)]++;	
	for (int i=1;i<=n;i++)
		if (TP[i]==-1 && degree[k]<degree[i]) k=i; 
	if (k){
		copy(tTP,C,TP,tC,n,m,tn,tm); //保护现场
		TP[k]=0; //值确定
		X[k]=0;
		branch(n,m,n0,m0,X,maxNum,ans,C,C0,TP,H,Upbound);
		back(tTP,C,TP,tC,n,m,tn,tm); //还原现场
		TP[k]=0; //----大错点----不加则死循环---
		X[k]=1;
		branch(n,m,n0,m0,X,maxNum,ans,C,C0,TP,H,Upbound);
		back(tTP,C,TP,tC,n,m,tn,tm); //还原现场
		return;
	}
	consH(n0,TP,H,tTP,X); //展开递推关系TP,H
	int t=0; 
	for (int i=1;i<=m0;i++)
		for (it=C0[i].begin();it!=C0[i].end();it++){
			if ((*it>0 && X[*it]==1) || (*it<0 && X[-*it]==0)){
				t++;
				break;
			}
		}
	if (t>maxNum){
		maxNum=t;
		for (int i=1;i<=n0;i++) ans[i]=X[i];
	}
	reTP(n0,TP,tTP);
	return;
}
int main(int argc,char **arg){
    freopen("sgen1-sat-60-100.cnf","r",stdin);
    freopen("output.txt","w",stdout);
    int n,m,n0,maxNum=0;
	set<int> C[MAXN],C0[MAXN];
	int ans[MAXN];
	int TP[MAXN]; //TP存变量的状态是 -1 未知  0 为确定值  1 由H[i].F得到  2看H[i].fx之后得到
    node H[MAXN];
    initial(n,m,C0);
    n0=n;
    int X[MAXN]={0,0,0,1,0,0,1,0,0,0,0,0,1,0,0,0,0,0,1,0,0,
					   0,0,1,0,0,0,1,0,0,0,0,1,0,0,0,1,0,0,0,0,
					   1,0,0,0,0,0,0,0,1,0,1,0,0,0,0,0,0,0,1,0 };
    memset(TP,-1,sizeof(TP));
	for (int i=1;i<=m;i++) C[i]=C0[i];
    if(DEBUG1)
    {
	//----------for test
    	memset(TP,0,sizeof(TP));
        srand((int)time(0));
    	for (int i=1;i<=testvar;i++){
    		int h=rand()%60+1;
    		while (1) {
    			if (TP[h]==0) break;
    			h=rand()%60+1;
    		}
    		TP[h]=-1;
    	}

    }
	//----------for test
    else memset(X,-1,sizeof(X));
	branch(n,m,n,m,X,maxNum,ans,C,C0,TP,H,m);
	printf("%d\n",maxNum);
	for (int i=1;i<=n0;i++)
    {
        if(ans[i]) printf("%d ", i);
        else printf("%d ",-i);
        if(i%20==0) puts("");
    }
	puts("");
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
组合优化问题一直是科学研究领域中的一个重要问题。目前解决组合优化问题的方法可以分为两类。Non-Population based 方法和Population based 方法。本文主要讨论属于Population based 方法的粒子群优化算法(PSO).粒子群优化算法由Dr.Eberhart 和Dr.Kenney 于1995年提出,它是受到鸟群或者鱼群的社会行为的启发而形成的一种基于种群的随机优化技术。粒子群优化算法属于进化算法,具有进化计算的基本特征。例如这个系统也是最初被初始化成为随机解的集合,然后通过更新后代并用迭代的方式来实现搜索最优解。然而,不同于进化算法的是,粒子群优化算法中的每个粒子都是待求问题的一个可能解,它跟随最优粒子在问题空间中飞行。每个粒子记录它所找到的最好值以及相应的坐标,这个值记做Pbest, 同时每个粒子还记录该群内所有粒子所找到的最好值以及相应的坐标,记做Gbest.。在每一次的迭代中,需要改变每个粒子飞向Pbest,和飞向Gbest的速度,然后还要通过分别乘以为Pbest和Gbest而生成的两个不同的随机数来平衡这种改变。本文在综述了PSO算法及其发展过程的基础上,还提出了一种通过引入局部搜索来提高粒子本身搜索能力的方法。现有的对于PSO的改进,无论是动态邻域的PSO算法还是2.6节所介绍DPSO,都强调加强粒子之间的信息共享,或者说是加强群的搜索能力,但是,人们并没有对粒子本身的搜索能力给以足够的重视。如果能够提高粒子本身的搜索能力,使粒子能够发现一定范围的最优解,那么就可以改变粒子的飞行轨迹,从而尽快找到最优解。所以在每次迭代的过程中,让每个粒子以随机步长执行一次局部搜索,这里局部搜索采用最速下降法,并把局部搜索中找到的最好值记做Lbest,然后使粒子在Lbest,Pbest,Gbest的共同作用下更新。其中Lbest的作用放在更新公式的第一部分。实验证明,对于标准的优化函数,当迭代次数为1000时,效果与标准PSO相似,但是当迭代次数达到1500时,该算法解的精度高于标准PSO算法,具有一定的实用价值。因为PSO算法最初被提出用来解决连续域上的优化问题,所以他在离散问题上的应用仍然十分有限。本文中提出了一种处理离散问题的PSO算法,主要针对SAT问题提出了一种BPSO(Binary Particle Swarm Optimization)算法。对于SAT问题,问题域是{0,1}n ,那么粒子的位置只能是0,1串,而且粒子的速度向量也只能是0或者1,这些都是离散量,所以引入概率的概念,通过轮盘赌的方法来控制粒子的位置以及粒子的飞行速率。 由于SAT问题是一种典型的多模式问题,也就是说一个SAT问题一般会有有多个解,正如前文所说,PSO算法并不适合解决多模式问题,所以为了使BPSO能够求解多模式问题,按下面的方式修改BPSO:当BPSO中某个粒子找到一个可满足的时候,把那个粒子从群中隔离,然后随机生成一个粒子替代原来的粒子,然后继续迭代。 这个算法的难点在于它的参数选择尤其是轮盘赌中的概率值的选取。通过实验,可以看到该算法处理小规模的SAT问题非常有效,平均每次可以找到1.9个解,这是现有的求解SAT问题得算法所不能做到的。但是应用BPSO求解大规模SAT问题效果还不理想,还有待于进一步研究。 管理毕业论文网www.yifanglunwen.com 音乐毕业论文www.xyclww.com 同时本文还讨论了如何使用PSO求解多目标规划问题。与传统的多目标规划算法相比,使用PSO算法不用进行复杂的求导运算,计算量小;而且也不需要按照某一标准组合多个目标,尽管这个标准很可能不满足实际需要;最重要的,使用PSO算法一次可以找到多个Pareto解,让用户自己选择适当的解。 医学论文网www.kuailelunwen.com;专业的医学论文网 英语毕业论文www.lanrenbanjia.com;商务英语论文 计算机论文www.lunwendingzhi.com java论文 机械毕业论文www.lunwenwanjia.com 本文综述了目前几种比较著名的使用PSO解决多目标规划问题的算法,比如6.3中介绍使用交配池的MOPSO算法,6.4种介绍的动态邻域的MOPSO算法等。但是对于多维多目标规划问题,使用PSO求解还存在一定困难,本文也将它留作开放问题。 总的来说,本文的具体工作在于:全面而具体的讨论了PSO算法的出现以及发展。在PSO算法中引入了局部搜索,在达到足够迭代次数的情况下,一定程度上改善了算法的执行效果。提出了一种BPSO算法,用来处理离散问题,尤其是SAT问题,该算法对于小规模问题十分有效。 经济论文www.youzhiessay.com 教育论文www.hu

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值