求解某个命题公式的真值表和主析取范式和主合取范式

一、求解公式

  思路:

  1、首先我们要处理这个公式怎么能被计算机怎样方便的计算,我们人类所熟悉的是中缀表达式,但是计算机需要的不是我们这种,计算起来十分麻烦,因此我们首先要把这个公式转换成后缀表达式(也就是逆波兰式)不会的同学可以去看看我那篇逆波兰表达式。

  2、然后我们要考虑公式符号的处理,因为我们计算机是没有->(蕴含符号) 和 <->(等价符号) 和 (取非符号的)所以我们要自定义符号,这里我把蕴含符号变成了‘-’号,等价符号变成了‘+’号,取非符号变成了‘ ! ',这样一来计算再次被化简。

  3、我们计算逆波兰表达式要用到栈结构,不了解得话可以去看看我的栈结构的文章啊。

  4、最后是统计主析取范式和主合取范式和真值表

  5、我们只需要遍历当前元素的个数,然后分别跑n个循环,就可以得到他们的真值表和主析取范式。。。。

二、代码实现

  1 #include <iostream>
  2 #include <queue>
  3 #include <vector>
  4 #include <cstring>
  5 #include <string>
  6 #include <map>
  7 #include <cmath>
  8 #include <algorithm>
  9 #include <set>
 10 #include <stack>
 11 #include <cstdio>
 12 #include <climits>
 13 #define PII pair<int,int>
 14 #define rep(i,z,n) for(int i = z;i <= n; i++)
 15 #define per(i,n,z) for(int i = n;i >= z; i--)
 16 #define ll long long
 17 #define db double
 18 #define vi vector<int>
 19 #define debug(x) cerr << "!!!" << x << endl;
 20 using namespace std;
 21 inline ll read()
 22 {
 23     ll s,r;
 24     r = 1;
 25     s = 0;
 26     char ch = getchar();
 27     while(ch < '0' || ch > '9'){
 28         if(ch == '-')
 29             r = -1;
 30         ch = getchar();
 31     }
 32     while(ch >= '0' && ch <= '9'){
 33         s = (s << 1) + (s << 3) + (ch ^ 48);
 34         ch = getchar();
 35     }
 36     return s * r;
 37 }
 38 inline void write(ll x)
 39 {
 40     if(x < 0) putchar('-'),x = -x;
 41     if(x > 9) write(x / 10);
 42     putchar(x % 10 + '0');
 43 }
 44 //后缀表达式
 45 string expression;
 46 int cop(char c)
 47 {
 48     if(c == '+')//对应等价
 49         return 1;
 50     else if(c == '-')//对应蕴含
 51         return 2;
 52     else if(c == '|')//对应吸取
 53         return 3;
 54     else if(c == '&')//对应合取
 55         return 4;
 56     else if(c == '!')//对应取非
 57         return 5;  
 58     return 0;
 59 }
 60 int prio(char c)
 61 {
 62     if(c == '(')//对应阔号
 63         return 0;
 64     else if(c == '+')//对应等价
 65         return 1;
 66     else if(c == '-')//对应蕴含
 67         return 2;
 68     else if(c == '|')//对应吸取
 69         return 3;
 70     else if(c == '&')//对应合取
 71         return 4;
 72     else if(c == '!')//对应取非
 73         return 5;
 74     return 0;
 75 }
 76 void aftExpression(string ms)
 77 {
 78     stack <char> ct;//定义一个ct容器存储运算符
 79     for(auto iter = ms.begin();iter != ms.end();iter++){
 80         if(*iter >= 'a' && *iter <= 'z')//如果是数字,直接入栈
 81             expression += *iter;
 82         else{
 83             if(ct.empty() || *iter == '(')//如果是空栈,或者是左括号,直接入栈
 84                 ct.push(*iter);
 85             else if(*iter == ')'){
 86                 while(ct.top() != '('){//把左括号和右括号里面的操作符出栈
 87                     expression += ct.top();
 88                     ct.pop();
 89                 }
 90                 ct.pop();//弹出左括号
 91             }
 92             else{
 93                 while(!ct.empty() && prio(*iter) <= prio(ct.top())){//把优先级低于当前操作符的操作符出栈
 94                     expression += ct.top();
 95                     ct.pop();
 96                 }
 97                 ct.push(*iter);//把当前操作符入栈
 98             }
 99         }
100     }
101     while(!ct.empty()){//如果栈区还有操作符
102         expression += ct.top();
103         ct.pop();
104     }
105     cout << "Aft expression is :";
106     cout << expression << endl;
107  }
108  int sw(char c,int p,int q,int r)
109  {
110      if(c == 'p')
111         return p;
112     else if(c == 'q')
113         return q;
114     else if(c == 'r')
115         return r;
116     return 0;
117  }
118  int compute(int p,int q,int r,string cpu)
119  {
120      stack <int> ans;
121      for(auto it = cpu.begin();it != cpu.end();it++){
122          if(*it >= 'a' && *it <= 'z')
123              ans.push(sw(*it,p,q,r));
124          else if(*it == '!'){
125              int num = ans.top();
126              ans.pop();
127              ans.push(!num);
128          }
129          else{
130              int num1 = ans.top();
131              ans.pop();
132              int num2 = ans.top();
133              ans.pop();
134              switch(cop(*it)){
135                  case 1: ans.push(num1 == num2);break;
136                  case 2: ans.push(num1 || !num2);break;
137                  case 3: ans.push(num1 || num2);break;
138                  case 4: ans.push(num1 && num2);break;
139              }
140          }
141      }
142      return ans.top();
143  }
144  string trans1(int p,int q,int r)
145  {
146      int cnt = p * 4 + q * 2 + r;
147      char c = cnt + '0';
148      string tmp = "m";
149      tmp += c;
150      return tmp;
151  }
152  string trans2(int p,int q,int r)
153  {
154      int cnt = p * 4 + q * 2 + r;
155      char c = cnt + '0';
156      string tmp = "M";
157      tmp += c;
158      return tmp;
159  }
160  void solve()
161  {
162      string s1[10];
163      string s2[10];
164      int cnt1,cnt2;
165      cnt1 = cnt2 = 0;
166      cout << "Table:p|q|r|rt" << endl;
167     for(int p = 0;p <= 1;p++)
168         for(int q = 0;q <= 1;q++)
169             for(int r = 0;r <= 1;r++){
170                 cout << "      " << p << '|' << q << '|' << r << '|' << compute(p,q,r,expression) << endl; 
171                 if(compute(p,q,r,expression))
172                     s1[++cnt1] = trans1(p,q,r);
173                 else
174                     s2[++cnt2] = trans2(p,q,r);
175             }
176     //主析取范式
177     cout << "Principal Disjunctive Normal Form:\n";
178     if(cnt1 == 0){
179         cout << "NULL" << endl;
180     }
181     else{
182         for(int i = 1;i <= cnt1;i++)
183             cout << "      " << s1[i] << endl;
184     }
185 
186     //主合取范式
187     cout << "Principal Conjunctive Normal Form:\n";
188     if(cnt2 == 0){
189         cout << "NULL" << endl;
190     }
191     else{
192         for(int i = 1;i <= cnt2;i++)
193             cout << "      " << s2[i] << endl;        
194     }
195  }
196 int main()
197 {
198     //输入逻辑表达式
199     string s;
200     cin >> s;
201     aftExpression(s);
202     solve();
203     return 0;
204 }

 

posted @ 2022-04-17 20:25  scannerkk  阅读(730)  评论(0)    收藏  举报