420 likes | 427 Views
15-820A PVS – An Introduction. Edmund Clarke Daniel Kroening Carnegie Mellon University. Outline. Theorem provers Why PVS? Topics for this semester Short introduction to the PVS language The PVS workflow A short proof. Theorem Provers. Stores theorems and establishes their correctness
E N D
15-820APVS – An Introduction Edmund Clarke Daniel Kroening Carnegie Mellon University
Outline • Theorem provers • Why PVS? • Topics for this semester • Short introduction to the PVS language • The PVS workflow • A short proof
Theorem Provers • Stores theorems and establishes their correctness • What kind of theorems? • First order • Second order / higher order • How to establish the correctness? • Completely automated • Semi-automated • Interactive (manual)
Theorem Provers There is a wide range of theorem provers • Higher order: ALF, Alfa, Coq, HOL, PVS • Logical Frameworks: Isabelle, LF, Twelf • Inductive: ACL2, Inka • Automated: Gandalf, TPS, Otter, Setheo, SPASS • EQP, Maude
Theorem Provers • The most commonly used Theorem Provers,from systems verification point of view • HOL: Floating Point Verification (Intel) • ACL2: Floating Point Verification (AMD) • PVS: NASA/DoD, e.g., Space Shuttle flight control requirements specificationIt also does Floating Point Units. • PVS is… • Higher order • Interactive
PVS Workflow System PROOFS PVS File Properties Conversion of system (Program, circuit, protocol…)and property. Can be automated or donemanually Proof construction Interaction with the theorem prover A
Why PVS? • Why PVS and not some other theorem prover? From PVS website: “PVS is a large and complex system and it takes a long while to learn to use it effectively. You should be prepared to invest six months to become a moderately skilled user” A
Why PVS? • Why PVS and not some other theorem prover? • Other (strong) theorem provers probably worse • The PVS language is close to “normal” notation • Not LISP! • PVS is interactive – why not an automated theorem prover? • Decidable logics often not rich enough, or inconvenient • Semi-automated theorem provers usually don’t tell what is wrong, experience and knowledge about internals required
Topics for this Semester • PVS • Installation • Proof Interaction • Language Basics • Types • Type Checking • Recursion • Lambda Notation • Abstract Data Types
Topics for this Semester • Specification using PVS • Prelude, Libraries • State Machines • Tabular Specifications • How to get “systems” into PVS • Hardware • Software
Topics for this Semester • Proofs • Induction • Real Numbers • Abstraction of Infinite State Transition Systems • Proof Automation • Rewriting • Write your own decision procedure! • Model Checking as Rule of Inference
The PVS Language • There are two languages • The language to write definitions and theorems (“definition language“) • The language to prove theorems(“proof language”) They have nothing to do with each other • The definition language looks like“normal math” (translator to Latex built in) • The proof language looks like LISP
The PVS Definition Language • Main language elements • Declarations • Types • Constants • Expressions over these types • Expressions of Boolean types may be a formula • Formulae are theorems or axioms • Declarations and formulae are grouped into theories
The PVS Definition Language class_theory: THEORY BEGIN my_type: NONEMPTY_TYPE constant1, constant2: my_type f1: THEOREM FORALL (a, b: integer): a+b=b+a f2: AXIOM constant1=constant2 END class_theory TypeDeclarations Expressions A
The PVS Definition Language class_theory: THEORY BEGIN my_type: NONEMPTY_TYPE constant1, constant2: my_type f1: THEOREM FORALL (a, b: integer): a+b=b+a f2: AXIOM constant1=constant2 END class_theory Formulae A
The PVS Definition Language class_theory: THEORY BEGIN my_type: NONEMPTY_TYPE constant1, constant2: my_type f1: THEOREM FORALL (a, b: integer): a+b=b+a f2: AXIOM constant1=constant2 END class_theory Declarations
Axioms vs. Theorems • Axioms are assumed to be true • Dangerous! • Avoid axioms, use constant declarations instead: class_theory: THEORY BEGIN c: integer = 3 END class_theory class_theory: THEORY BEGIN c: integer c: AXIOM c=3 END class_theory Left hand side is conservative
Types • PVS has a very rich type concept • Uninterpreted type declaration: numbers: TYPE numbers: NONEMPTY_TYPE • Interpreted type declarationIntroduce names for type expressions posint: TYPE={ i: integer | i > 0}
Types PVS comes with • boolean • FALSE, TRUE • Number types • real, rational, integer, natural • string • Ordinals
Type Expressions • Function Types [ t1,…,tn -> t ] Sugar for that: FUNCTION[ t1,…,tn -> t ] ARRAY[ t1,…,tn -> t ] Note that ti and t may be function types as well!
Expressions • Constants • Given by their name, as used in the declaration • Numbers (1, 2, 3, …) are actually identifiers and can even be overloaded • If name is ambiguous, use identifier::type
Expressions • Function Applications f(x) • Tons of Syntactic sugar for that, don’t be confused • Binary operator symbols y * z is the same as *(y, z)
Expressions • Functions PVS comes with • Boolean AND &, OR, IMPLIES =>, WHEN, IFF <=> • IF c THEN a ELSE b IF:[boolean, T, T -> T] • (COND: sugar for IF THEN ELSE) • Numeric operators +, -, *, /, ^, <, <=, >, >=
Expressions • Binding Expressions • Quantifiers EXISTS (x: T): p(x) FORALL (y: T): q(y)
Expressions • Binding Expressions • Lambda: unnamed functions LAMBDA (x: int): x+1 Type of that: [ int -> int ] class_theory: THEORYBEGIN f(x: int): int = x+1 END class_theory class_theory: THEORYBEGIN f: [int->int] = LAMBDA (x: int): x+1 END class_theory A
Recursion • Lambda cannot be used for recursion • Only named functions allow recursion • No mutual recursion factorial(x: nat): RECURSIVE nat = IF x=0 THEN 1 ELSE factorial(x-1)*x ENDIF MEASURE (LAMBDA (x: nat): x) Used to prove that the function is total A
Expressions • LET Expressions LET i:T=e1 IN e2 • Useful for avoiding redundancy if e1 is used many times in e2 • Sugar for LAMBDA (LAMBDA (i: T): e2)(e1) • Example LET x=2 IN x*y is (LAMBDA x: x*y)(2)
Expressions • Override Expressions e WITH [(i1):=v1, (i2):=v2, …] • Sugar for LAMBDA LAMBDA x:IF x=i1 THEN v1ELSIF x=i2 THEN v2 …ELSE e(x) ENDIF • Also for records and tuples
Expressions • LET and WITH useful for some sequential program constructs! int f(int i) { int a[10]={ 0, … }; ... a[i]=5; ... return a[0]; } f(i: int):int= LET a1=LAMBDA (x: below(10)): 0 IN ... LET a2=a1 WITH [(i):=5] IN ... ai(0)
Expressions • Set Expressions • In PVS, sets are represented using their characteristic function [ T -> boolean ] same as setof[T] • Set expressions: { x:T | p(x) } For sets a, b over T: Union: a OR b Intersection: a AND b
Some Syntactic Sugar • Tuple types [ t1,…,tn ] • Tuple expressions (e1,…,en) • Comes with projections PROJ_1, PROJ_2, ..., PROJ_n
Example • stacks1: THEORY BEGIN • stack: TYPE = [int, ARRAY[int->int]] • empty: stack = (0, (LAMBDA (j: int): 0)) • size(s: stack):int = PROJ_1(s) • elements(s: stack):ARRAY[int->int] = PROJ_2(s) • push(x: int, s:stack): stack = • (size(s)+1, elements(s) WITH [(size(s)):=x]) • pop(s:stack): stack = (size(s)-1, elements(s)) • END stacks1 How abouta “struct”? A
Some Syntactic Sugar • Record types [#a1:t1,…,an:tn #] • Record expressions (#a1:=e1,…,an:=en#) • Comes with projections a1, a2, ..., an • Or: e`ai
Example stacks2: THEORY BEGIN stack: TYPE = [# size: int, elements: ARRAY[int->int] #] empty: stack = (# size:=0, elements:=(LAMBDA (j: int): 0) #) push(x: int, s:stack): stack = (# size:=s`size+1, elements:=s`elements WITH [(s`size):=x] #) pop(s:stack): stack = (# size:=s`size-1, elements:=s`elements #) END stacks2 What about the empty stack? A
Subtypes { x: T | p(x)} • p must be of type [ T -> boolean ] • Sugar for that: (p) • This type contains all elements x of Tfor which p(x) is true • E.g., define domain of integer division: { x: integer | x/=0 } • Makes type equivalence undecidable
Subtypes • Subtypes in binding expressions • Forall, exists: forall (i: int | i>10): … • Lambda: class_theory: THEORYBEGIN f(x: int | x/=0): real = 1/x END class_theory class_theory: THEORYBEGIN f: [ {x: int | x/=0 }->real] = LAMBDA (x: int | x/=0): 1/x END class_theory
Example stacks3: THEORY BEGIN stack: TYPE = [# size: nat, elements: ARRAY[nat->int] #] empty: stack = (# size:=0, elements:=(LAMBDA (j: nat): 0) #) push(x: int, s:stack): { s: stack | s`size>=1 } = (# size:=s`size+1, elements:=s`elements WITH [(s`size):=x] #) pop(s:stack | s`size>=1): stack = (# size:=s`size-1, elements:=s`elements #) END stacks3 Properties? A
Example stacks3: THEORY BEGIN stack: TYPE = [# size: nat, elements: ARRAY[nat->int] #] empty: stack = (# size:=0, elements:=(LAMBDA (j: nat): 0) #) push(x: int, s:stack): { s: stack | s`size>=1 } = (# size:=s`size+1, elements:=s`elements WITH [(s`size):=x] #) pop(s:stack | s`size>=1): stack = (# size:=s`size-1, elements:=s`elements #) push_pop: THEOREM FORALL (s: stack, x: int): pop(push(x, s))=s END stacks3 Does this work? A
Example stacks4: THEORY BEGIN stack: TYPE = [# size: nat, elements: ARRAY[{i:nat|i<size}->int] #] empty: stack = (# size:=0, elements:=(LAMBDA (j:nat| FALSE): 0) #) push(x: int, s:stack): { s: stack | s`size>=1 } = (# size:=s`size+1, elements:=LAMBDA (j: below(s`size+1)): IF j<s`size THEN s`elements(j) ELSE x ENDIF #) pop(s:stack | s`size>=1): stack = (# size:=s`size-1, elements:=LAMBDA (j:nat|j<s`size-1): s`elements(j) #) push_pop: THEOREM FORALL (s: stack, x: int): pop(push(x, s))=s END stacks4
Proof? • How to argue? pop(push(x, s)) = s • Let’s to the size component and the elements component separately • Size: pop(push(x, s))`size = s`size • Expand definition of pop: push(x, s)`size - 1 = s`size • Expanding the definition of push results in s`size+1-1=s`size
Proof? (2) • Elements: pop(push(x, s))`elements = s`elements • Expand definition of pop: ((j:nat|j<push(x, s)`size-1):push(x, s)`elements(j)) = s`elements • Expanding the definition of push results in ((j:nat|j<s`size):IF j<s`size THEN s`elements(j)ELSE x ENDIF= s`elements • Obviously, the condition of the IF is always true
What next… • Webpage! • Installation instructions for PVS • Further reading • Homework assignment