离散数学:等价命题判断实验

实验目的

    学习逻辑表达式真值表建立,逻辑等价判断的实现。

实验内容与要求 

  •   写一段程序,测试p和q两个逻辑表达式是否逻辑相等
    • 用真值表判断
    • 输入的逻辑表达式为命题逻辑表达式
    • 输入的逻辑表达式可以为复合命题,可包含四种联接词:与,或,非,条件

实验原理:

1.输入变量的个数,比如a b c,通过stringstream来读取,存储在哈希表和vector中.

2.输入命题p,命题q.

3.深度优先搜索,枚举变量的真值表.

void dfs(int index) {

    if (末尾) {

        输出;

    }

    第index位取反;

    dfs(index + 1);

    第index位取反;

    dfs(index + 1);

}

4.在“输出”部分,处理命题p和q.按顺序读入p和q的字符串,&|!>分别为与、或、非、蕴含


对于如何读取逻辑表达式,可以直接对字符串从左到右解析。

bool process(string p) {
    bool res = true;
    int flag = 0;
    int rev = 0;
    for (int i = 0; i < p.length(); ++i) {
        switch (p[i]) {
        case '&':
            flag = 1;
            break;
        case '|':
            flag = 2;
            
            break;
        case '!':
        {
            int index = 0;
            for (; index < vars.size(); ++index) {
                if (p.substr(i+1).find(vars[index]) == 0)break;
            }
            string obj = vars[index];
            rev = !var[obj];
            switch (flag) {
            case 0:
                res = rev;
                break;
            case 1:
                res = res && rev;
                break;
            case 2:
                res = res || rev;
                if (res)return res;
                break;
            case 4:
               
                if (!res || (res && rev))return true;
                return false;

                break;
            }
            ++i;
            break;
        }
        case '>':
            flag = 4;
            break;
        default:
        {
            int index = 0;
            for (; index < vars.size(); ++index) {
                if (p.substr(i).find(vars[index]) == 0)break;
            }
            string obj = vars[index];
            switch (flag) {
            case 0:
                res = var[obj];
                break;
            case 1:
                res = res&&var[obj];
                break;
            case 2:
                res = res||var[obj];
                if (res)return res;
                break;
            case 4:
                if (!res||( res && var[obj]))return true;
                return false;


                break;
            }

        }


        }

    }


    return res;
}

显然,这种方式只能解析较为简单的逻辑表达式,且容易存在优先级处理的问题,因此需要使用更为高级的方法来解析字符串。

可以参见计算器对任意表达式的匹配,通过构建二叉树的方式来处理表达式。

读取表达式的算法(二叉树):

1.按照运算符优先级(括号>取反>或>且),进行构建二叉树

2.通过后序遍历,进行逻辑运算.

struct node
{
    bool bval = true;
    string val;
    node* l, * r;
};
bool singleBracket(string s) {

    if (s[0] == '(' && s[s.length() - 1] == ')') {
        string ss = s.substr(1, s.length() - 2);
        if (ss.find('(') == ss.npos && ss.find(')') == ss.npos)
            return 1;
    }
    return 0;
}
bool belongToBracket(string s, int i) {
    int l = 0, r = 0;
    for (int j = i; j >= 0; --j) {
        if (s[j] == '(')l--;
        if (s[j] == ')')l++;
        if (l == -1)return 1;
    }
    for (int j = i; j <s.length(); ++j) {
        if (s[j] == ')')r--;
        if (s[j] == '(')r++;
        if (r == -1)return 1;
    }
    return 0;
}
node* build(string p) {
    if (!p.length())return NULL;
    if (singleBracket(p)) {
        string s = p.substr(1, p.length() - 2);
        if(s.find('(')==s.npos&&s.find(')')==s.npos)
            return build(s);
    }
    int i = 0;
    node* obj = new node();
    if (p.length() == 1) {
        obj->val = p;
        return obj;
    }
    if (p.length()==2&&p[0]=='!'||singleBracket(p.substr(1)) && p[0] == '!') {
        obj->val = '!';
        obj->l = build(p.substr(1));
        return obj;
    }

    for (; i < p.length(); ++i) {
        if (p[i] == '>' && !belongToBracket(p,i)) {
            obj->val = p[i];
            obj->l = build(p.substr(0, i));
            obj->r = build(p.substr(i + 1, p.length() - i - 1));
            return obj;
        }
    }
    i = 0;
    for (; i < p.length(); ++i) {
        if (p[i] == '|' && !belongToBracket(p, i)) {
            obj->val = p[i];
            obj->l = build(p.substr(0, i));
            obj->r = build(p.substr(i + 1, p.length() - i - 1));
            return obj;
        }
    }
    i = 0;
    for (; i < p.length(); ++i) {
        if (p[i] == '&' && !belongToBracket(p, i)) {
            obj->val = p[i];
            obj->l = build(p.substr(0, i));
            obj->r = build(p.substr(i + 1, p.length() - i - 1));
            return obj;
        }
    }
    return obj;
}


bool postorder(node* tree) {
    if (!tree)return 1;
    if (tree->val[0] != '&' && tree->val[0] != '|' && tree->val[0] != '>'&& tree->val[0] != '!')
        return var[tree->val];
    bool L = 1, R = 1;
    if (tree->l)L = postorder(tree->l);
    if (tree->r)R = postorder(tree->r);

    switch (tree->val[0]) {
    case '&':
        return L && R;
    case '|':
        return L || R;
    case '>':
        return (L ? R : 1);
    case '!':
        return!(L && R);
    }
}


bool process(string p) {
    node* tree = build(p);
    return postorder(tree);
}

以下是完整的代码。

// Exp4_逻辑等价判断.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//


//bool process(string p) {
//    bool res = true;
//    int flag = 0;
//    int rev = 0;
//    for (int i = 0; i < p.length(); ++i) {
//        switch (p[i]) {
//        case '&':
//            flag = 1;
//            break;
//        case '|':
//            flag = 2;
//            
//            break;
//        case '!':
//        {
//            int index = 0;
//            for (; index < vars.size(); ++index) {
//                if (p.substr(i+1).find(vars[index]) == 0)break;
//            }
//            string obj = vars[index];
//            rev = !var[obj];
//            switch (flag) {
//            case 0:
//                res = rev;
//                break;
//            case 1:
//                res = res && rev;
//                break;
//            case 2:
//                res = res || rev;
//                if (res)return res;
//                break;
//            case 4:
//               
//                if (!res || (res && rev))return true;
//                return false;
//
//                break;
//            }
//            ++i;
//            break;
//        }
//        case '>':
//            flag = 4;
//            break;
//        default:
//        {
//            int index = 0;
//            for (; index < vars.size(); ++index) {
//                if (p.substr(i).find(vars[index]) == 0)break;
//            }
//            string obj = vars[index];
//            switch (flag) {
//            case 0:
//                res = var[obj];
//                break;
//            case 1:
//                res = res&&var[obj];
//                break;
//            case 2:
//                res = res||var[obj];
//                if (res)return res;
//                break;
//            case 4:
//                if (!res||( res && var[obj]))return true;
//                return false;
//
//
//                break;
//            }
//
//        }
//
//
//        }
//
//    }
//
//
//    return res;
//}

#include <iostream>
#include <string>
#include <stack>
#include <sstream>
#include <vector>
#include <unordered_map>
using namespace std;
unordered_map<string, bool>var;
vector<string>vars;

/// <summary>
/// & | ! >
/// </summary>
/// <param name="p"></param>
/// <returns></returns>


struct node
{
    bool bval = true;
    string val;
    node* l, * r;
};
bool singleBracket(string s) {

    if (s[0] == '(' && s[s.length() - 1] == ')') {
        string ss = s.substr(1, s.length() - 2);
        if (ss.find('(') == ss.npos && ss.find(')') == ss.npos)
            return 1;
    }
    return 0;
}
bool belongToBracket(string s, int i) {
    int l = 0, r = 0;
    for (int j = i; j >= 0; --j) {
        if (s[j] == '(')l--;
        if (s[j] == ')')l++;
        if (l == -1)return 1;
    }
    for (int j = i; j <s.length(); ++j) {
        if (s[j] == ')')r--;
        if (s[j] == '(')r++;
        if (r == -1)return 1;
    }
    return 0;
}
node* build(string p) {
    if (!p.length())return NULL;
    if (singleBracket(p)) {
        string s = p.substr(1, p.length() - 2);
        if(s.find('(')==s.npos&&s.find(')')==s.npos)
            return build(s);
    }
    int i = 0;
    node* obj = new node();
    if (p.length() == 1) {
        obj->val = p;
        return obj;
    }
    if (p.length()==2&&p[0]=='!'||singleBracket(p.substr(1)) && p[0] == '!') {
        obj->val = '!';
        obj->l = build(p.substr(1));
        return obj;
    }

    for (; i < p.length(); ++i) {
        if (p[i] == '>' && !belongToBracket(p,i)) {
            obj->val = p[i];
            obj->l = build(p.substr(0, i));
            obj->r = build(p.substr(i + 1, p.length() - i - 1));
            return obj;
        }
    }
    i = 0;
    for (; i < p.length(); ++i) {
        if (p[i] == '|' && !belongToBracket(p, i)) {
            obj->val = p[i];
            obj->l = build(p.substr(0, i));
            obj->r = build(p.substr(i + 1, p.length() - i - 1));
            return obj;
        }
    }
    i = 0;
    for (; i < p.length(); ++i) {
        if (p[i] == '&' && !belongToBracket(p, i)) {
            obj->val = p[i];
            obj->l = build(p.substr(0, i));
            obj->r = build(p.substr(i + 1, p.length() - i - 1));
            return obj;
        }
    }
    return obj;
}


bool postorder(node* tree) {
    if (!tree)return 1;
    if (tree->val[0] != '&' && tree->val[0] != '|' && tree->val[0] != '>'&& tree->val[0] != '!')
        return var[tree->val];
    bool L = 1, R = 1;
    if (tree->l)L = postorder(tree->l);
    if (tree->r)R = postorder(tree->r);

    switch (tree->val[0]) {
    case '&':
        return L && R;
    case '|':
        return L || R;
    case '>':
        return (L ? R : 1);
    case '!':
        return!(L && R);
    }
}


bool process(string p) {
    node* tree = build(p);
    return postorder(tree);
}
char btos(bool i) {
    return (i ? 'T' : 'F');
}
string p, q;
bool same = true;
void dfs(int index) {
    if (index == vars.size()) {
        if (process(p) != process(q))same = false;
        for (auto i : vars)cout << btos(var[i]) << (i != vars.back() ? "\t" : "");
        cout << "\t\t" << btos(process(p)) << "\t\t\t" << btos(process(q)) << endl;
        return;
    }
    var[vars[index]] = !var[vars[index]];
    dfs(index + 1);
    var[vars[index]] = !var[vars[index]];
    dfs(index + 1);
}
int main()
{
    cout << "请输入变量:" << endl;
    string src;
    getline(cin, src);
    stringstream ss(src);
    while (ss >> src) {
        if (!var[src])vars.push_back(src);
        var[src] = 1;
    }
    cout << "请输入命题p:" << endl;
    getline(cin, p);
    cout << "请输入命题q:" << endl;
    getline(cin, q);
    for (auto i : vars)cout << i << (i != vars.back() ? "\t" : "");
    cout << "\t\t" << p << "\t\t" << q << endl;
    dfs(0);
    if(same)
        cout << "两个命题等价!" << endl;
    else 
        cout << "两个命题不等价!" << endl;
    return 0;
}

  • 2
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值