A Modular Way to Reason About Iteration

Similar documents
Why3 A Multi-Prover Platform for Program Verification

Producing All Ideals of a Forest, Formally (Verification Pearl)

Deductive Program Verification with Why3

Why3 where programs meet provers

Why3 Where Programs Meet Provers

Deductive Program Verification with WHY3

Deductive Program Verification with Why3 A Tutorial

Why. an intermediate language for deductive program verification

Simple proofs of simple programs in Why3

Formal Verification of MIX Programs

An Introduction to Deductive Program Verification

L R I BACKTRACKING ITERATORS FILLIATRE J C. Unité Mixte de Recherche 8623 CNRS-Université Paris Sud LRI 01/2006. Rapport de Recherche N 1428

Verifying Two Lines of C with Why3: An Exercise in Program Verification

Deductive Program Verification with Why3, Past and Future

A Simple Supercompiler Formally Verified in Coq

Combining Coq and Gappa for Certifying FP Programs

Coq. LASER 2011 Summerschool Elba Island, Italy. Christine Paulin-Mohring

Let s Verify This with Why3

Reminder of the last lecture. Aliasing Issues: Call by reference, Pointer programs. Introducing Aliasing Issues. Home Work from previous lecture

A Formally Proved, Complete Algorithm for Path Resolution with Symbolic Links

Deductive Verification in Frama-C and SPARK2014: Past, Present and Future

Formal Verification of Floating-Point programs

Improving Coq Propositional Reasoning Using a Lazy CNF Conversion

Formally-Proven Kosaraju s algorithm

Backtracking Iterators

Semi-Persistent Data Structures

CIS 120 Midterm I February 16, 2015 SOLUTIONS

CIS 120 Midterm I October 2, Name (printed): Username (login id):

Datatype declarations

arxiv: v1 [cs.lo] 29 Oct 2018

The fringe of a binary tree are the values in left-to-right order. For example, the fringe of the following tree:

A Formal Proof of a Unix Path Resolution Algorithm

CIS 500 Software Foundations. Midterm I. (Standard and advanced versions together) October 1, 2013 Answer key

Verifying Java Programs. Verifying Java Programs. The Krakatoa/Why Tool Suite

Verifying Java Programs

First-Class Type Classes

How to get an efficient yet verified arbitrary-precision integer library

Inductive data types (I)

6. Hoare Logic and Weakest Preconditions

A Functional Implementation of the Garsia Wachs Algorithm

The Why3 platform. Version 0.81, March 2013

CIS 500: Software Foundations

SOFTWARE VERIFICATION AND COMPUTER PROOF (lesson 1) Enrico Tassi Inria Sophia-Antipolis

Readable semi-automatic formal proofs of Depth-First Search in graphs using Why3

Why3: Shepherd Your Herd of Provers

Jonathan Protzenko (INRIA)

Playing with Fun. Walter Cazzola. Playing with Fun currying partial evaluation map&reduce iteration var args. References.

15 212: Principles of Programming. Some Notes on Continuations

Index. Cambridge University Press Functional Programming Using F# Michael R. Hansen and Hans Rischel. Index.

INF121: Functional Algorithmic and Programming

CSCI-GA Scripting Languages

Formal Proofs of Tarjan s Algorithm in Why3, Coq, and Isabelle

Numerical Computations and Formal Methods

Inductive data types

Defining the Ethereum Virtual Machine for Interactive Theorem Provers

Writing and analyzing system policies in SUPPL

Clock-directed Modular Code-generation for Synchronous Data-flow Languages

Python Iterators. Stéphane Vialette. LIGM, Université Paris-Est Marne-la-Vallée. October 19, 2011

Wellesley College CS251 Programming Languages Spring, 2000 FINAL EXAM REVIEW PROBLEM SOLUTIONS

OCaml. ML Flow. Complex types: Lists. Complex types: Lists. The PL for the discerning hacker. All elements must have same type.

Implementing hash-consed structures in Coq

ML Type Inference and Unification. Arlen Cox

A Short Introduction to OCaml

02157 Functional Programming. Michael R. Ha. Disjoint Unions and Higher-order list functions. Michael R. Hansen

The Matrix Reproved (Verification Pearl)

How to get an efficient yet verified arbitrary-precision integer library

Programming with (co-)inductive types in Coq

MoreIntro.v. MoreIntro.v. Printed by Zach Tatlock. Oct 07, 16 18:11 Page 1/10. Oct 07, 16 18:11 Page 2/10. Monday October 10, 2016 lec02/moreintro.

Data structure and algorithm in Python

An intuitionistic proof of a discrete form of the Jordan Curve Theorem formalized in Coq with combinatorial hypermaps

Call-by-name evaluation

Automatically verified implementation of data structures based on AVL trees

Abstract Interpretation Using Laziness: Proving Conway s Lost Cosmological Theorem

A constructive denotational semantics for Kahn networks in Coq

02157 Functional Programming. Michael R. Ha. Tagged values and Higher-order list functions. Michael R. Hansen

Generating Small Countermodels. Andrew Reynolds Intel August 30, 2012

CS 320 Homework One Due 2/5 11:59pm

Automated Reasoning. Natural Deduction in First-Order Logic

Streams. CS21b: Structure and Interpretation of Computer Programs Spring Term, 2004

Vector Clocks in Coq

Introduction to OCaml

Pretty-Big-Step Semantics

Verified Characteristic Formulae for CakeML. Armaël Guéneau, Magnus O. Myreen, Ramana Kumar, Michael Norrish April 27, 2017

Recap: Functions as first-class values

Verifying Java Programs Verifying Java Programs with KeY

DAG-Calculus: A Calculus for Parallel Computation

News. Programming Languages. Complex types: Lists. Recap: ML s Holy Trinity. CSE 130: Spring 2012

Imperative programming in F#

CSE-321 Programming Languages 2011 Final

1. true / false By a compiler we mean a program that translates to code that will run natively on some machine.

Strongly Connected Components in graphs, formal proof of Tarjan1972 algorithm

CIS 500: Software Foundations

MoreIntro_annotated.v. MoreIntro_annotated.v. Printed by Zach Tatlock. Oct 04, 16 21:55 Page 1/10

The University of Nottingham

CIS 500: Software Foundations

Object Ownership in Program Verification

Induction in Coq. Nate Foster Spring 2018

02157 Functional Programming Tagged values and Higher-order list functions

August 5-10, 2013, Tsinghua University, Beijing, China. Polymorphic types

Transcription:

A Modular Way to Reason About Iteration Jean-Christophe Filliâtre Mário Pereira LRI, Univ. Paris-Sud, CNRS, Inria Saclay INRIA Paris - Séminaire Gallium Mars 7, 2016

iteration iteration: hello old friend! many different forms of iteration cursors higher-order functions (fold, iter) streams etc. our goal: specify and verify the enumeration of a collection of elements. in this work : cursors and higher-order iterators

specify a specification that takes into account either finite or infinite iterations either deterministic or non-deterministic iterations traversal of a possibly mutable collection not necessarily the traversal of a data structure

verify verify programs implementing an iteration (producers) using an iteration (consumers) abstraction: consumer verified without any knowledge about the implementation of the producer

a proposal iteration formalized with two predicates completed indicates whether we are done with the enumeration enumerated characterizes the elements already produced so far v 0 v 1 v n 1 }{{} already enumerated to come {}}{?????

example: array traversal of an array enumerated v a completed v a def = i. 0 i < v = v[i] = a[i] = def v = a

example: set non-deterministic traversal of a set enumerated v s completed v s def = distinct v x. x v = x s def = v = card(s) deterministic traversal enumerated v s completed v s def = prefix v (to seq s) def = v = card(s)

example: iterated function enumerated v (x 0, f ) completed v (x 0, f ) def = i. 0 i < v = v[i] = f i (x 0 ) def = false x 0, f (x 0 ), f (f (x 0 )), f (f (f (x 0 ))),...

example: channel scanner elements of v are characters character EOF marks the end of the channel enumerated v c completed v c def =... i. 0 i < v 1 = v[i] EOF = def v > 0 v[ v 1] = EOF

example: symbol generator to generate, at each step, a fresh symbol enumerated v () completed v () def = distinct v def = false

experimental validation with Why3

why3 file.mlw file.why VCgen WhyML Why transform/translate print/run Coq Alt-Ergo CVC4 Z3 etc. http://why3.lri.fr/

v 0 v 1 v n 1 cursors in a picture

cursors in a picture v 0 v 1 v n 1 C

cursors in a picture v 0 v 1 v n 1 C next C = v 0

cursors in a picture v 0 v 1 v n 1 C next C = v 0 next C = v 1

cursors in a picture v 0 v 1 v n 1 C next C = v 0 next C = v 1... next C = v n 2

cursors in a picture v 0 v 1 v n 1 C next C = v 0 next C = v 1... next C = v n 2 next C = v n 1 c create_cursor (...) while has_next(c) do x next(c)...

cursor specification type elt type collection type cursor model { mutable visited : seq elt; collection: collection; }

cursor specification type elt type collection type cursor model { mutable visited : seq elt; collection: collection; } predicate enumerated cursor predicate completed cursor

cursor specification type elt type collection type cursor model { mutable visited : seq elt; collection: collection; } predicate enumerated cursor predicate completed cursor val has_next (c: cursor) : bool requires { enumerated c } ensures { result not (completed c) }

cursor specification type elt type collection type cursor model { mutable visited : seq elt; collection: collection; } predicate enumerated cursor predicate completed cursor val has_next (c: cursor) : bool requires { enumerated c } ensures { result not (completed c) } val next (c: cursor) : elt requires { enumerated c } requires { not (completed c) } writes { c } ensures { enumerated c } ensures { c.visited = snoc (old c.visited) result }

verification example 1 specify the in-order traversal of a binary tree 2 realize it using a cursor 3 application to the same fringe problem

type tree = Empty Node tree elt tree 1. specify the in-order traversal function elements (t : tree) : seq elt = match t with Empty empty Node l x r elements l ++ cons x (elements r) end X 1 X 4 X 2 X 3

type tree = Empty Node tree elt tree 1. specify the in-order traversal function elements (t : tree) : seq elt = match t with Empty empty Node l x r elements l ++ cons x (elements r) end predicate enumerated (c: cursor) = prefix c.visited (elements c.collection) predicate completed (c: cursor) = length c.visited = length (elements c.collection)

2. realize the in-order traversal with a cursor type enum = Done Next elt tree enum type cursor = { ghost mutable visited: seq elt; mutable enum: enum; collection: tree; } visited enum

2. realize the in-order traversal with a cursor type enum = Done Next elt tree enum type cursor = { ghost mutable visited: seq elt; mutable enum: enum; collection: tree; } visited enum function enum_elements (e: enum) : seq elt = match e with Done empty Next x r e cons x (elements r ++ enum_elements e) end predicate enumerated (c: cursor) = elements c.collection = c.visited ++ enum_elements c.enum

3. application to the same fringe problem decide whether two trees have the same in-order elements let same_fringe (t1 t2: tree) : bool ensures { result elements t1 = elements t2 } X 1 X 4 X 4 X 1 X 2 X 3 X 2 X 3

3. application to the same fringe problem decide whether two trees have the same in-order elements let same_fringe (t1 t2: tree) : bool ensures { result elements t1 = elements t2 } = eq_cursors (create_cursor t1) (create_cursor t2) X 1 X 4 X 4 X 1 X 2 X 3 X 2 X 3

3. application to the same fringe problem decide whether two trees have the same in-order elements let rec eq_cursors (c1 c2: cursor) : bool... = match has_next c1, has_next c2 with False, False True True, True next c1 = next c2 && eq_cursors c1 c2 _ False end

demo same fringe

higher-order iterators iter: (elt unit) collection unit traditional approach: higher-order (program) logic alternative: enumerated / completed predicates how: translate higher-order iterators into first-order Why3 code

verifying HO iterator - specification type list = Nil Cons elt list let rec iter (f: elt unit) (l: list) = match l with Nil () Cons x l f x; iter f l end

verifying HO iterator - specification type list = Nil Cons elt list let rec iter (f: elt unit) (l: list) with { enumerated (visited, t) =... completed (visited, t) =... } = match l with Nil () Cons x l f x; iter f l end

verifying HO iterator - translation val visited: ref (seq elt) let iter_correct (l0: list) requires {!visited == empty } requires { enumerated (empty, l0) } ensures { enumerated (!visited, l0) } ensures { completed (!visited, l0) } = let f x = visited := snoc!visited x in let rec iter0 (l: list) : unit = match l with Nil () Cons x l f x; iter0 l end in iter0 l0

demo iter

using HO iterator - specification let uniq (l: list) ensures { distinct result } ensures { forall x. mem x result mem x l } = let h = H.create () in let r = ref Nil in iter (fun x!r if not (H.mem x h) then begin H.add x h; r := Cons x!r end) l;

using HO iterator - specification let uniq (l: list) ensures { distinct result } ensures { forall x. mem x result mem x l } = let h = H.create () in let r = ref Nil in iter (fun x (* user loop invariant *) if not (H.mem x h) then begin H.add x h; r := Cons x!r end) l;!r

using HO iterator - specification let uniq (l: list) ensures { distinct result } ensures { forall x. mem x result mem x l } = let h = H.create () in let r = ref Nil in iter (fun (ghost v) x (* user loop invariant *) if not (H.mem x h) then begin H.add x h; r := Cons x!r end) l;!r

using HO iterator - specification let uniq (l: list) ensures { distinct result } ensures { forall x. mem x result mem x l } = let h = H.create () in let r = ref Nil in iter (fun (ghost v) x invariant { distinct!r } invariant { forall x. mem x v mem x!r } invariant { forall x. H.contains h x mem x!r } if not (H.mem x h) then begin H.add x h; r := Cons x!r end) l;!r

using HO iterator - translation replace iter with a cursor: let uniq_correct (l: list elt) : list elt ensures { distinct result } ensures { forall x. mem x result mem x l } = let h = H.create () in let r = ref Nil in let _c = create_cursor l in!r

using HO iterator - translation replace iter with a cursor: let uniq_correct (l: list elt) : list elt ensures { distinct result } ensures { forall x. mem x result mem x l } = let h = H.create () in let r = ref Nil in let _c = create_cursor l in while has_next _c do invariant { enumerated _c } invariant { let v = _c.visited in...user loop invariant... } let x = next _c in if not (H.mem x h) then begin H.add x h; r := Cons x!r end done;!r

demo uniq

summary a modular way to specify iteration verification of programs realizing / using iterators with Why3 Why3 source code available at http://www.lri.fr/~mpereira/iteration/

in the future soundness proof of higher-order iterators proof method application to other higher-order iterators fold: (elt a a) collection a a verify realistic code making heavy use of higher-order iterators (e.g. OCamlGraph s code)

more details in Itérer avec confiance J.-C. Filliâtre and M. Pereira JFLA 16 https://hal.inria.fr/hal-01240891 A Modular Way to Reason About Iteration J.-C. Filliâtre and M. Pereira submitted to NFM 16 https://hal.inria.fr/hal-01281759

questions?