How to efficiently reduce this logic sentence? - boolean-logic

I have a sentence that describes a circuit, like this:
I x (Q1 x Q0 + not Q1 x not Q0) + not I x (not Q1 x Q0 + Q1 x not Q0)
I have translated it like this:
I and ((Q1 and Q0) or (!Q1 and !Q0)) or !I and ((!Q1 and Q0) or (Q1 and !Q0)) ->
I and ((Q1 and Q0) or !(Q1 or Q0)) or !I and ((!Q1 and Q0) or (Q1 and !Q0)) ->
I and (!(Q1 xor Q0)) or !I and (Q1 xor Q0)
but I get stuck at this point, is there an easy way to make it even more compact or I'll have to solve the bit-by-bit table?

Reduction
1. I and ((Q1 and Q0) or (!Q1 and !Q0)) or !I and ((!Q1 and Q0) or (Q1 and !Q0))
≡
2. I and ((Q1 and Q0) or !(Q1 or Q0)) or !I and ((!Q1 and Q0) or (Q1 and !Q0))
≡
3. I and !(!(Q1 and Q1) and (Q1 or Q0)) or !I and ((!Q1 and Q0) or (Q1 and !Q0))
≡
4. I and !(Q0 xor Q1) or !I and (Q0 xor Q1)
≡
5. I xor (Q0 xor Q1)
≡
6. I xor Q0 xor Q1
Reasons
1 ≡ 2: De Morgan
2 ≡ 3: De Morgan
3 ≡ 4: Def of xor
4 ≡ 5: Def of xor
5 ≡ 6: Associativity of xor

Related

Agda rewrite does not change goal in _*_ commutativity proof

SOLVED: I have a solution after following white-wolf's advice. If you are interested in my solution feel free to message me.
I am trying to write a proof in Agda for commutativity for multiplication:
lem3 : (x y : ℕ) → (x * y) ≡ (y * x)
lem3 0 y rewrite pr3a y = refl
lem3 (suc x) y rewrite lem3 x y | pr3b x y = refl
where we have:
pr3a : (x : ℕ) → (x * 0) ≡ 0
pr3a 0 = refl
pr3a (suc x) with (x * 0) | pr3a x
... | .0 | refl = refl
pr3b : (x y : ℕ) → y + y * x ≡ y * suc x
pr3b 0 0 = refl
pr3b 0 (suc y) rewrite pr3b 0 y = refl
pr3b (suc x) y = {!!}
I am having trouble filing this final goal. The expected type is y + y * suc x ≡ y * suc (suc x), and I had expected that using rewrite would give me y * suc (suc x) ≡ y * suc (suc x) as a goal. However:
pr3b (suc x) y rewrite pr3b x y = {!!}
expects the same goal as before: y + y * suc x ≡ y * suc (suc x).
It is my understanding that rewrite would effectively substitute the RHS into the LHS for x = x, giving y * suc x ≡ y * suc x, and then use x = suc x to give y * suc (suc x) ≡ y * suc (suc x). Am I mis-understanding how rewrite works or have I made some other error?
Your goal is y + y * suc x ≡ y * suc (suc x). Your induction hypothesis is y + y * x ≡ y * suc x. I can check that by putting pr3b x y inside the goal and typing C-c C-.
Goal: y + y * suc x ≡ y * suc (suc x)
Have: y + y * x ≡ y * suc x
This means that with a rewrite you should be able to replace y * suc x with y * x. However, you see that the two sides are switched, so you have to rewrite with symmetry like so
pr3b : (x y : ℕ) → y + y * x ≡ y * suc x
pr3b 0 0 = refl
pr3b 0 (suc y) rewrite pr3b 0 y = refl
pr3b (suc x) y rewrite sym $ pr3b x y = {!!}
This promotes the goal to y + (y + y * x) ≡ y * suc (suc x). This particular proof requires associativity and commutativity of addition to be completed.
Edit
I think you should try to prove this by induction on y instead of x.

Build x XOR (y XOR z) with NAND port

I need to make x xor(y xor z) with only NAND ports.
Notation: NOT(y) = ~y.
My first steps were to identify the output of that stuff, so:
x xor(y xor z) = x xor (y~z + ~yz) = ~x(y~z + ~yz) + x~(y~z + ~yz) = ~xy~z + ~x~yz + x~y~z + xyz
So the final output of my NAND construction should be: ~xy~z + ~x~yz + x~y~z + xyz
I tried to attack this by first making y XOR z:
y XOR z = y~z + ~yz = NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))]
Since
NAND(y,NAND(z,z)) = NOT(y * NOT(z*z)) = NOT(y) + z which I'll call g1 and
NAND(z,NAND(y,y)) = NOT(z * NOT(y*y)) = NOT(z) + y as g2
then the outside NAND[g1,g2] = z~y + y~z.
So now I have a XOR with just NANDs and doing the x xor (y xor z) should be just matter of treating (y xor z) as a single variable which gives me:
x xor (y xor z) = NAND[NAND(x,NAND(NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))],NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))])),NAND(NAND[NAND(y,NAND(z,z)),NAND(z,NAND(y,y))],NAND(x,x))]
Am I correct? I feel like the xor could be made in a more efficient way than using 5 NANDs ports.
Thanks guys.
Your final expression is correct.
The 20 NAND gates can be reduced to eight:
This circuit makes use of XOR(x,y,z) = XOR(XOR(x,y),z). It is a combination of two two-input XOR gates, each of them composed of four NAND gates.

Boolean Logic and Expression

Simplify the expression below using boolean algebra theorem.
A XOR B XOR A XOR ~ B
outline each step and indicate which law you're using in each step please.
Too simple, isn't it?
A⊕B⊕A⊕~B => A⊕A⊕B⊕~B => (A⊕A)⊕(B⊕~B)
A⊕A=0 (1⊕1=0, 0⊕0=0)
B⊕~B=1 (1⊕0=1, 0⊕1=1)
1⊕0=1
It refers to basics of this operation.
Maybe you were hoping for something like this...
A XOR B XOR A XOR ~ B
(A XOR (B XOR (A XOR (~B)))) Parenthesized
(A XOR ((A XOR (~B)) XOR B)) Commutative
((A XOR (A XOR (~B))) XOR B) Associative
(((A XOR A) XOR (~B)) XOR B) Associative
((0 XOR (~B)) XOR B) A XOR A = 0 for all A; not sure of name
(~B XOR B) 0 XOR A = A for all A; not sure of name
1 A XOR ~A = 1 for all A; not sure of name
Not sure what a few of those properties are named... the definition of XOR? These may be properties that are proven from simpler notions. In any event, they are neither commutativity nor associativity. Anyway, hope this helped.

Agda Theorems for Powers

I'm trying to prove the following:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc x} = {!!}
I'm brand new to Adga and don't even really know where to start. Any suggestions or guidance? Obviously very easy to prove on paper but I am unsure of what to tell Agda.
I defined my pow function as follows:
_pow_ : ℕ → ℕ → ℕ
x pow zero = 1
x pow (suc zero) = x
x pow (suc y) = x * (x pow y)
When you pattern match on n in 1-pow and find out it is zero, Agda will take a look at the definition of _pow_ and check if one of the function clauses matches. The first one does, so it will apply that definition and 1 pow zero becomes 1. 1 is obviously equal to 1, so refl will work for the proof.
What about the case when n was suc x? Here's the problem: Agda cannot commit to the second clause (because x could be zero) nor the third clause (because x could be suc y for some y). So you have to go one step further to make sure Agda applies the definition of _pow_:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc zero} = {!!}
1-pow {suc (suc x)} = {!!}
Let's check out what is the type of the first hole. Agda tells us it is 1 ≡ 1, so we can use refl again. The last one is a bit trickier, we are supposed to produce something of type 1 * 1 pow (suc x) ≡ 1. Assuming your are using the standard definition of _*_ (i.e. recursion on the left argument and repeated addition on the left side, such as the one in the standard library), this should reduce to 1 pow (suc x) + 0 ≡ 1. Induction hypothesis (that is, 1-pow applied to suc x) tells us that 1 pow (suc x) ≡ 1.
So we are almost there, but we don't know that n + 0 ≡ n (that's because addition is defined by recursion on the left argument, so we can't simplify this expression). One option is to prove this fact, which I leave as an exercise. Here's a hint, though: you might find this function useful.
cong : ∀ {a b} {A : Set a} {B : Set b}
(f : A → B) {x y} → x ≡ y → f x ≡ f y
cong f refl = refl
It's already part of the Relation.Binary.PropositionalEquality module, so you don't need to define it yourself.
So, to recap: we know that n + 0 ≡ n and 1 pow (suc x) ≡ 1 and we need 1 pow (suc x) + 0 ≡ 1. These two facts fit together quite nicely - the equality is transitive, so we should be able to merge 1 pow (suc x) + 0 ≡ 1 pow (suc x) and 1 pow (suc x) ≡ 1 into one proof and indeed, this is the case:
1-pow {suc (suc x)} = trans (+0 (1 pow suc x)) (1-pow {suc x})
And that's it!
Let me mention few other approaches.
The whole proof could also be done using a proof that 1 * x ≡ x, though this is hardly different from what we did before.
You could simplify _pow_ to:
_pow_ : ℕ → ℕ → ℕ
x pow zero = 1
x pow (suc y) = x * (x pow y)
This is slightly more convenient to work with. The proof would be changed accordingly (i.e. it wouldn't have the second clause of the original proof).
And lastly, you could do this:
1-pow : ∀ {n : ℕ} → 1 pow n ≡ 1
1-pow {zero} = refl
1-pow {suc zero} = refl
1-pow {suc (suc x)} = cong (λ x → x + 0) (1-pow {suc x})
Try to figure out why that works! If you have any problems, let me know in the comments and I'll help you.

Proof on less than and less or equal on nat

Assuming the following definitions (the first two are taken from http://www.cis.upenn.edu/~bcpierce/sf/Basics.html):
Fixpoint beq_nat (n m : nat) : bool :=
match n with
| O => match m with
| O => true
| S m' => false
end
| S n' => match m with
| O => false
| S m' => beq_nat n' m'
end
end.
Fixpoint ble_nat (n m : nat) : bool :=
match n with
| O => true
| S n' =>
match m with
| O => false
| S m' => ble_nat n' m'
end
end.
Definition blt_nat (n m : nat) : bool :=
if andb (ble_nat n m) (negb (beq_nat n m)) then true else false.
I would like to prove the following:
Lemma blt_nat_flip0 : forall (x y : nat),
blt_nat x y = false -> ble_nat y x = true.
Lemma blt_nat_flip : forall (x y : nat),
blt_nat x y = false -> beq_nat x y = false -> blt_nat y x = true.
The furthest I was able to get to is to prove blt_nat_flip assuming blt_nat_flip0. I spent a lot of time and I am almost there but overall it seems more complex than it should be. Anybody has a better idea on how to prove the two lemmas?
Here is my attempt so far:
Lemma beq_nat_symmetric : forall (x y : nat),
beq_nat x y = beq_nat y x.
Proof.
intros x. induction x.
intros y. simpl. destruct y.
reflexivity. reflexivity.
intros y. simpl. destruct y.
reflexivity.
simpl. apply IHx.
Qed.
Lemma and_negb_false : forall (b1 b2 : bool),
b2 = false -> andb b1 (negb b2) = b1.
Proof.
intros. rewrite -> H. unfold negb. destruct b1.
simpl. reflexivity.
simpl. reflexivity.
Qed.
Lemma blt_nat_flip0 : forall (x y : nat),
blt_nat x y = false -> ble_nat y x = true.
Proof.
intros x.
induction x.
intros. destruct y.
simpl. reflexivity.
simpl. inversion H.
intros. destruct y. simpl. reflexivity.
simpl. rewrite -> IHx. reflexivity.
(* I am giving up for now at this point ... *)
Admitted.
Lemma blt_nat_flip : forall (x y : nat),
blt_nat x y = false -> beq_nat x y = false ->
blt_nat y x = true.
Proof.
intros.
unfold blt_nat.
rewrite -> beq_nat_symmetric. rewrite -> H0.
rewrite -> and_negb_false.
replace (ble_nat y x) with true.
reflexivity.
rewrite -> blt_nat_flip0. reflexivity. apply H. reflexivity.
Qed.
coq seems to have trouble doing an inversion on H in the last case of your induction, but if you unfold blt_nat before, it seems to work as intended.