Logic 查找可能的布尔值以将表达式求值为true
如果我有一个给定的布尔表达式(Logic 查找可能的布尔值以将表达式求值为true,logic,expression,logical-operators,boolean-logic,boolean-expression,Logic,Expression,Logical Operators,Boolean Logic,Boolean Expression,如果我有一个给定的布尔表达式(和和或操作)和许多布尔变量,那么我想将这个表达式求值为true,如何找到所有可能的布尔值集来获得一个真正的表达式 例如,我有4个布尔变量a,b,c,d和一个表达式: (a ^ b) v (c ^ d) 我尝试过的最慢的方法是: 我构建一个表达式树来获取表达式中的所有变量,我得到一个{a,b,c,d}集 我找到集合的所有子集:{a}、{b}、{c}、{d}、{a,b}、{a,c}、{b,c}、{b,d}、{b,d}、{c,d}、{a,b,c}、{a,b,d}、{
和
和或
操作)和许多布尔变量,那么我想将这个表达式求值为true,如何找到所有可能的布尔值集来获得一个真正的表达式
例如,我有4个布尔变量a
,b
,c
,d
和一个表达式:
(a ^ b) v (c ^ d)
我尝试过的最慢的方法是:
- 我构建一个表达式树来获取表达式中的所有变量,我得到一个
集{a,b,c,d}
- 我找到集合的所有子集:
{a}、{b}、{c}、{d}、{a,b}、{a,c}、{b,c}、{b,d}、{b,d}、{c,d}、{a,b,c}、{a,b,d}、{a,c,d}、{a,c,d}、{a,b,c,d}
- 对于每个子集,我将每个变量设置为true,然后计算表达式。如果表达式返回true,我将用值保存子集
EDIT:我消除了
NOT
操作符,使问题变得更简单。我想我找到了一种不必尝试所有排列的计算方法,下面描述的我的高级大纲并不十分复杂。我将概述基本方法,您将自己完成两项后续任务:
- 将逻辑表达式(如“a&&(B | | C)”解析为经典解析树,该解析树表示表达式,其中树中的每个节点要么是变量,要么是布尔运算,要么是“&&”、“| |”或“!”(NOT),其中两个子节点是其操作数。这是一个经典的解析树。谷歌上有很多这样做的例子
true
的所有变量的所有潜在值集的暂定列表true
或false
的可能值的数据类型:
typedef std::set<std::pair<std::string, bool>> values_t;
表示变量“a”的值为true
。因此,这个std::set
表示一组变量及其对应的值
所有这些潜在的解决方案都将是:
typedef std::list<values_t> all_values_t;
及
在片场。这意味着为了使表达式的计算结果为true
或false
,“a”必须同时为true和false
但这显然在逻辑上是不可能的。因此,在本解决方案的第2阶段,您需要简单地遍历所有值中的所有值,并删除包含某个变量的真和假的“不可能”值。实现这一点的方法应该看起来相当明显,我不会浪费时间来描述它,但是一旦第1阶段完成,第2阶段应该很简单
对于第1阶段,我们的目标是提出一个函数,大致如下所示:
all_values_t phase1(expression_t expr, bool goal);
expr
是布尔表达式的解析表示形式,作为解析树(正如我在开头提到的,这部分由您决定)goal
是您希望解析表达式的求值方式:phase1()
返回所有可能的所有值,对于这些值,expr
求值为true
或false
,如“goal”所示。显然,您将调用phase1()
passingtrue
以获取“目标”作为您的答案,因为这正是您想要了解的。但是phase1()
将递归地调用自己,使用true
或false
“目标”来实现它的魔力
在继续之前,现在重要的是阅读和理解描述归纳法证明如何工作的各种资源。在你完全理解这个一般概念之前,不要再继续下去
好了,现在你明白这个概念了。如果您这样做,那么您现在必须同意我的意见,即phase1()
已经完成。它起作用了!归纳法证明首先假设phase1()
做了它应该做的事情phase1()
将对自身进行递归调用,由于phase1()
返回正确的结果,phase1()
可以简单地依靠自身来解决所有问题。看看这有多容易
phase1()
手头确实有一个“简单”的任务:
- 检查解析树的顶级节点是什么。它将是变量节点或表达式节点(见上文)
- 在此基础上返回相应的
所有\u值\u t
就这样。我们将采取两种可能性,一次一种
顶层节点是一个变量
因此,如果表达式只是一个变量,并且希望表达式返回goal
,则:
values_t v{ {name, goal} };
表达式计算为goal
的方法只有一种:一种显而易见的简单方法:变量,以及goal
的值
只有一种可能的解决办法。没有其他选择:
all_values_t res;
res.push_back(v);
return res;
现在,另一种可能性是表达式中的顶级节点是布尔运算之一:and、or或not
再一次,我们要分而治之,一次解决一个问题
让我们说它不是。那我们该怎么办?这应该很容易:
return phase1(child1, !goal);
只需递归调用phase1()
,传递
values_t v{ {name, goal} };
all_values_t res;
res.push_back(v);
return res;
return phase1(child1, !goal);
all_values_t left_result=phase1(child1, true);
all_values_t right_result=phase1(child2, true);