Guidance on very shallow embedding VHDL in AGDA - functional-programming

for my project in Programming Languages I am doing a very shallow and simple embedding VHDL digital circuits in agda. The aim is to write the syntax, static semantics, dynamic semantics and then write some proofs to show our understanding of the material. Up till now I have written the following code:
data Ckt : Set where
var : String → Ckt
bool : Bool → Ckt
empty : Ckt
gate : String → ℕ → ℕ → Ckt -- name in out
series : String → Ckt → Ckt → Ckt -- name ckt1 ckt2
parallel : String → Ckt → Ckt → Ckt --name ckt1 ckt2
And : Ckt
And = gate "And" 2 1
data Ctxt : Set where
□ : Ctxt
_,_ : (String × ℕ × ℕ) → Ctxt → Ctxt
_≈_ : Ctxt → Ctxt → Set
□ ≈ □ = ⊤
□ ≈ (_ , _) = ⊥
(_ , _) ≈ □ = ⊥
((s₁ , (in₁ , out₂)) , Γ₁) ≈ ((s₂ , (in₃ , out₄)) , Γ₂) = True (s₁ ≟ s₂) × in₁ ≡ in₃ × out₂ ≡ out₄ × Γ₁ ≈ Γ₂
--static Semantics
data _⊢_ : (Γ : Ctxt) → (e : Ckt) → Set where
VarT : ∀ {Γ s τ} → ((s , τ) ∈ Γ) → Γ ⊢ var s
BoolT : ∀ {Γ b} → Γ ⊢ bool b
EmptyT : ∀ {Γ} → Γ ⊢ empty
GateT : ∀ {Γ s i o} → (s , (i , o)) ∈ Γ → Γ ⊢ gate s i o
SeriesT : ∀ {Γ s c₁ c₂} → Γ ⊢ c₁ → Γ ⊢ c₂ → Γ ⊢ series s c₁ c₂
ParallelT : ∀ {Γ s c₁ c₂} → Γ ⊢ c₁ → Γ ⊢ c₂ → Γ ⊢ parallel s c₁ c₂
What I am stuck at is how can I convert this program so as to carry out the program execution i-e I don't know how to start writing the dynamic semantics. Also, if there is any way to improve the syntax or statics of my current program then please let me know.

Related

Porting (simply-typed) lambda calculus term saturation proof from Coq to Agda

I'm trying to port msubst_R from Software Foundations, vol. 2 to Agda. I'm trying to avoid a lot of busywork by using a typed representation for terms. Below is my port of everything up to msubst_R; I think everything is fine below but it's needed for the problematic part.
open import Data.Nat
open import Relation.Binary.PropositionalEquality hiding (subst)
open import Data.Empty
open import Data.Unit
open import Relation.Binary
open import Data.Star
open import Level renaming (zero to lzero)
open import Data.Product
open import Function.Equivalence hiding (sym)
open import Function.Equality using (_⟨$⟩_)
data Ty : Set where
fun : Ty → Ty → Ty
infixl 21 _▷_
data Ctx : Set where
[] : Ctx
_▷_ : Ctx → Ty → Ctx
data Var (t : Ty) : Ctx → Set where
vz : ∀ {Γ} → Var t (Γ ▷ t)
vs : ∀ {Γ u} → Var t Γ → Var t (Γ ▷ u)
data _⊆_ : Ctx → Ctx → Set where
done : ∀ {Δ} → [] ⊆ Δ
keep : ∀ {Γ Δ a} → Γ ⊆ Δ → Γ ▷ a ⊆ Δ ▷ a
drop : ∀ {Γ Δ a} → Γ ⊆ Δ → Γ ⊆ Δ ▷ a
⊆-refl : ∀ {Γ} → Γ ⊆ Γ
⊆-refl {[]} = done
⊆-refl {Γ ▷ _} = keep ⊆-refl
data Tm (Γ : Ctx) : Ty → Set where
var : ∀ {t} → Var t Γ → Tm Γ t
lam : ∀ t {u} → (e : Tm (Γ ▷ t) u) → Tm Γ (fun t u)
app : ∀ {u t} → (f : Tm Γ (fun u t)) → (e : Tm Γ u) → Tm Γ t
wk-var : ∀ {Γ Δ t} → Γ ⊆ Δ → Var t Γ → Var t Δ
wk-var done ()
wk-var (keep Γ⊆Δ) vz = vz
wk-var (keep Γ⊆Δ) (vs v) = vs (wk-var Γ⊆Δ v)
wk-var (drop Γ⊆Δ) v = vs (wk-var Γ⊆Δ v)
wk : ∀ {Γ Δ t} → Γ ⊆ Δ → Tm Γ t → Tm Δ t
wk Γ⊆Δ (var v) = var (wk-var Γ⊆Δ v)
wk Γ⊆Δ (lam t e) = lam t (wk (keep Γ⊆Δ) e)
wk Γ⊆Δ (app f e) = app (wk Γ⊆Δ f) (wk Γ⊆Δ e)
data _⊢⋆_ (Γ : Ctx) : Ctx → Set where
[] : Γ ⊢⋆ []
_▷_ : ∀ {Δ t} → Γ ⊢⋆ Δ → Tm Γ t → Γ ⊢⋆ Δ ▷ t
⊢⋆-wk : ∀ {Γ Δ} t → Γ ⊢⋆ Δ → Γ ▷ t ⊢⋆ Δ
⊢⋆-wk t [] = []
⊢⋆-wk t (σ ▷ e) = (⊢⋆-wk t σ) ▷ wk (drop ⊆-refl) e
⊢⋆-mono : ∀ {Γ Δ t} → Γ ⊢⋆ Δ → Γ ▷ t ⊢⋆ Δ ▷ t
⊢⋆-mono σ = ⊢⋆-wk _ σ ▷ var vz
⊢⋆-refl : ∀ {Γ} → Γ ⊢⋆ Γ
⊢⋆-refl {[]} = []
⊢⋆-refl {Γ ▷ _} = ⊢⋆-mono ⊢⋆-refl
subst-var : ∀ {Γ Δ t} → Γ ⊢⋆ Δ → Var t Δ → Tm Γ t
subst-var [] ()
subst-var (σ ▷ x) vz = x
subst-var (σ ▷ x) (vs v) = subst-var σ v
subst : ∀ {Γ Δ t} → Γ ⊢⋆ Δ → Tm Δ t → Tm Γ t
subst σ (var x) = subst-var σ x
subst σ (lam t e) = lam t (subst (⊢⋆-mono σ) e)
subst σ (app f e) = app (subst σ f) (subst σ e)
data Value : {Γ : Ctx} → {t : Ty} → Tm Γ t → Set where
lam : ∀ {Γ t} → ∀ u (e : Tm _ t) → Value {Γ} (lam u e)
data _==>_ {Γ} : ∀ {t} → Rel (Tm Γ t) lzero where
app-lam : ∀ {t u} (f : Tm _ t) {v : Tm _ u} → Value v → app (lam u f) v ==> subst (⊢⋆-refl ▷ v) f
appˡ : ∀ {t u} {f f′ : Tm Γ (fun u t)} → f ==> f′ → (e : Tm Γ u) → app f e ==> app f′ e
appʳ : ∀ {t u} {f} → Value {Γ} {fun u t} f → ∀ {e e′ : Tm Γ u} → e ==> e′ → app f e ==> app f e′
_==>*_ : ∀ {Γ t} → Rel (Tm Γ t) _
_==>*_ = Star _==>_
NF : ∀ {a b} {A : Set a} → Rel A b → A → Set _
NF step x = ∄ (step x)
value⇒normal : ∀ {Γ t e} → Value {Γ} {t} e → NF _==>_ e
value⇒normal (lam t e) (_ , ())
Deterministic : ∀ {a b} {A : Set a} → Rel A b → Set _
Deterministic step = ∀ {x y y′} → step x y → step x y′ → y ≡ y′
deterministic : ∀ {Γ t} → Deterministic (_==>_ {Γ} {t})
deterministic (app-lam f _) (app-lam ._ _) = refl
deterministic (app-lam f v) (appˡ () _)
deterministic (app-lam f v) (appʳ f′ e) = ⊥-elim (value⇒normal v (, e))
deterministic (appˡ () e) (app-lam f v)
deterministic (appˡ f e) (appˡ f′ ._) = cong _ (deterministic f f′)
deterministic (appˡ f e) (appʳ f′ _) = ⊥-elim (value⇒normal f′ (, f))
deterministic (appʳ f e) (app-lam f′ v) = ⊥-elim (value⇒normal v (, e))
deterministic (appʳ f e) (appˡ f′ _) = ⊥-elim (value⇒normal f (, f′))
deterministic (appʳ f e) (appʳ f′ e′) = cong _ (deterministic e e′)
Halts : ∀ {Γ t} → Tm Γ t → Set
Halts e = ∃ λ e′ → e ==>* e′ × Value e′
value⇒halts : ∀ {Γ t e} → Value {Γ} {t} e → Halts e
value⇒halts {e = e} v = e , ε , v
-- -- This would not be strictly positive!
-- data Saturated : ∀ {Γ t} → Tm Γ t → Set where
-- fun : ∀ {t u} {f : Tm [] (fun t u)} → Halts f → (∀ {e} → Saturated e → Saturated (app f e)) → Saturated f
mutual
Saturated : ∀ {t} → Tm [] t → Set
Saturated e = Halts e × Saturated′ _ e
Saturated′ : ∀ t → Tm [] t → Set
Saturated′ (fun t u) f = ∀ {e} → Saturated e → Saturated (app f e)
saturated⇒halts : ∀ {t e} → Saturated {t} e → Halts e
saturated⇒halts = proj₁
step‿preserves‿halting : ∀ {Γ t} {e e′ : Tm Γ t} → e ==> e′ → Halts e ⇔ Halts e′
step‿preserves‿halting {e = e} {e′ = e′} step = equivalence fwd bwd
where
fwd : Halts e → Halts e′
fwd (e″ , ε , v) = ⊥-elim (value⇒normal v (, step))
fwd (e″ , s ◅ steps , v) rewrite deterministic step s = e″ , steps , v
bwd : Halts e′ → Halts e
bwd (e″ , steps , v) = e″ , step ◅ steps , v
step‿preserves‿saturated : ∀ {t} {e e′ : Tm _ t} → e ==> e′ → Saturated e ⇔ Saturated e′
step‿preserves‿saturated step = equivalence (fwd step) (bwd step)
where
fwd : ∀ {t} {e e′ : Tm _ t} → e ==> e′ → Saturated e → Saturated e′
fwd {fun s t} step (halts , sat) = Equivalence.to (step‿preserves‿halting step) ⟨$⟩ halts , λ e → fwd (appˡ step _) (sat e)
bwd : ∀ {t} {e e′ : Tm _ t} → e ==> e′ → Saturated e′ → Saturated e
bwd {fun s t} step (halts , sat) = Equivalence.from (step‿preserves‿halting step) ⟨$⟩ halts , λ e → bwd (appˡ step _) (sat e)
step*‿preserves‿saturated : ∀ {t} {e e′ : Tm _ t} → e ==>* e′ → Saturated e ⇔ Saturated e′
step*‿preserves‿saturated ε = id
step*‿preserves‿saturated (step ◅ steps) = step*‿preserves‿saturated steps ∘ step‿preserves‿saturated step
Note that I have removed the bool and pair types since they are not necessary to show my problem.
The problem, then, is with msubst_R (which I call saturate below):
data Instantiation : ∀ {Γ} → [] ⊢⋆ Γ → Set where
[] : Instantiation []
_▷_ : ∀ {Γ t σ} → Instantiation {Γ} σ → ∀ {e} → Value {_} {t} e × Saturated e → Instantiation (σ ▷ e)
saturate-var : ∀ {Γ σ} → Instantiation σ → ∀ {t} (x : Var t Γ) → Saturated (subst-var σ x)
saturate-var (_ ▷ (_ , sat)) vz = sat
saturate-var (env ▷ _) (vs x) = saturate-var env x
app-lam* : ∀ {Γ t} {e e′ : Tm Γ t} → e ==>* e′ → Value e′ → ∀ {u} (f : Tm _ u) → app (lam t f) e ==>* subst (⊢⋆-refl ▷ e′) f
app-lam* steps v f = gmap _ (appʳ (lam _ _)) steps ◅◅ app-lam f v ◅ ε
saturate : ∀ {Γ σ} → Instantiation σ → ∀ {t} → (e : Tm Γ t) → Saturated (subst σ e)
saturate env (var x) = saturate-var env x
saturate env (lam u f) = value⇒halts (lam u _) , sat-f
where
f′ = subst _ f
sat-f : ∀ {e : Tm _ u} → Saturated e → Saturated (app (lam u f′) e)
sat-f sat#((e′ , steps , v) , _) =
Equivalence.from (step*‿preserves‿saturated (app-lam* steps v f′)) ⟨$⟩ saturate ([] ▷ (v , Equivalence.to (step*‿preserves‿saturated steps) ⟨$⟩ sat)) f′
saturate env (app f e) with saturate env f | saturate env e
saturate env (app f e) | _ , sat-f | sat-e = sat-f sat-e
saturate doesn't pass the termination checker, because in the lam case, sat-f recurses into saturate on f′, which isn't necessarily smaller than lam u f; and [] ▷ e′ is also not necessarily smaller than σ.
Another way of looking at why saturate doesn't terminate is to look at saturate env (app f e). Here, recursing into f and (potentially) e will grow t, even though all the other cases either leave t the same and shrink the term, or shrink t. So if saturate env (app f e) didn't recurse into saturate env f and saturate env e, the recursion in saturate env (lam u f) would not be problematic in itself.
However, I think my code does the right thing for the app f e case (since that's the whole point of lugging around the parametric saturation proof for function types), so it should be the lam u f case where I need a tricky way in which f′ is smaller than lam u f.
What am I missing?
Assuming an additional Bool base type, Saturated would look nicer the following way, since it would not demand a Halts for the fun argument which already follows from Saturated.
Saturated : ∀ {A} → Tm [] A → Set
Saturated {fun A B} t = Halts t × (∀ {u} → Saturated u → Saturated (app t u))
Saturated {Bool} t = Halts t
Then, in saturate you can only recurse on f in the lam case. There is no other way to make it structural. The job is to massage the hypothesis from f into the right shape using the reduction/saturation lemmas.
open import Function using (case_of_)
saturate : ∀ {Γ σ} → Instantiation σ → ∀ {t} → (e : Tm Γ t) → Saturated (subst σ e)
saturate env (var x) = saturate-var env x
saturate env (lam u f) =
value⇒halts (lam _ (subst _ f)) ,
λ {u} usat →
case (saturated⇒halts usat) of λ {(u' , u==>*u' , u'val) →
let hyp = saturate (env ▷ (u'val , Equivalence.to (step*‿preserves‿saturated u==>*u') ⟨$⟩ usat)) f
in {!!}} -- fill this with grunt work
saturate env (app f e) with saturate env f | saturate env e
saturate env (app f e) | _ , sat-f | sat-e = sat-f sat-e

Formulating proof for assignment

Consider the following code from an assignment. The aim here is to prove that transactions on accounts are commutative. From what i understand is there are two accounts e1{cash 10} and e2{cash 20}. So if i make a transaction on e1 by giving 10 and then on e2 by giving 10 then and then i do it in the reverse order then at the end the account state is the same. For this i have to prove the the account states in between are equivalent.
like the account state [e1{10} e2{20}]->[e1{0} e2{20}]->[e1{0} e2{10}] and [e1{10} e2{20}]->[e1{10} e2{10}]->[e1{0} e2{10}] i-e the states in between lead to the same state. Is my thinking correct? How do i formulate this? This looked trivial at first glance to me but is not that easy.
module Acc where
open import Data.Nat hiding (_≟_; _+_; _≤_)
open import Data.Integer hiding (_≟_; suc)
open import Data.String
open import Data.Product
open import Relation.Nullary
open import Relation.Nullary.Decidable
open import Relation.Binary.PropositionalEquality
-- Trivial example of an EDSL inspired by
-- http://www.lpenz.org/articles/hedsl-sharedexpenses/
-- We have n people who go on a trip
-- they pay for things
-- they give each other money
-- at the end we want to have the balance on each account
-- Syntax
infixr 10 _•_
infixr 10 _and_
infix 20 _⇒_
data Person : Set where
P : String → Person
data Exp : Set where
_⇒_ : Person → ℕ → Exp
_[_]⇒_ : Person → ℕ → Person → Exp
_and_ : Exp → Exp → Exp
data Accounts : Set where
□ : Accounts
_,_ : (String × ℤ) → Accounts → Accounts
data _∈ᵣ_ : (String × ℤ) → Accounts → Set where
hereᵣ : ∀ {ρ s v} → (s , v) ∈ᵣ ((s , v) , ρ)
skipᵣ : ∀ {ρ s v s' v'} →
{α : False (s ≟ s')} → (s , v) ∈ᵣ ρ → (s , v) ∈ᵣ ((s' , v') , ρ)
update : Accounts → String → ℤ → Accounts
update □ s amount = (s , amount) , □
update ((s₁ , amount₁) , accounts) s₂ amount₂ with (s₁ ≟ s₂)
... | yes _ = (s₁ , (amount₁ + amount₂)) , accounts
... | no _ = (s₁ , amount₁) , update accounts s₂ amount₂
data account : Exp → Accounts → Accounts → Set where
spend : ∀ {s n σ} → account (P s ⇒ (suc n)) σ (update σ s -[1+ n ])
give : ∀ {s₁ s₂ n σ} → account (P s₁ [ suc n ]⇒ P s₂) σ
(update (update σ s₁ -[1+ n ]) s₂ (+ (suc n)))
_•_ : ∀ {e₁ e₂ σ₁ σ₂ σ₃} →
account e₁ σ₁ σ₂ → account e₂ σ₂ σ₃ → account (e₁ and e₂) σ₁ σ₃
andComm : ∀ {σ σ' σ'' e₁ e₂} → account (e₁ and e₂) σ σ' →
account (e₂ and e₁) σ σ'' → σ' ≡ σ''
andComm (a₁ • a) (b • b₁) = {!!}

Handling substitutions of mutually defined types with Agda's standard library's Data.Fin.Substitution

I'm trying to encode a call-by-push-value lambda calculus with isorecursive types in Agda. So I mutually define value types and computation types with up to n free value type variables (I only need to substitute value types for the isorecursive types) as follows (this is just a fragment).
data VType (n : ℕ) : Set where
vunit : VType n -- unit type
var : Fin n → VType n -- type variable
u : CType n → VType n -- thunk
μ : VType (1 + n) → VType n -- isorecursive type
data CType (n : ℕ) : Set where
_⇒_ : VType n → CType n → CType n -- lambda abstraction
f : VType n → CType n -- a value-producer
In the style here, I want to be able to do substitutions like
example : CType 0
example = f (var (# 0)) C[/ vunit ]
where
_C[/_] : ∀ {n} → CType (1 + n) → VType n → CType n
ct [/ vt ] = ?
post-substitutes vt into ct. Notice I want to substitute a value type into a computation type. I am able to use the standard library to substitute VTypes into VTypes, but not VTypes into CTypes, like above. I do that like so, using Data.Fin.Substitution (see here):
module TypeSubst where
-- Following Data.Substitutions.Example
module TypeApp {T} (l : Lift T VType) where
open Lift l hiding (var)
-- Applies a substitution to a type
infixl 8 _/v_
_/v_ : ∀ {m n} → VType m → Sub T m n → VType n
_/c_ : ∀ {m n} → CType m → Sub T m n → CType n
vunit /v ρ = vunit
(var x) /v ρ = lift (lookup x ρ)
(u σ) /v ρ = u (σ /c ρ)
(μ τ) /v ρ = μ (τ /v ρ ↑)
(σ ⇒ τ) /c ρ = σ /v ρ ⇒ τ /c ρ
f x /c ρ = f (x /v ρ)
open Application (record { _/_ = _/v_ }) using (_/✶_)
typeSubst : TermSubst VType
typeSubst = record { var = var; app = TypeApp._/v_ }
open TermSubst typeSubst public hiding (var)
weaken↑ : ∀ {n} → VType (1 + n) → VType (2 + n)
weaken↑ τ = τ / wk ↑
infix 8 _[/_]
-- single type substitution
_[/_] : ∀ {n} → VType (1 + n) → VType n → VType n
τ [/ σ ] = τ / sub σ
I've tried working with a new datatype Type:
data VorC : Set where
v : VorC
c : VorC
data Type : VorC → ℕ → Set where
vtype : ∀ {n} → VType n → Type v n
ctype : ∀ {n} → CType n → Type c n
I tried using the natural unwrapping function to go from Types to VType's or CType's, but this doesn't seem to work or leads to termination checking problems if I try mimicking the standard library's module.
Does anyone know if it is possible to use Data.Fin.Substitution from the standard library to accomplish something like this? Could someone explain that module to me? There is no documentation on this... If it isn't possible to use the standard library for this, any pointers on how to approach this problem is also welcome. Thanks!
You can open Application in the CType case instead of opening TermSubst which looks inappropriate (I don't know what's wrong with it). Here is the relevant part:
typeSubst : TermSubst VType
typeSubst = record { var = var; app = TypeApp._/v_ }
open TermSubst typeSubst public hiding (var)
module TypeSubst where
_[/v_] : ∀ {n} → VType (1 + n) → VType n → VType n
τ [/v σ ] = τ / sub σ
open Application (record { _/_ = TypeApp._/c_ termLift }) renaming (_/_ to _/c_) using ()
_[/c_] : ∀ {n} → CType (1 + n) → VType n → CType n
τ [/c σ ] = τ /c sub σ
The whole code.
To understand what's going in the standard library you need to read the Type-Preserving Renaming and Substitution paper. Though, the code in stdlib is quite more abstract.
BTW, you can use order preserving embeddings to define renaming and renaming to define substitution. Fill the holes here.

Termination-checking of function over a trie

I'm having difficulty convincing Agda to termination-check the function fmap below and similar functions defined recursively over the structure of a Trie. A Trie is a trie whose domain is a Type, an object-level type formed from unit, products and fixed points (I've omitted coproducts to keep the code minimal). The problem seems to relate to a type-level substitution I use in the definition of Trie. (The expression const (μₜ τ) * τ means apply the substitution const (μₜ τ) to the type τ.)
module Temp where
open import Data.Unit
open import Category.Functor
open import Function
open import Level
open import Relation.Binary
-- A context is just a snoc-list.
data Cxt {𝒂} (A : Set 𝒂) : Set 𝒂 where
ε : Cxt A
_∷ᵣ_ : Cxt A → A → Cxt A
-- Context membership.
data _∈_ {𝒂} {A : Set 𝒂} (a : A) : Cxt A → Set 𝒂 where
here : ∀ {Δ} → a ∈ Δ ∷ᵣ a
there : ∀ {Δ a′} → a ∈ Δ → a ∈ Δ ∷ᵣ a′
infix 3 _∈_
-- Well-formed types, using de Bruijn indices.
data _⊦ (Δ : Cxt ⊤) : Set where
nat : Δ ⊦
𝟏 : Δ ⊦
var : _ ∈ Δ → Δ ⊦
_+_ _⨰_ : Δ ⊦ → Δ ⊦ → Δ ⊦
μ : Δ ∷ᵣ _ ⊦ → Δ ⊦
infix 3 _⊦
-- A closed type.
Type : Set
Type = ε ⊦
-- Type-level substitutions and renamings.
Sub Ren : Rel (Cxt ⊤) zero
Sub Δ Δ′ = _ ∈ Δ → Δ′ ⊦
Ren Δ Δ′ = ∀ {x} → x ∈ Δ → x ∈ Δ′
-- Renaming extension.
extendᵣ : ∀ {Δ Δ′} → Ren Δ Δ′ → Ren (Δ ∷ᵣ _) (Δ′ ∷ᵣ _)
extendᵣ ρ here = here
extendᵣ ρ (there x) = there (ρ x)
-- Lift a type renaming to a type.
_*ᵣ_ : ∀ {Δ Δ′} → Ren Δ Δ′ → Δ ⊦ → Δ′ ⊦
_ *ᵣ nat = nat
_ *ᵣ 𝟏 = 𝟏
ρ *ᵣ (var x) = var (ρ x)
ρ *ᵣ (τ₁ + τ₂) = (ρ *ᵣ τ₁) + (ρ *ᵣ τ₂)
ρ *ᵣ (τ₁ ⨰ τ₂) = (ρ *ᵣ τ₁) ⨰ (ρ *ᵣ τ₂)
ρ *ᵣ (μ τ) = μ (extendᵣ ρ *ᵣ τ)
-- Substitution extension.
extend : ∀ {Δ Δ′} → Sub Δ Δ′ → Sub (Δ ∷ᵣ _) (Δ′ ∷ᵣ _)
extend θ here = var here
extend θ (there x) = there *ᵣ (θ x)
-- Lift a type substitution to a type.
_*_ : ∀ {Δ Δ′} → Sub Δ Δ′ → Δ ⊦ → Δ′ ⊦
θ * nat = nat
θ * 𝟏 = 𝟏
θ * var x = θ x
θ * (τ₁ + τ₂) = (θ * τ₁) + (θ * τ₂)
θ * (τ₁ ⨰ τ₂) = (θ * τ₁) ⨰ (θ * τ₂)
θ * μ τ = μ (extend θ * τ)
data Trie {𝒂} (A : Set 𝒂) : Type → Set 𝒂 where
〈〉 : A → 𝟏 ▷ A
〔_,_〕 : ∀ {τ₁ τ₂} → τ₁ ▷ A → τ₂ ▷ A → τ₁ + τ₂ ▷ A
↑_ : ∀ {τ₁ τ₂} → τ₁ ▷ τ₂ ▷ A → τ₁ ⨰ τ₂ ▷ A
roll : ∀ {τ} → (const (μ τ) * τ) ▷ A → μ τ ▷ A
infixr 5 Trie
syntax Trie A τ = τ ▷ A
{-# NO_TERMINATION_CHECK #-}
fmap : ∀ {a} {A B : Set a} {τ} → (A → B) → τ ▷ A → τ ▷ B
fmap f (〈〉 x) = 〈〉 (f x)
fmap f 〔 σ₁ , σ₂ 〕 = 〔 fmap f σ₁ , fmap f σ₂ 〕
fmap f (↑ σ) = ↑ (fmap (fmap f) σ)
fmap f (roll σ) = roll (fmap f σ)
It would seem that fmap recurses into a strictly smaller argument in each case; certainly the product case is fine if I remove recursive types. On the other hand, the definition handles recursive types fine if I remove products.
What's the simplest way to proceed here? The inline/fuse trick does not look particularly applicable, but maybe it is. Or should I be looking for another way to deal with the substitution in the definition of Trie?
The inline/fuse trick can be applied in (perhaps) surprising way. This trick is suited for problems of this sort:
data Trie (A : Set) : Set where
nil : Trie A
node : A → List (Trie A) → Trie A
map-trie : {A B : Set} → (A → B) → Trie A → Trie B
map-trie f nil = nil
map-trie f (node x xs) = node (f x) (map (map-trie f) xs)
This function is structurally recursive, but in a hidden way. map just applies map-trie f to the elements of xs, so map-trie gets applied to smaller (sub-)tries. But Agda doesn't look through the definition of map to see that it doesn't do anything funky. So we must apply the inline/fuse trick to get it past termination checker:
map-trie : {A B : Set} → (A → B) → Trie A → Trie B
map-trie f nil = nil
map-trie {A} {B} f (node x xs) = node (f x) (map′ xs)
where
map′ : List (Trie A) → List (Trie B)
map′ [] = []
map′ (x ∷ xs) = map-trie f x ∷ map′ xs
Your fmap function shares the same structure, you map a lifted function of some sort. But what to inline? If we follow the example above, we should inline fmap itself. This looks and feels a bit strange, but indeed, it works:
fmap fmap′ : ∀ {a} {A B : Set a} {τ} → (A → B) → τ ▷ A → τ ▷ B
fmap f (〈〉 x) = 〈〉 (f x)
fmap f 〔 σ₁ , σ₂ 〕 = 〔 fmap f σ₁ , fmap f σ₂ 〕
fmap f (↑ σ) = ↑ (fmap (fmap′ f) σ)
fmap f (roll σ) = roll (fmap f σ)
fmap′ f (〈〉 x) = 〈〉 (f x)
fmap′ f 〔 σ₁ , σ₂ 〕 = 〔 fmap′ f σ₁ , fmap′ f σ₂ 〕
fmap′ f (↑ σ) = ↑ (fmap′ (fmap f) σ)
fmap′ f (roll σ) = roll (fmap′ f σ)
There's another technique you can apply: it's called sized types. Instead of relying on the compiler to figure out when somethig is or is not structurally recursive, you instead specify it directly. However, you have to index your data types by a Size type, so this approach is fairly intrusive and cannot be applied to already existing types, but I think it is worth mentioning.
In its simplest form, sized type behaves as a type indexed by a natural number. This index specifies the upper bound of structural size. You can think of this as an upper bound for the height of a tree (given that the data type is an F-branching tree for some functor F). Sized version of List looks almost like a Vec, for example:
data SizedList (A : Set) : ℕ → Set where
[] : ∀ {n} → SizedList A n
_∷_ : ∀ {n} → A → SizedList A n → SizedList A (suc n)
But sized types add few features that make them easier to use. You have a constant ∞ for the case when you don't care about the size. suc is called ↑ and Agda implements few rules, such as ↑ ∞ = ∞.
Let's rewrite the Trie example to use sized types. We need a pragma at the top of the file and one import:
{-# OPTIONS --sized-types #-}
open import Size
And here's the modified data type:
data Trie (A : Set) : {i : Size} → Set where
nil : ∀ {i} → Trie A {↑ i}
node : ∀ {i} → A → List (Trie A {i}) → Trie A {↑ i}
If you leave the map-trie function as is, the termination checker is still going to complain. That's because when you don't specify any size, Agda will fill in infinity (i.e. don't-care value) and we are back at the beginning.
However, we can mark map-trie as size-preserving:
map-trie : ∀ {i A B} → (A → B) → Trie A {i} → Trie B {i}
map-trie f nil = nil
map-trie f (node x xs) = node (f x) (map (map-trie f) xs)
So, if you give it a Trie bounded by i, it will give you another Trie bounded by i as well. So map-trie can never make the Trie larger, only equally large or smaller. This is enough for the termination checker to figure out that map (map-trie f) xs is okay.
This technique can also be applied to your Trie:
open import Size
renaming (↑_ to ^_)
data Trie {𝒂} (A : Set 𝒂) : {i : Size} → Type → Set 𝒂 where
〈〉 : ∀ {i} → A →
Trie A {^ i} 𝟏
〔_,_〕 : ∀ {i τ₁ τ₂} → Trie A {i} τ₁ → Trie A {i} τ₂ →
Trie A {^ i} (τ₁ + τ₂)
↑_ : ∀ {i τ₁ τ₂} → Trie (Trie A {i} τ₂) {i} τ₁ →
Trie A {^ i} (τ₁ ⨰ τ₂)
roll : ∀ {i τ} → Trie A {i} (const (μ τ) * τ) →
Trie A {^ i} (μ τ)
infixr 5 Trie
syntax Trie A τ = τ ▷ A
fmap : ∀ {i 𝒂} {A B : Set 𝒂} {τ} → (A → B) → Trie A {i} τ → Trie B {i} τ
fmap f (〈〉 x) = 〈〉 (f x)
fmap f 〔 σ₁ , σ₂ 〕 = 〔 fmap f σ₁ , fmap f σ₂ 〕
fmap f (↑ σ) = ↑ fmap (fmap f) σ
fmap f (roll σ) = roll (fmap f σ)

Hilbert System - Automate Proof

I'm trying to prove the statement ~(a->~b) => a in a Hilbert style system. Unfortunately it seems like it is impossible to come up with a general algorithm to find a proof, but I'm looking for a brute force type strategy. Any ideas on how to attack this are welcome.
If You like "programming" in combinatory logic, then
You can automatically "translate" some logic problems into another field: proving equality of combinatory logic terms.
With a good functional programming practice, You can solve that,
and afterwards, You can translate the answer back to a Hilbert style proof of Your original logic problem.
The possibility of this translation in ensured by Curry-Howard correspondence.
Unfortunately, the situation is so simple only for a subset of (propositional) logic: restricted using conditionals. Negation is a complication, I know nothing about that. Thus I cannot answer this concrete question:
¬ (α ⊃ ¬β) ⊢ α
But in cases where negation is not part of the question, the mentioned automatic translation (and back-translation) can be a help, provided that You have already practice in functional programming or combinatory logic.
Of course, there are other helps, too, where we can remain inside the realm of logic:
proving the problem in some more intuitive deductive system (e.g. natural deduction)
and afterwards using metatheorems that provide a "compiler" possibility: translating the "high-level" proof of natural deduction to the "machine-code" of Hilbert-style deduction system. I mean, for example, the metalogical theorem called "deduction theorem".
As for theorem provers, as far as I know, the capabilities of some of them are extended so that they can harness interactive human assistance. E.g. Coq is such.
Appendix
Let us see an example. How to prove α ⊃ α?
Hilbert system
Verum ex quolibetα,β is assumed as an axiom scheme, stating that sentence α ⊃ β ⊃ α is expected to be deducible, instantiated for any subsentences α,β
Chain ruleα,β,γ is assumed as an axiom scheme, stating that sentence (α ⊃ β ⊃ γ) ⊃ (α ⊃ β) ⊃ α ⊃ γ is expected to be deducible, instantiated for any subsentences α,β
Modus ponens is assumed as a rule of inference: provided that α ⊃ β is deducible, and also α is deducible, then we expect to be justified to infer that also α ⊃ β is deducible.
Let us prove theorem: α ⊃ α is deducible for any α proposition.
Let us introduce the following notations and abbreviations, developing a "proof calculus":
Proof calculus
VEQα,β: ⊢ α ⊃ β ⊃ α
CRα,β,γ: ⊢ (α ⊃ β ⊃ γ) ⊃ (α ⊃ β) ⊃ α⊃ γ
MP: If ⊢ α ⊃ β and ⊢ α, then also ⊢ β
A tree diagram notation:
Axiom scheme — Verum ex quolibet:
━━━━━━━━━━━━━━━━━ [VEQα,β]
⊢ α ⊃ β ⊃ α
Axiom scheme — chain rule:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [CRα,β,γ]
⊢ (α ⊃ β ⊃ γ) ⊃ (α ⊃ β) ⊃ α⊃ γ
Rule of inference — modus ponens:
⊢ α ⊃ β ⊢ α
━━━━━━━━━━━━━━━━━━━ [MP]
⊢ β
Proof tree
Let us see a tree diagram representation of the proof:
━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [CRα, α⊃α, α]
━━━━━━━━━━━━━━━ [VEQα, α⊃α]
⊢ [α⊃(α⊃α)⊃α]⊃(α⊃α⊃α)⊃α⊃α
⊢ α ⊃ (α ⊃ α) ⊃ α
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [MP] ━━━━━━━━━━━ [VEQα,α]
⊢ (α ⊃ α ⊃ α) ⊃ α ⊃ α
⊢ α ⊃ α ⊃ α
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ [MP]
⊢ α ⊃ α
Proof formulae
Let us see an even conciser (algebraic? calculus?) representation of the proof:
(CRα,α⊃α,α VEQα,α ⊃ α) VEQα,α: ⊢ α⊃ α
so, we can represent the proof tree by a single formula:
the forking of the tree (modus ponens) is rendered by simple concatenation (parentheses),
and the leaves of the tree are rendered by the abbreviations of the corresponding axiom names.
It is worth of keep record about the concrete instantiation, that' is typeset here with subindexical parameters.
As it will be seen from the series of examples below, we can develop a proof calculus, where axioms are notated as sort of base combinators, and modus ponens is notated as a mere application of its "premise" subproofs:
Example 1
VEQα,β: ⊢ α ⊃ β ⊃ α
meant as
Verum ex quolibet axiom scheme instantiated with α,β provides a proof for the statement, that α ⊃ β ⊃ α is deducible.
Example 2
VEQα,α: ⊢ α ⊃ α ⊃ α
Verum ex quolibet axiom scheme instantiated with α,α provides a proof for the statement, that α ⊃ α ⊃ α is deducible.
Example 3
VEQα, α⊃α: ⊢ α ⊃ (α ⊃ α) ⊃ α
meant as
Verum ex quolibet axiom scheme instantiated with α, α⊃α provides a proof for the statement, that α ⊃ (α ⊃ α) ⊃ α is deducible.
Example 4
CRα,β,γ: ⊢ (α ⊃ β ⊃ γ) ⊃ (α ⊃ β) ⊃ α⊃ γ
meant as
Chain rule axiom scheme instantiated with α,β,γ provides a proof for the statement, that (α ⊃ β ⊃ γ) ⊃ (α ⊃ β) ⊃ α⊃ γ is deducible.
Example 5
CRα,α⊃α,α: ⊢ [α ⊃ (α⊃α) ⊃ α] ⊃ (α ⊃ α⊃α) ⊃ α⊃ α
meant as
Chain rule axiom scheme instantiated with α,α⊃α,α provides a proof for the statement, that [α ⊃ (α⊃α) ⊃ α] ⊃ (α ⊃ α⊃α) ⊃ α⊃ α is deducible.
Example 6
CRα,α⊃α,α VEQα,α ⊃ α: ⊢ (α ⊃ α⊃α) ⊃ α⊃ α
meant as
If we combine CRα,α⊃α,α and VEQα,α ⊃ α together via modus ponens, then we get a proof that proves the following statement: (α ⊃ α⊃α) ⊃ α⊃ α is deducible.
Example 7
(CRα,α⊃α,α VEQα,α ⊃ α) VEQα,α: ⊢ α⊃ α
If we combine the compund proof (CRα,α⊃α,α) together with VEQα,α ⊃ α (via modus ponens), then we get an even more compund proof. This proves the following statement: α⊃ α is deducible.
Combinatory logic
Although all this above has indeed provided a proof for the expected theorem, but it seems very unintuitive. It cannot be seen how people can "find out" the proof.
Let us see another field, where similar problems are investigated.
Untyped combinatory logic
Combinatory logic can be regarded also as an extremely minimalistic functional programming language. Despite of its minimalism, it entirely Turing complete, but evenmore, one can write quite intuitive and complex programs even in this seemingly obfuscated language, in a modular and reusable way, with some practice gained from "normal" functional programming and some algebraic insights, .
Adding typing rules
Combinatory logic also has typed variants. Syntax is augmented with types, and evenmore, in addition to reduction rules, also typing rules are added.
For base combinators:
Kα,β is selected as a basic combinator, inhabiting type α → β → α
Sα,β,γ is selected as a basic combinator, inhabiting type (α → β → γ) → (α → β) → α → γ.
Typing rule of application:
If X inhabits type α → β and Y inhabits type α, then
X Y inhabits type β.
Notations and abbreviations
Kα,β: α → β → α
Sα,β,γ: (α → β → γ) → (α → β)* → α → γ.
If X: α → β and Y: α, then
X Y: β.
Curry-Howard correspondence
It can be seen that the "patterns" are isomorphic in the proof calculus and in this typed combinatory logic.
The Verum ex quolibet axiom of the proof calculus corresponds to the K base combinator of combinatory logic
The Chain rule axiom of the proof calculus corresponds to the S base combinator of combinatory logic
The Modus ponens rule of inference in the proof calculus corresponds to the operation "application" in combinatory logic.
The "conditional" connective ⊃ of logic corresponds to type constructor → of type theory (and typed combinatory logic)
Functional programming
But what is the gain? Why should we translate problems to combinatory logic? I, personally, find it sometimes useful, because functional programming is a thing which has a large literature and is applied in practical problems. People can get used to it, when forced to use it in erveryday programming tasks ans pracice. And some tricks and hints of functional programming practice can be exploited very well in combinatory logic reductions. And if a "transferred" practice develops in combinatory logic, then it can be harnessed also in finding proofs in Hilbert system.
External links
Links how types in functional programming (lambda calculus, combinatory logic) can be translated into logical proofs and theorems:
Wadler, Philip (1989). Theorems for free!.
Links (or books) how to learn methods and practice to program directly in combinatory logic:
Madore, David (2003). The Unlambda Programming Language. Unlambda: Your Functional Programming Language Nightmares Come True.
Curry, Haskell B. & Feys, Robert & Craig, William (1958). Combinatory Logic. Vol. I. Amsterdam: North-Holland Publishing Company.
Tromp, John (1999). Binary Lambda Calculus and Combinatory Logic. Downloadable in PDF and Postscript from the author's John's Lambda Calculus and Combinatory Logic Playground.
The Hilbert system is not normally used in automated theorem proving. It is much easier to write a computer program to do proofs using natural deduction. From the material of a CS course:
Some FAQ’s about the Hilbert system:
Q: How does one know which axiom
schemata to use, and which
substitutions to make? Since there are
infinitely many possibilities, it is
not possible to try them all, even in
princple. A: There is no algorithm; at
least no simple one. Rather, one has
to be clever. In pure mathematics,
this is not viewed as a problem, since
one is most concerned about the
existence of a proof. However, in
computer science applications, one is
interested in automating the deduction
process, so this is a fatal flaw. The
Hilbert system is not normally used in
automated theorem proving. Q: So, why
do people care about the Hilbert
system? A: With modus ponens as its
single deductive rule, it provides a
palatable model of how humans devise
mathematical proofs. As we shall see,
methods which are more amenable to
computer implementation produce proofs
which are less “human like.”
You can approach the problem also by setting ¬ α = α → ⊥. We can then adopt the Hilbert style system as shown in the appendix of one of the answers, and make it classical by adding the following two axioms respectively constants:
Ex Falso Quodlibet: Eα : ⊥ → α
Consequentia Mirabilis: Mα : (¬ α → α) → α
A sequent proof of ¬ (α → ¬ β) → α then reads as follows:
α ⊢ α (Identity)
⊥ ⊢ β → ⊥ (Ex Falso Quodlibet)
α → ⊥, α ⊢ β → ⊥ (Impl Intro Left 1 & 2)
α → ⊥ ⊢ α → (β → ⊥) (Impl Intro Right 3)
⊥ ⊢ α (Ex Falso Quodlibet)
(α → (β → ⊥)) → ⊥, α → ⊥ ⊢ α (Impl Intro Left 4 & 5)
(α → (β → ⊥)) → ⊥ ⊢ α (Consequentia Mirabilis 6)
⊢ ((α → (β → ⊥)) → ⊥) → α (Impl Intro Right 7)
From this sequent proof, one can extract a lambda expression. A possible
lambda expressions for the above sequent proof reads as follows:
λy.(M λz.(E (y λx.(E (z x)))))
This lambda expression can be converted into a SKI term. A possible
SKI term for the above lambda expression reads as follows:
S (K M)) (L2 (L1 (K (L2 (L1 (K I))))))
where L1 = (S ((S (K S)) ((S (K K)) I)))
and L2 = (S (K (S (K E))))
This gives the following Hilbert style proofs:
Lemma 1: A weakened form of the chain rule:
1: ((A → B) → ((C → A) → (C → B))) → (((A → B) → (C → A)) → ((A → B) → (C → B))) [Chain]
2: ((A → B) → ((C → (A → B)) → ((C → A) → (C → B)))) → (((A → B) → (C → (A → B))) → ((A → B) → ((C → A) → (C → B)))) [Chain]
3: ((C → (A → B)) → ((C → A) → (C → B))) → ((A → B) → ((C → (A → B)) → ((C → A) → (C → B)))) [Verum Ex]
4: (C → (A → B)) → ((C → A) → (C → B)) [Chain]
5: (A → B) → ((C → (A → B)) → ((C → A) → (C → B))) [MP 3, 4]
6: ((A → B) → (C → (A → B))) → ((A → B) → ((C → A) → (C → B))) [MP 2, 5]
7: ((A → B) → ((A → B) → (C → (A → B)))) → (((A → B) → (A → B)) → ((A → B) → (C → (A → B)))) [Chain]
8: ((A → B) → (C → (A → B))) → ((A → B) → ((A → B) → (C → (A → B)))) [Verum Ex]
9: (A → B) → (C → (A → B)) [Verum Ex]
10: (A → B) → ((A → B) → (C → (A → B))) [MP 8, 9]
11: ((A → B) → (A → B)) → ((A → B) → (C → (A → B))) [MP 7, 10]
12: (A → B) → (A → B) [Identity]
13: (A → B) → (C → (A → B)) [MP 11, 12]
14: (A → B) → ((C → A) → (C → B)) [MP 6, 13]
15: ((A → B) → (C → A)) → ((A → B) → (C → B)) [MP 1, 14]
Lemma 2: A weakened form of Ex Falso:
1: (A → ((B → ⊥) → (B → C))) → ((A → (B → ⊥)) → (A → (B → C))) [Chain]
2: ((B → ⊥) → (B → C)) → (A → ((B → ⊥) → (B → C))) [Verum Ex]
3: (B → (⊥ → C)) → ((B → ⊥) → (B → C)) [Chain]
4: (⊥ → C) → (B → (⊥ → C)) [Verum Ex]
5: ⊥ → C [Ex Falso]
6: B → (⊥ → C) [MP 4, 5]
7: (B → ⊥) → (B → C) [MP 3, 6]
8: A → ((B → ⊥) → (B → C)) [MP 2, 7]
9: (A → (B → ⊥)) → (A → (B → C)) [MP 1, 8]
Final Proof:
1: (((A → (B → ⊥)) → ⊥) → (((A → ⊥) → A) → A)) → ((((A → (B → ⊥)) → ⊥) → ((A → ⊥) → A)) → (((A → (B → ⊥)) → ⊥) → A)) [Chain]
2: (((A → ⊥) → A) → A) → (((A → (B → ⊥)) → ⊥) → (((A → ⊥) → A) → A)) [Verum Ex]
3: ((A → ⊥) → A) → A [Mirabilis]
4: ((A → (B → ⊥)) → ⊥) → (((A → ⊥) → A) → A) [MP 2, 3]
5: (((A → (B → ⊥)) → ⊥) → ((A → ⊥) → A)) → (((A → (B → ⊥)) → ⊥) → A) [MP 1, 4]
6: (((A → (B → ⊥)) → ⊥) → ((A → ⊥) → ⊥)) → (((A → (B → ⊥)) → ⊥) → ((A → ⊥) → A)) [Lemma 2]
7: (((A → (B → ⊥)) → ⊥) → ((A → ⊥) → (A → (B → ⊥)))) → (((A → (B → ⊥)) → ⊥) → ((A → ⊥) → ⊥)) [Lemma 1]
8: ((A → ⊥) → (A → (B → ⊥))) → (((A → (B → ⊥)) → ⊥) → ((A → ⊥) → (A → (B → ⊥)))) [Verum Ex]
9: ((A → ⊥) → (A → ⊥)) → ((A → ⊥) → (A → (B → ⊥))) [Lemma 2]
10: ((A → ⊥) → (A → A)) → ((A → ⊥) → (A → ⊥)) [Lemma 1]
11: (A → A) → ((A → ⊥) → (A → A)) [Verum Ex]
12: A → A [Identity]
13: (A → ⊥) → (A → A) [MP 11, 12]
14: (A → ⊥) → (A → ⊥) [MP 10, 13]
15: (A → ⊥) → (A → (B → ⊥)) [MP 9, 14]
16: ((A → (B → ⊥)) → ⊥) → ((A → ⊥) → (A → (B → ⊥))) [MP 8, 15]
17: ((A → (B → ⊥)) → ⊥) → ((A → ⊥) → ⊥) [MP 7, 16]
18: ((A → (B → ⊥)) → ⊥) → ((A → ⊥) → A) [MP 6, 17]
19: ((A → (B → ⊥)) → ⊥) → A [MP 5, 18]
Quite a long proof!
Bye
Finding proofs in Hilbert calculus is very hard.
You could try to translate proofs in sequent calculus or natural deduction to Hilbert calculus.
Which specific Hilbert system? There are tons.
Probably the best way is to find a proof in a sequent calculus and convert it to the Hilbert system.
I use Polish notation.
Since you referenced the Wikipedia, we'll suppose our basis is
1 CpCqp.
2 CCpCqrCCpqCpr.
3 CCNpNqCqp.
We want to prove
NCaNb |- a.
I use the theorem prover Prover9. So, we'll need to parenthesize everything. Also, the variables of Prover9 go (x, y, z, u, w, v5, v6, ..., vn). All other symbols get interpreted as functions or relations or predicates. All axioms need a predicate symbol "P" before them also, which we can think of as meaning "it is provable that..." or more simply "provable". And all sentences in Prover9 need to get ended by a period. Thus, axioms 1, 2, and 3 become respectively:
1 P(C(x,C(y,x))).
2 P(C(C(x,C(y,z)),C(C(x,y),C(x,z)))).
3 P(C(C(N(x),N(y)),C(y,x))).
We can combine the rules of uniform substitution and detachment into the rule of condensed detachment. In Prover9 we can represent this as:
-P(C(x,y)) | -P(x) | P(y).
The "|" indicates logical disjunction, and "-" indicates negation. Prover9 proves by contradiction. The rule says in words can get interpreted as saying "either it is not the case that if x, then y is provable, or it is not the case that x is provable, or y is provable." Thus, if it does hold that if x, then y is provable, the first disjunct fails. If it does hold that x is provable, then the second disjunct fails. So, if, if x, then y is provable, if x is provable, then the third disjunct, that y is provable follows by the rule.
Now we can't make substitutions in NCaNb, since it's not a tautology. Nor is "a". Thus, if we put
P(N(C(a,N(b)))).
as an assumption, Prover9 will interpret "a" and "b" as nullary functions, which effectively turns them into constants. We also want to make P(a) as our goal.
Now we can also "tune" Prover9 using various theorem-proving strategies such as weighting, resonance, subformula, pick-given ratio, level saturation (or even invent our own). I'll use the hints strategy a little bit, by making all of the assumptions (including the rule of inference), and the goal into hints. I'll also turn the max weight down to 40, and make 5 the number of maximum variables.
I use the version with the graphical interface, but here's the entire input:
set(ignore_option_dependencies). % GUI handles dependencies
if(Prover9). % Options for Prover9
assign(max_seconds, -1).
assign(max_weight, 40).
end_if.
if(Mace4). % Options for Mace4
assign(max_seconds, 60).
end_if.
if(Prover9). % Additional input for Prover9
formulas(hints).
-P(C(x,y))|-P(x)|P(y).
P(C(x,C(y,x))).
P(C(C(x,C(y,z)),C(C(x,y),C(x,z)))).
P(C(C(N(x),N(y)),C(y,x))).
P(N(C(a,N(b)))).
P(a).
end_of_list.
assign(max_vars,5).
end_if.
formulas(assumptions).
-P(C(x,y))|-P(x)|P(y).
P(C(x,C(y,x))).
P(C(C(x,C(y,z)),C(C(x,y),C(x,z)))).
P(C(C(N(x),N(y)),C(y,x))).
P(N(C(a,N(b)))).
end_of_list.
formulas(goals).
P(a).
end_of_list.
Here's the proof it gave me:
============================== prooftrans ============================
Prover9 (32) version Dec-2007, Dec 2007.
Process 1312 was started by Doug on Machina2,
Mon Jun 9 22:35:37 2014
The command was "/cygdrive/c/Program Files (x86)/Prover9-Mace43/bin-win32/prover9".
============================== end of head ===========================
============================== end of input ==========================
============================== PROOF =================================
% -------- Comments from original proof --------
% Proof 1 at 0.01 (+ 0.01) seconds.
% Length of proof is 23.
% Level of proof is 9.
% Maximum clause weight is 20.
% Given clauses 49.
1 P(a) # label(non_clause) # label(goal). [goal].
2 -P(C(x,y)) | -P(x) | P(y). [assumption].
3 P(C(x,C(y,x))). [assumption].
4 P(C(C(x,C(y,z)),C(C(x,y),C(x,z)))). [assumption].
5 P(C(C(N(x),N(y)),C(y,x))). [assumption].
6 P(N(C(a,N(b)))). [assumption].
7 -P(a). [deny(1)].
8 P(C(x,C(y,C(z,y)))). [hyper(2,a,3,a,b,3,a)].
9 P(C(C(C(x,C(y,z)),C(x,y)),C(C(x,C(y,z)),C(x,z)))). [hyper(2,a,4,a,b,4,a)].
12 P(C(C(C(N(x),N(y)),y),C(C(N(x),N(y)),x))). [hyper(2,a,4,a,b,5,a)].
13 P(C(x,C(C(N(y),N(z)),C(z,y)))). [hyper(2,a,3,a,b,5,a)].
14 P(C(x,N(C(a,N(b))))). [hyper(2,a,3,a,b,6,a)].
23 P(C(C(a,N(b)),x)). [hyper(2,a,5,a,b,14,a)].
28 P(C(C(x,C(C(y,x),z)),C(x,z))). [hyper(2,a,9,a,b,8,a)].
30 P(C(x,C(C(a,N(b)),y))). [hyper(2,a,3,a,b,23,a)].
33 P(C(C(x,C(a,N(b))),C(x,y))). [hyper(2,a,4,a,b,30,a)].
103 P(C(N(b),x)). [hyper(2,a,33,a,b,3,a)].
107 P(C(x,b)). [hyper(2,a,5,a,b,103,a)].
113 P(C(C(N(x),N(b)),x)). [hyper(2,a,12,a,b,107,a)].
205 P(C(N(x),C(x,y))). [hyper(2,a,28,a,b,13,a)].
209 P(C(N(a),x)). [hyper(2,a,33,a,b,205,a)].
213 P(a). [hyper(2,a,113,a,b,209,a)].
214 $F. [resolve(213,a,7,a)].
============================== end of proof ==========================

Resources