C++实现离散数学求主合取范式和主析取范式

-------YYC

#include<iostream>

#include<string>
#include<map>
#include<list>
using namespace std;
/*
*说明:
*     用!表示 否定
*     用& 表示 合取
*     用| 表示 析取
*     用- 表示 条件
*     用~ 表示 双条件
*/
list<map<char,int>> inlist_value_map ;//用于记录所有最初变量的真值组合
list<map<char,int>> hqlist_value_map;//用于记录所有符合主合取范式条件的真值组合
list<map<char,int>> xqlist_value_map;//用于记录所有符合主析取范式条件的真值组合
int value=0;
//string expr;
//真值转换函数
void change_val(int & s)
{
if(0==s)
s=1;
else
s=0;
}


//处理基本连接词的函数
int deal_cal(int par1,char  par2,int par3)
{   // cout<<par2<<endl;
switch(par2)

 case '&'://合取
 return par1&&par3;
 break;
 case '|'://析取
 return par1||par3;
    break;
 case '-'://条件
 return !(par1==1&&par3==0);
    break;
 case '~'://双条件
 return (par1==par3);
    break;
 default:
 cout<<"有某些命题的真值错误"<<endl;
 break;
}


}


//没有括号的表达式处理函数
int run_unkh_expr( string & str,map<char ,int >& value_map)
{


int a;
int par_value;//该部分表达式的值
string::size_type l=str.length();
string::const_iterator it = str.begin();
for(;it!=str.end();it++)
{
 if(*it=='!')
{ //利用string类型的迭代器实现对String对象的字符的遍历访问。erase
string::const_iterator init_it = it+1;//保存!符后的下一个位置
change_val(value_map[*(init_it)]);//转换真值

str.erase(it);//删除否定符号
   }
}
it = str.begin();
par_value=value_map[*it];
if(l==1)//如果该部分只有一个命题则返回该命题的真值
{
return par_value;
}
else
{
for(;it !=str.end()-1;)
  {   // cout<<"从这儿"<<endl;
       ++it;
char b=*it;
// cout<<*it<<endl;
   par_value = deal_cal(par_value,b,value_map[*(++it)]);
  }
}
return par_value;
}


int run_expr(string & Expr,map<char ,int >& value_map)
{
//扫描括号
int sum_kh=0;//括号数
string::const_iterator iter;
string::const_iterator addr_kh[50];//用于记录括号的位置
char kind_kh[50];//用于记录括号的类型
for(iter = Expr.begin();iter!=Expr.end();iter++)
{
if(*iter=='('||*iter==')')
{
addr_kh[sum_kh]=iter;
kind_kh[sum_kh]=*iter;
sum_kh++;
}
}
if(0==sum_kh)//如果没有括号
{
value=run_unkh_expr(Expr,value_map);
return value;
}
else
{
int i=0;
for(;i<=sum_kh;i++)
{
if(kind_kh[i]==')')//找到最内级的括号并跳出循环
break;
}
//取出最内层没有括号的字符串
string in_str = string(addr_kh[i-1]+1,addr_kh[i]);
//算出最内层表达式的值
value = run_unkh_expr(in_str,value_map);
static char var = '1';


value_map[var]=value;//将括号整体设为一个字符‘1’
string::const_iterator ite =  addr_kh[i-1];//"字符(的位置"
//判断(是不是表达式的开头
string::const_iterator init_i;
bool is_begin=false;
if(ite==Expr.begin())
{is_begin = true;
}
else
{ init_i = addr_kh[i-1]-1;
}
{
Expr.erase(ite,addr_kh[i]+1);//删除掉最内层表达式包括括号在内
}
//再在删除的地方插入新的字符‘1’




if(is_begin==true)
{ Expr = var+Expr;
}
else
{Expr.insert(init_i+1,var);
}
var = var +1;
value = run_expr(Expr,value_map);
 
return value;
}


}
//求主析取范式和主合取范式的函数
//为value_map取到所有不同真值组合的函数
//回溯法


map<char,int>::iterator it;
map<char,int> in_value_map;
void init_value_map(map<char ,int >& value_map)
{
map<char ,int >::size_type lern = value_map.size();//用于记录变量的个数



 
    if(it == in_value_map.begin())
{   cout<<"进行赋值!"<<endl;
for(map<char,int>::const_iterator bb= value_map.begin();bb!=value_map.end();bb++)
{
in_value_map[bb->first]=bb->second;
}
it = in_value_map.begin();//重新对it赋值


 }
if(it == in_value_map.end())//如果已经赋值完毕则想队列中加载组合
{
 
  inlist_value_map.push_back(in_value_map);//向队列中加载组合


  --it;//如果到底了则只往回走一步,释放最后一步的资源


  return ;//跳出函数
}


 for(int i=0;i<2;i++)
 { 
 it->second = i;
 ++it;
 init_value_map(value_map);
 
 }
 --it;//每一个子树结束则往回退一步
}








int main()
{   string expr;
map<char ,int > initial_value_map;
cout<<"请先输入合式公式表达式"<<endl;
cin>>expr;

string::const_iterator iter = expr.begin();
for(;iter!=expr.end();iter++)
{
if(*iter!='!'&&*iter!='&'&&*iter!='~'&&*iter!='-'&&*iter!='|'&&*iter!='('&&*iter!=')')
{
initial_value_map[*iter]=1;//为每一个原子命题默认为真
}
}
//输出测试组合赋值函数
it = in_value_map.begin();
init_value_map(initial_value_map);
    cout<<"初始化完毕"<<endl;
//测试合式公式的真值
for(list<map<char,int>>::iterator ii=inlist_value_map.begin();ii!=inlist_value_map.end();ii++)
{  
map<char,int>::iterator ai = (*ii).begin();
if(ai==(*ii).end())
{
 cout<<"ii为空值"<<endl;
}
for(map<char,int>::iterator yy = (*ii).begin();yy !=(*ii).end();yy++)
{
cout<<"cal_value_map  "<<yy->first<<yy->second<<endl;
}

int is_true = 0;//用来记录该组合是否能使合式公式为真

string Expr = expr;
is_true =  run_expr(Expr,*ii);
cout<<"此次的真值是:"<<is_true<<endl;


if(1==is_true)//如果为真则记录在主析取范式队列中 
{
xqlist_value_map.push_back(*ii);
}
if(0==is_true)//如果为假则记录在主合取范式队列中 
{
hqlist_value_map.push_back(*ii);
}

}




//输出主析取范式
    list<map<char,int>>::iterator xqchei;
xqchei = xqlist_value_map.begin();
if(xqchei ==xqlist_value_map.end())
{


cout<<"该合式公式不存在主析取范式!"<<endl;

}
else
{


cout<<"该合式公式的主析取范式为:"<<endl;
for(list<map<char,int>>::iterator iit = xqlist_value_map.begin();iit != xqlist_value_map.end();iit++)
{

cout<<"(";
for(map<char,int>::iterator i = (*iit).begin();i !=(*iit).end();i++)
{  
if(i->first>='0'&&i->first<='9')//不输出表达式中的临时数字字符
{
;
}
else
{
if(0==i->second)
  {
cout<<"!";
  }
cout<<i->first;
map<char,int>::iterator iii=i;
++iii;
  if((iii)==(*iit).end())//如果是最后一位元素则不用再输出合取符
  {
    ;
  }
  else
  {
cout<<"/\\";
  }
}
}
cout<<")";
list<map<char,int>>::iterator aaa = iit;
++aaa;
if(aaa == xqlist_value_map.end())//如果是最后一组组合则不用再输出吸取符
{
;
}
else
{
cout<<"\\/";
}


}


    cout<<endl;
}
//输出主合取范式
    list<map<char,int>>::iterator hqchei;
hqchei = hqlist_value_map.begin();
if(hqchei ==hqlist_value_map.end())
{
cout<<"该合式公式不存在主合取范式!"<<endl;
}
else
{
cout<<"该合式公式的主合取范式为:"<<endl;
for(list<map<char,int>>::iterator iit = hqlist_value_map.begin();iit != hqlist_value_map.end();iit++)
{


cout<<"(";
for(map<char,int>::iterator i = (*iit).begin();i !=(*iit).end();i++)
{  
if(i->first>='0'&&i->first<='9')//不输出表达式中的临时数字字符
{
;
}
else
{


if(1==i->second)
  {
cout<<"!";
  }
cout<<i->first;
map<char,int>::iterator iii=i;
++iii;
  if((iii)==(*iit).end())//如果是最后一位元素则不用再输出合取符
  {
    ;
  }
  else
  {
cout<<"\\/";
  }


}
}


cout<<")";
list<map<char,int>>::iterator aaa = iit;
++aaa;
if(aaa == hqlist_value_map.end())//如果是最后一组组合则不用再输出吸取符
{
;
}
else
{
cout<<"/\\";
}


}
}
}
  • 8
    点赞
  • 26
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值