Simplifying a boolean expression with 4 variables - boolean

I can't figure this one out, I'm going insane looking through my textbook.
The expression is: (!w && !x && !y && z) || (w && !x && !y && z) || (x && z) || (x && y && !z)
Using distributive and compliment laws, I have narrowed it down to:
(!x && !y && z) || (x && z) || (x && y && !z)
But I can't narrow it any further! The answer is supposed to be (x && y) || ( !y && z) but I can't figure out what law would put me there. My teacher told me to use distributive but wouldn't help me further. That doesn't make any sense since there's nothing I can factor out and get rid of. What law am I supposed to use next?

You can expand xz to x(y + !y)z => xyz + x!yz.
Now you have !x!yz + xyz + x!yz + xy!z.
Then !x!yz + x!yz simplifies to !yz, and xyz + xy!z simplifies to xy,
giving the minimal expression.

Related

How to simplify and extend verified algorithm?

I implemented and verified a quicksort function based on the implementation here on page 22.
It verifies (hurray!) but I'm not too happy with the proof, quicksortSorted, that the quicksort function is sorted for a couple reasons that lead to the following questions.
For whatever reason it seems like the proof will not verify because of the two recursive calls needed by the lemma. I got around this by setting the quicksort function to opaque and using another helping lemma quicksortDef when I needed to assert something about its definition. I feel like making the function opaque shouldn't be required. Is there another way to call the recursive subcases that doesn't explode? (better inductive setup?)
Following from above I saw the {:fuel} attribute exists, can it be used to improve this situation?
Although I was able to verify the lemma that quicksort ensures the result is sorted. It would be nice if that fact was part of the ensure conditions of the quicksort function, but my attempts to add it there always seemed to trigger endless recursion. Is there a better way to define quicksort or to prove it which allows this?
When I tried to set filter and quicksort to be function methods I got an error about filters parameter being a ghost variable. Why is a generic predicate function parameter a ghost variable?
Finally the quicksortSorted lemma feels a bit over-complicated, any suggestion on how to simplify it?
Whole implementation on github:
function {:opaque} quicksort(xs: seq<int>): seq<int>
// ensures sortedRec(quicksort(xs))
ensures multiset(xs) == multiset(quicksort(xs))
ensures xs == [] ==> quicksort(xs) == []
ensures xs == [] ==> quicksort(xs) == []
decreases multiset(xs)
{
if xs == [] then [] else
assert xs == [xs[0]] + xs[1..];
filterPreservesMultiset(xs);
// var ln := y => y < xs[0];
// var gn := y => y >= xs[0];
var ln := lessThanFirst(xs);
var gn := greaterOrEqualFirst(xs);
filterMultiSetSlice(xs, xs[1..], ln);
filterMultiSetSlice(xs, xs[1..], gn);
quicksort(filter(xs[1..], ln)) + [xs[0]] + quicksort(filter(xs[1..], gn))
}
lemma quicksortDef(xs: seq<int>)
requires |xs| > 0
ensures quicksort(xs) == quicksort(filter(xs[1..], lessThanFirst(xs))) + [xs[0]] + quicksort(filter(xs[1..], greaterOrEqualFirst(xs)))
{
reveal quicksort();
}
lemma quicksortSorted(xs: seq<int>)
ensures sortedRec(quicksort(xs))
decreases multiset(xs)
{
if xs == [] {
assert quicksort(xs) == [];
assert sortedRec(quicksort(xs));
}else{
assert xs == [xs[0]] + xs[1..];
var ln := lessThanFirst(xs);
var gn := greaterOrEqualFirst(xs);
if xs[1..] == [] {
assert xs == [xs[0]];
assert sortedRec([xs[0]]);
}else{
// filterPreservesMultiset(xs[1..]);
filterMultiSetSlice(xs, xs[1..], ln);
filterMultiSetSlice(xs, xs[1..], gn);
var lessThan := filter(xs[1..], ln);
var greaterThan := filter(xs[1..], gn);
var sortedLt := quicksort(lessThan);
var sortedGt := quicksort(greaterThan);
// assert multiset(lessThan) == multiset(sortedLt);
assert multiset(greaterThan) == multiset(sortedGt);
assert forall y :: y in multiset(sortedGt) ==> y in multiset(greaterThan) && y in sortedGt && y in greaterThan;
assert listPartition(lessThan, [xs[0]]);
quicksortPreservesRelations(lessThan, [xs[0]]);
assert listPartition(sortedLt, [xs[0]]);
assert forall x :: x in sortedLt ==> forall y :: y in [xs[0]] ==> x < y ==> x < xs[0];
forall x | x in sortedLt + [xs[0]]
ensures forall y :: y in sortedGt ==> x <= y
{
forall y | y in sortedGt
ensures x <= y
{
assert y in greaterThan;
assert y >= xs[0];
if x in sortedLt {
assert forall z :: z in [xs[0]] ==> x < z ==> x < xs[0];
}else if x in [xs[0]] {
assert x == xs[0];
assert y >= xs[0];
}
}
}
quicksortSorted(lessThan);
quicksortSorted(greaterThan);
assert listPartition(sortedLt + [xs[0]], sortedGt);
// assert sortedRec(sortedLt);
// assert sortedRec(sortedGt);
sortedConcat(sortedLt, [xs[0]]);
assert sortedRec(sortedLt+[xs[0]]);
sortedConcat(sortedLt + [xs[0]], sortedGt);
assert sortedRec((sortedLt + [xs[0]]) + sortedGt);
quicksortDef(xs);
assert quicksort(xs) == sortedLt + [xs[0]] + sortedGt;
assert sortedRec(quicksort(xs));
}
}
}
predicate listPartition(xs: seq<int>, ys: seq<int>)
{
forall x :: x in xs ==> forall y :: y in ys ==> x <= y
}
predicate sortedRec(list: seq<int>) {
if list == [] then true else (forall y :: y in list[1..] ==> list[0] <= y) && sortedRec(list[1..])
}
lemma sortedConcat(xs: seq<int>, ys: seq<int>)
requires sortedRec(xs)
requires sortedRec(ys)
requires listPartition(xs,ys)
ensures sortedRec(xs + ys)
{
if xs == [] || ys == [] {
if xs == [] {
assert xs + ys == ys;
assert sortedRec(xs + ys);
} else if ys == [] {
assert xs + ys == xs;
assert sortedRec(xs+ys);
}
}else{
assert sortedRec([xs[0]]);
assert sortedRec([ys[0]]);
var sum := xs + ys;
assert xs == [xs[0]] + xs[1..];
assert ys == [ys[0]] + ys[1..];
assert xs[0] in xs;
assert forall y :: y in ys ==> xs[0] <= y;
assert forall xz :: xz in xs[1..] ==> xz in xs && forall y :: y in ys ==> xz <= y;
sortedConcat(xs[1..], ys);
assert xs+ys == [xs[0]] + (xs[1..]+ys);
assert sortedRec(xs + ys );
}
}

Rewrite Boolean Expression without Parentheses

I have a black box processing system that accepts boolean expressions but does not support parentheses. I want to input a boolean expression like this:
A && (B || C)
However, when I input it as:
A && B || C
it evaluates expressions as if I had entered:
(A && B) || C
Is there any way to rewrite my expression to get the desired behavior of A && (B || C) without parentheses? Thanks!
There's a relation between precedence but, you can use associative and distributive laws to resolve this.
A && B || A && C
Truth tables match.
Be careful when implementing this. Not all compilers and languages use the same precedence and evaluation order.
Edit: No left-right precedence, sorry.
Use the distributive law and the precedence of && to check if either both A and B is true or both A and C is true.
Solution
A && B || A && C
Distributive Law
x ^ (y v z) = (x ^ y) v (x ^ z)
x && (y || z) = (x && y) || (x && z)
function original(A, B, C) {
return A && (B || C);
}
function mySolution(A, B, C) {
return A && B || C && A;
}
console.log(original(true, true, true) == mySolution(true, true, true));
console.log(original(true, true, false) == mySolution(true, true, false));
console.log(original(true, false, true) == mySolution(true, false, true));
console.log(original(true, false, false) == mySolution(true, false, false));
console.log(original(false, true, true) == mySolution(false, true, true));
console.log(original(false, true, false) == mySolution(false, true, false));
console.log(original(false, false, true) == mySolution(false, false, true));
console.log(original(false, false, false) == mySolution(false, false, false));

Logical operator outside parentheses

I can't figure out what the logical operator "not" (~/!), does in front of a parenthesis.
Here is the task:
I have a = 1, b = 2 and c = 2.
and this if statement:
if (a ~= b | a ~= c) &&~(a ~= b && a ~= c && b ~= c)
What does it mean having a logical operator "not" before the parenthesis (look at the bold ~)?
It plays the role of a logic-negation. It'll return the logical negation of (a ~= b && a ~= c && b ~= c). Meaning if (a ~= b && a ~= c && b ~= c) is true, then ~(a ~= b && a ~= c && b ~= c) is false. and vice versa.
not(A) is equivalent to ~A. The symbol ~ acts like the not(A) logical operator if A is a logical expression. The same symbol ~ placed before = acts like the ne(A) relational operator.
Matlab employs short-circuiting behavior when dealing with logical operators && and ||. Meaning that if we are evaluating e.g expr1 && expr2, then expr2 is not evaluated if expr1 is logical 0 (false). Same way happens when we evaluate e.g expr1 || expr2, expr2 is not evaluated if expr1 is logical 1 (true).
The symbols | and || perform different operations in a MATLAB application. The symbol | is an element-wise OR operator. The short-circuit OR operator is ||. meaning that if we have e.g expr1 || expr2, both expr1 and expr2 are evaluated. Same thing happens with the & element-wise AND operator.
Now, let's have a look at the expression you asked for:
if (a ~= b | a ~= c) &&~(a ~= b && a ~= c && b ~= c)
Knowing that: a = 1, b = 2 and c = 2.
expr1 = (a ~= b | a ~= c)
= (1 ~= 2 | 1 ~= 2)
= 1 (true)
expr1 is true, so Matlab proceeds to evaluate expr2:
expr2 = ~(a ~= b && a ~= c && b ~= c)
= ~(1 ~= 2 && a ~= c && b ~= c)
= ~(1 && 1 ~= 2 && b ~= c)
= ~(1 && 1 && 2 ~= 2)
= ~(1 && 1 && 0)
= ~(0)
= 1 (true)
So the final result of expr1 && expr2 is 1 (true).
Hope it's useful!
I'll try to complement the Academia's answer - the evaluation order is important and every logical operator has it's precedence. In Matlab the negation operator '~' not() has higher precedence than other logical operators. In this case the expression a ~= b && a ~= c && b ~= c will be evaluated before the negation operator as a whole because it was placed inside the parenthesis. This expression can be read as "all three variables have different values". By placing it inside the parenthesis and negating it, you get "not all three variables have different values". Without the parenthesis you'd get not(a) ~= b && a ~= c && b ~= c. Note also that comparison operators have higher precedence than &&.
Hope it helps.

Writing (A && C) || (B && C) conditional shorter

(E.G. In Perl) When either condition A or condition B have the same consequence
if (A){
# Consequence X
}elsif (B){
# Consequence X
}
we can write
if ( A || B ) {
# Consequence X
}
How about we have the following condition: Either when A and C are true, or B and C are true, consequence C follows.
This can be written very long:
if ( A && C){
# Consequence X
} elsif (B && C ){
# consequence X
}
My question is, is there any way to write this shorter?
Something like this:
if ( (A && C) || (B && C) )
is syntactically ok ???
Yes.
if ( A && C){
# Consequence X
} elsif (B && C ){
# consequence X
}
is the same as:
if ( (A && C) || (B && C) ){
#Consequence X
}
And this avoids evaluating C twice:
if ( (A || B) && C){
#Consequence X
}
BTW, this is more like a logical question, the logic here isn't limited to Perl.
Try the following:
if (C && (A || B)) {
}

Confusing Boolean Expression

Given these values for the boolean variables x, y, and z:
x = true
y = false
z = true
Why does the following logical expression evaluate to true?
(x || !y) && (!x || z)
Substitute in the values of x, y, and z:
(true || !false) && (!true || true)
Flip the negated values:
(true || true) && (false || true)
Replace the ORed statements (if one side is true, the whole statement is true):
true && true
Replace the ANDed statement (if both sides are true, the whole statement is true):
true
True or False is always True. true || false
True and True is always True. true && true
X is true in the first grouping causing the first grouping to be true. Z is true in the second grouping causing the second grouping to be true. Therefore group 1 and group 2 are true.
(x || !y) && (!x || z)
= (T || !F) && (!T || T) <-- plug in x = T, y = F, z = T
= (T || T) && (F || T) <-- !F = T, !T = F
= T && T <- T || T = T, F || T = T
= T <- T && T = T
Actually, please tell us what's so confusing; I am slightly confused that you find it confusing at all.