Dedukti : A Universal Proof Checker Mathieu Boespflug 1 Quentin - - PowerPoint PPT Presentation

dedukti a universal proof checker
SMART_READER_LITE
LIVE PREVIEW

Dedukti : A Universal Proof Checker Mathieu Boespflug 1 Quentin - - PowerPoint PPT Presentation

Dedukti : A Universal Proof Checker Mathieu Boespflug 1 Quentin Carbonneaux 2 Olivier Hermant 3 1 McGill University 2 INRIA and ENPC 3 INRIA and ISEP PxTP 2012 Contents Introduction The -calculus modulo The Dedukti proof checker Better


slide-1
SLIDE 1

Dedukti: A Universal Proof Checker

Mathieu Boespflug1 Quentin Carbonneaux2 Olivier Hermant3

1McGill University 2INRIA and ENPC 3INRIA and ISEP

PxTP 2012

slide-2
SLIDE 2

Contents

Introduction The λΠ-calculus modulo The Dedukti proof checker Better performance using JIT compilation Conclusion

slide-3
SLIDE 3

Dedukti as a universal backend

Dedukti HOL Coq FoCaLiZe PVS Isabelle

Introduction

slide-4
SLIDE 4

The λΠ-calculus at the core

A calculus with dependent types: array : nat → Type. In a Curry-de Bruijn-Howard style, the λΠ-calculus is a language representing proofs of minimal predicate logic. At least two choices to increase expressiveness:

  • 1. enrich the λΠ-calculus by adding more deduction rules (e.g.

CIC);

  • 2. liberalize the conversion rule (λΠ-calculus modulo).

The λΠ-calculus modulo

slide-5
SLIDE 5

The λΠ-calculus modulo

Var ∋ x, y, z Term ∋ t, A, B ::= x | λx:A. M | Πx:A. B | M N | Type | Kind

Figure: Grammar of the λΠ-calculus modulo

The λΠ-calculus modulo

slide-6
SLIDE 6

Typing rules: Abstractions

Γ ⊢ A : Type Γ, x:A ⊢ B : s (prod) Γ ⊢ Πx:A. B : s Γ ⊢ A : Type Γ, x:A ⊢ B : s Γ, x:A ⊢ M : B (abs) Γ ⊢ λx:A. M : Πx:A. B s ∈ {Type, Kind}

The λΠ-calculus modulo

slide-7
SLIDE 7

Typing rules: Dependent application

Γ ⊢ M : Πx:A. B Γ ⊢ N : A (app) Γ ⊢ M N : {N/x}B

The λΠ-calculus modulo

slide-8
SLIDE 8

Typing rules: Conversion modulo

Γ ⊢ M : A Γ ⊢ A : s Γ ⊢ B : s (conv) A ≡βR B Γ ⊢ M : B

The λΠ-calculus modulo

slide-9
SLIDE 9

A Dedukti signature

∀y, 0 + y = y ∀x, ∀y, S x + y = S (x + y). nat : Type . Z : nat . S : nat → nat . plus : nat → nat → nat . [ y : nat ] plus Z y ֒ → y [ x : nat , y : nat ] plus (S x ) y ֒ → S ( plus x y ) .

The λΠ-calculus modulo

slide-10
SLIDE 10

A sample derivation

In the following context: Γ := nat : Type, vec : nat → Type, cat : Πn:nat. Πm:nat. vec n → vec m → vec (n + m) n : nat, v : vec n. we have Γ ⊢ cat : ... Γ ⊢ n : nat Γ ⊢ v : vec n (apps) Γ ⊢ cat n n v v : vec (n + n) (conv) Γ ⊢ cat n n v v : vec (2 ∗ n)

The λΠ-calculus modulo

slide-11
SLIDE 11

Dedukti’s goals

◮ Fast type checking of an extensible λ-calculus. ◮ Use compilation techniques.

◮ Plenty of efficient compilers available; ◮ reuse them off the shelf (separate concerns).

◮ Lightest possible runtime system.

Two choices are possible:

The Dedukti proof checker

slide-12
SLIDE 12

Dedukti’s goals

◮ Fast type checking of an extensible λ-calculus. ◮ Use compilation techniques.

◮ Plenty of efficient compilers available; ◮ reuse them off the shelf (separate concerns).

◮ Lightest possible runtime system.

Two choices are possible:

◮ generate a specific type checker for each theory (LFSC);

The Dedukti proof checker

slide-13
SLIDE 13

Dedukti’s goals

◮ Fast type checking of an extensible λ-calculus. ◮ Use compilation techniques.

◮ Plenty of efficient compilers available; ◮ reuse them off the shelf (separate concerns).

◮ Lightest possible runtime system.

Two choices are possible:

◮ generate a specific type checker for each theory (LFSC); ◮ generate a specific type checker for a set of terms (Dedukti).

The Dedukti proof checker

slide-14
SLIDE 14

The big picture

a.out .dk Dedukti .dko Compiler Runtime

The Dedukti proof checker

slide-15
SLIDE 15

Two interpretations

We fully embed the type checking logic in the target language. Generated data/code must fit two purposes:

  • 1. Type checking (static representation).
  • 2. Normalizing (dynamic representation).

The Dedukti proof checker

slide-16
SLIDE 16

Two interpretations

The static version of terms in HOAS (.). data Term = Lam (Term → Term) | App Term Term | B Term x = B x λx. t = Lam (λx.t) a b = App a b

The Dedukti proof checker

slide-17
SLIDE 17

Two interpretations

The static version of terms in HOAS (.). data Term = Lam (Term → Term) | App Term Term | B Term x = B x λx. t = Lam (λx.t) a b = App a b With this interpreter: eval (B x) = x eval (Lam f ) = λx.eval (f x) eval (App a b) = (eval a)(eval b) How to peel the result of the evaluation?

The Dedukti proof checker

slide-18
SLIDE 18

Two interpretations

eval’ (B x) = x eval’ (Lam f ) = L (λx.eval’ (f x)) eval’ (App a b) = app (eval’ a) (eval’ b) app (L f ) x = f x app a b = A a b

The Dedukti proof checker

slide-19
SLIDE 19

Two interpretations

eval’ (B x) = x eval’ (Lam f ) = L (λx.eval’ (f x)) eval’ (App a b) = app (eval’ a) (eval’ b) app (L f ) x = f x app a b = A a b The dynamic version of terms (.). . = eval’ ◦ . x = x λx. t = L (λx.t) a b = app a b

The Dedukti proof checker

slide-20
SLIDE 20

Two interpretations

eval’ (B x) = x eval’ (Lam f ) = L (λx.eval’ (f x)) eval’ (App a b) = app (eval’ a) (eval’ b) app (L f ) x = f x app a b = A a b x = B x λx. t = Lam (λx.t) a b = App a b x = x λx. t = L (λx.t) a b = app a b

The Dedukti proof checker

slide-21
SLIDE 21

Context free type checking

de Bruijn’s criterion

We must have the simplest possible runtime. As a solution, we rely on the host language’s features. Judgements become closures: we move from Γ ⊢ t:T to ⊢ t:T; substitutions are performed using HOAS. Term ∋ t, A, B ::= x | [y : T] | λx. M | Πx:A. B | M N | Type | Kind

The Dedukti proof checker

slide-22
SLIDE 22

Context free type checking

C − →∗

w Πx:A. B

⊢ {[y : A]/x}M ⇐ {y/x}B (absb) ⊢ λx. M ⇐ C

The Dedukti proof checker

slide-23
SLIDE 23

Context free type checking

C − →∗

w Πx:A. B

⊢ {[y : A]/x}M ⇐ {y/x}B (absb) ⊢ λx. M ⇐ C Which maps trivially to this Haskell snippet: check n (Lam f ) ( Pi a t ) = check (n + 1) ( f box ) ( t var ) where box = Box n a var = Var n

The Dedukti proof checker

slide-24
SLIDE 24

Dedukti on a simple example

Module Dedukti Compilation and execution Coq.Init.Logic 50 sec 1 min 13 sec + 0.261 sec

Better performance using JIT compilation

slide-25
SLIDE 25

Dedukti on a simple example

Module Dedukti Compilation and execution Coq.Init.Logic 50 sec 1 min 13 sec + 0.261 sec Module Chicken Coq.Init.Logic 0.170 sec

Better performance using JIT compilation

slide-26
SLIDE 26

A complete rewrite

Dedukti was freshly (6 weeks ago) rewritten in C. Simple observation: the translator is a syntactic map. This allows a new design:

Better performance using JIT compilation

slide-27
SLIDE 27

A complete rewrite

Dedukti was freshly (6 weeks ago) rewritten in C. Simple observation: the translator is a syntactic map. This allows a new design:

  • 1. the translator can be an online program (work in a stream

friendly way);

Better performance using JIT compilation

slide-28
SLIDE 28

A complete rewrite

Dedukti was freshly (6 weeks ago) rewritten in C. Simple observation: the translator is a syntactic map. This allows a new design:

  • 1. the translator can be an online program (work in a stream

friendly way);

  • 2. the internal state of the translator is tiny, hence no garbage

collection is needed.

Better performance using JIT compilation

slide-29
SLIDE 29

A complete rewrite

Dedukti now switches from Haskell to Lua.

◮ Lua is a minimal programming language. ◮ Lua enjoys a very fast cutting edge JIT (luajit). ◮ Lua is not statically typed, not scoped.

Better performance using JIT compilation

slide-30
SLIDE 30

A huge performance gap

File Dedukti before Dedukti after bool steps.dk > 5 min 6 sec Coq Init Logic.dk 50 sec 0.08 sec

Figure: Speed of the first translation

Because memory management is handmade, several gigabytes are saved during the processing of big files.

Better performance using JIT compilation

slide-31
SLIDE 31

The JIT compromise

Figure: Compilation vs JIT

Better performance using JIT compilation

slide-32
SLIDE 32

Conclusion

◮ Dedukti is

◮ 1285 lines of C (+ 451 lines of comments); ◮ blazingly fast on resonably sized examples; ◮ not worse than a trivial implementation; ◮ generating Lua code.

◮ Using a JIT allows a a smoother behavior of type checking

times.

◮ Next steps: improve our control on generated code, cope with

luajit’s limits.

Conclusion