We describe here some fundamental laws of boolean algebra, called “monotone laws”. We then tackle some laws specific to Boolean algebra.
module Logic.laws where
open import Lang.dataStructures using (Bool; true; false)
open import Types.product using (_×_; _,_)
open import Logic.logicBasics using (¬; not; xor; ⟂; ⊤; singleton)
open import Logic.equality using (Equiv; _≡_; Rel; Equivalence)
Monotone laws are ones in which the inputs and outputs change monotonically, or the output either remains unchanged on changing inputs or changes in the same way as the input.
We first need to define operations in an abstract way before we proceed with laws on these operations. We used types to define families (types) of operations:
A unary operation can be defined as:
: Set → Set
∘ = A → A ∘ A
A binary operation ★ A
can be defined as:
_ : Set → Set
★= A → A → A ★ A
Here *_
constructs a type family of operations that operate on given type A
.
For proving these laws we need an instance of the equivalence relation ==
.
module BooleanLaws {A : Set} (eq : Equivalence A) where
module Eq₁ = Equivalence eq
open Eq₁
For an operation ★
,
\[ x ★ (y ★ z) ≡ (x ★ y) ★ z \]
: ★ A → Set
associativity _★_ = (x y z : A)
associativity → (x ★ (y ★ z))
((x ★ y) ★ z) ==
\[ x ★ y ≡ y ★ x \]
: ★ A → Set
commutativity _★_ = (x y : A)
commutativity → (x ★ y)
(y ★ x) ==
\[ ( x ★ y ) ★ z ≡ x ★ y × y ★ z \]
_distributesOverˡ_ : ★ A → ★ A → Set _
_*_ distributesOverˡ _+_ =
∀ x y z → (x * (y + z)) == ((x * y) + (x * z))
_distributesOverʳ_ : ★ A → ★ A → Set _
_*_ distributesOverʳ _+_ =
∀ x y z → ((y + z) * x) == ((y * x) + (z * x))
_distributesOver_ : ★ A → ★ A → Set _
= (* distributesOverˡ +) × (* distributesOverʳ +) * distributesOver +
\[ x ★ id_{★} ≡ x \]
These form the major laws of boolean algebra. There exists a bunch of others that we’ll also see here. Note that for non-commutative systems of algebra, identity can exist in two forms: right and left, similarly for directional operations like distributivity, inverses, etc.
: A → ★ A → Set
identityₗ _★_ = (y : A)
identityₗ x → (x ★ y)
== x
: A → ★ A → Set
identityᵣ _★_ = (y : A)
identityᵣ x → (y ★ x)
== x
: A → ★ A → Set
identity = (identityₗ x ★) × (identityᵣ x ★) identity x ★
\[ x ★ id ≡ x \]
: A → ★ A → Set _
leftZero _★_ = ∀ x → (z ★ x) == z
leftZero z
: A → ★ A → Set _
rightZero _★_ = ∀ x → (x ★ z) == z
rightZero z
: A → ★ A → Set _
zero = leftZero z ★ × rightZero z ★ zero z ★
Idempotence is a more specific law of boolean algebra:
\[ x ∧ x ≡ x \]
_idempotentOn_ : ★ A → A → Set _
_★_ idempotentOn x = (x ★ x) == x
: ★ A → Set _
idempotent = ∀ x → ★ idempotentOn x idempotent ★
Another pair of reductive laws that apply only in boolean algebra:
\[ x ∧ (x ∨ y) ≡ x x ∨ (x ∧ y) ≡ x \]
_absorbs_ : ★ A → ★ A → Set _
_∙_ absorbs _◌_ = ∀ x y → (x ∙ (x ◌ y)) == x
: ★ A → ★ A → Set _
absorptive = (∙ absorbs ◌) × (◌ absorbs ∙) absorptive ∙ ◌
The logical AND
and OR
operators satisfy the above laws:
open import Logic.logicBasics
open import Types.operations _==_
∨-assoc : associativity ∨ ∨-assoc true y z = refl ∨-assoc false y z = refl
∨-comm : Commutative ∨ ∨-comm true true = refl ∨-comm true false = refl ∨-comm false true = refl ∨-comm false false = refl
∨-identityˡ : LeftIdentity false ∨ ∨-identityˡ _ = refl
∨-identityʳ : RightIdentity false ∨ ∨-identityʳ false = refl ∨-identityʳ true = refl
∨-identity : Identity false ∨ ∨-identity = ∨-identityˡ , ∨-identityʳ
∨-zeroˡ : LeftZero true ∨ ∨-zeroˡ _ = refl
∨-zeroʳ : RightZero true ∨ ∨-zeroʳ false = refl ∨-zeroʳ true = refl
∨-zero : Zero true ∨ ∨-zero = ∨-zeroˡ , ∨-zeroʳ
∨-inverseˡ : LeftInverse true not ∨ ∨-inverseˡ false = refl ∨-inverseˡ true = refl
∨-inverseʳ : RightInverse true not ∨ ∨-inverseʳ x = ∨-comm x (not x) ⟨ trans ⟩ ∨-inverseˡ x
∨-inverse : Inverse true not ∨ ∨-inverse = ∨-inverseˡ , ∨-inverseʳ