1 / 75

Implicit Programming

EPF Lausanne. Implicit Programming. http://lara.epfl.ch/w/impro . Viktor Kuncak. Joint w ork with. Sebastien Vasey. Ruzica Piskac. Philippe Suter. Tihomir Gvero. Mikaël Mayer. Ali Sinan Köksal. EPFL. Darko Marinov Milos Gligoric Vilas Jagannath UIUC Sarfraz Khurshid

melvyn
Télécharger la présentation

Implicit Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. EPF Lausanne Implicit Programming http://lara.epfl.ch/w/impro Viktor Kuncak

  2. Joint work with SebastienVasey Ruzica Piskac Philippe Suter TihomirGvero Mikaël Mayer Ali SinanKöksal EPFL DarkoMarinov Milos Gligoric Vilas Jagannath UIUC SarfrazKhurshid UT Austin Barbara Jobstmann Verimag JadHamza ENS Cachan

  3. Notion of Implicit Programming

  4. Calculus of numbers and functions (studied for centuries in real analysis)two tasks- compute y : F(x) = y?5∙72 + 2∙7 + 3 = y sin’(t) = y(t) - solve for x : F(x?) = y5∙x2 + 2∙x + 3 = 42 f ’(t) = cos(t) arithmetic derivatives algebraic equations differential equations

  5. Calculus of Programs Compute with numbers and with:lists, trees, sets, relations Again two tasks • compute the result y : F(x) = y? • today’s software (imperative and functional) • solve for x : F(x?) = y • verification: find input that crashes program, or invariants that prove correctness • synthesis: find program that satisfies the spec tomorrow’s software – implicit computation

  6. Programming Activity requirements Consider three related activities: • Development within an IDE (Eclipse, Visual Studio, emacs, vim) • Compilation and static checking(optimizing compiler for the language, static analyzer, contract checker) • Execution on a (virtual) machine More compute power available for each of these  use it to improve programmer productivity def f(x : Int) = { y = 2 * x + 1 } iload_0 iconst_1 iadd 42

  7. Implicit Programming • A high-level programming model • In addition to traditional constructs, useimplicit specificationsGive property of result, not how to compute it • More expressive, easier to argue correctness • Challenge: • make it executable and efficient, so it is useful • Claim: automated reasoning is a key technique

  8. Explicit Design Explicit = written down, machine readable Implicit = omitted, to be (re)discovered • Current practice: • explicit program code • implicit design (key invariants, properties) • Goal: • explicit design • implicit program Total work not increased, moreover • can be decreased for certain types of specifications • confidence in correctness higher –following design

  9. Example: Date Conversion Knowing number of days since 1980, find current year and day BOOL ConvertDays(UINT32 days, SYSTEMTIME* lpTime) { ...; year = 1980; while (days > 365) { if (IsLeapYear(year)) { if (days > 366) { days -= 366; year += 1; } } else { days -= 365; year += 1; } } • Enter December 31, 2008 • all music players of a major brand freeze

  10. Date Conversion in Kaplan System Let origin denote 1980. Choose year and day such that the property holds, where leadYearsUpto is defined by the given expression. val origin = 1980 val (year, day)=choose((year:Val[Int],day:Val[Int]) =>{ defleapYearsUpto(y : Tree[IntSort]) = (y - 1) / 4 - (y - 1) / 100 + (y - 1) / 400 totalDays== (year - origin) * 365 + leapYearsUpto(year)-leapYearsUpto(origin) + day && day > 0 &&day <= 366 }) • The implicit programming approach ensures both • termination and • correctness with respect to stated properties

  11. Implicit Programming at All Levels requirements Opportunities for implicit programming in • Development within an IDE • InSynth tool (CAV’11) • Compilation • Comfusy (PLDI’10) and RegSy(FMCAD’10) • Execution • UDITA (ICSE’10), Scala^Z3 (CADE’11),Kaplan def f(x : Int) = { choose y st... } iload_0 iconst_1 call Z3 42

  12. Overview of Our Tools&Prototypes InSynth(w/ T.Gvero, R. Piskac) • synthesize code fragments interactively within IDE Comfusy (w/ M.Mayer,R.Piskac,P.Suter) • compile specifications using quantifier elimination RegSy (w/ J. Hamza, B. Jobstmann) • compile specifications into very fast automata UDITA extension of Java Pathfinder • make non-deterministic choice variables symbolic Scala^Z3 (w/ P.Suter, A.S. Köksal, R.Steiger) • invoke Z3 from Scala and vice versa with nice syntax Kaplan (w/ A.S.Köksal, P.Suter) • constraint solving for constraints over Z3+executable functions • solution enumeration through `for’ comprehensions • logical variables with global constraint store

  13. Implicit (Programming Language) Constructs

  14. A concrete language Notation for functions in Scala x => x*x squaring function f, such that f(x)=x*x (x,y) => x+2*y example linear function of arguments x and y x => (x > 0) returning true iff the argument is positive (x,y) => x+y < 10 true if sum of its arguments is less than 10 (x,y) => x > 0 && y > 0 true if both arguments positive predicate: function of type (A1,...,An) => Boolean

  15. Algebraic Data Types and Pattern Matching Objective Caml type tree = Leaf | Node of tree*int*tree let recelemx t =match t with | Leaf -> false | Node(l,y,r) ->if x=y thentrue else if x<y then elemx lelseelemx r Scala abstract class Treecase class Leaf() extends Treecase class Node(left:Tree, data:Int, right:Tree) extends Tree defelem(x:Int,t:Tree):Boolean= t match {case Leaf() => falsecase Node(l,y,r) =>if (x==y) trueelse if (x<y) elem(x,l)elseelem(x,r) }

  16. Option Types abstract case class Option[T]case class None() extends Option[T]case class Some(x:T) extends Option[T] Example use of option types: lookup(x,myMap) match { caseNone() => print(“Nothing found”) caseSome(v) => print(“Found: “ + v) }

  17. Constraints Semantically, constraint is a predicate Syntactically, we specify them (for now) using 1) variable binding and 2) boolean expression x => (x*x==a) : Int => Boolean Here ‘a’ is parameter, some valid value of the language In general, constraint C is a function of form (x1,..., xn) => P(x1,..., xn, a1,...,an) : Intn=> Boolean where P has type Boolean Given values a1,...,an, the set of solutions of C isS(C) = {(x1,..., xn) | P(x1,..., xn, a1,...,an) }

  18. findAll and find C - a constraint S(C) - its solution set, S(C) = { x | C(x) } S(x => x > 5) = {5,6,7,8,...} 1) findAll(C) = S(C) findAll: (T => Boolean) => Set[T] We represent result of findAllas iterator and use a forloop for ((a,b) <- findAll((x,y)=> 0 < x && x < y && x + y < 10)) { println(“a = “ + a + “b = “ + b) } 2) find(C)=if S(C)={} then Noneelse Some(x) where x S(C) find: (T => Boolean) => Option[T] Example of use:find(x => (x*x==a)) match { case Some(v) => println(“Square root of a is” + v) caseNone() => println(“a is not a square of an integer”) }

  19. findvariations: choose and given // choose : (T => Boolean) => T defchoose(C : T => Boolean) : T = find(C) match { case Some(v) => v case None() => throw new Exception(“no solution”)} Example: println(choose(x => (x*x==a))) // print x such that x*x=a // given one x such that P(x), compute q(x); if none exists, compute r given(x => P(x)) have q(x) else r find(x => P(x)) match { case Some(y) => q(y) case None() => r } Example: given (k=> (2*k==a)) have kelse 3*k+1 given(_ => e) haveq else r  if (e) q else r

  20. Example of using choose defsecondsToTime(totalSeconds: Int) : (Int, Int, Int) = choose((h: Int, m: Int, s: Int) ⇒ ( h * 3600 + m * 60 + s == totalSeconds && 0 <= h && 0 <= m && m < 60 && 0 <= s && s < 60 )) 3787 seconds 1 hour, 3 mins. and 7 secs.

  21. What Pattern Matching Means sealed abstract class Treecase class Leaf() extends Treecase class Node(left:Tree, data:Int, right:Tree) extends Tree t match {case Leaf() => qcase Node(l,y,r) => r(l,y,r)}  if (t == Leaf()) q else if (t.isInstanceOf[Node]) r(t.left, t.data, t.right) else throw new Exception(“unhandled match case”) l,y,r. t == Node(l,y,r) • given _=>t == Leaf() have qelse given (l,y,r)=> t == Node(l,y,r) have r(l,y,r)elsethrow new Exception(“unhandled match case”)

  22. Generalized pattern matching by translation to given t match {case _: Leaf() => qcasel,y,r: Node(l,y,r) => r(l,y,r)} bound variables indicated explicitly, not by convention ... case v1,...,vn: pi(v1,...,vn) => qi(v1,...,vn) ... ... else given v1,...,vn => t==pi(v1,...,vn) haveqi(v1,...,vn) ...  t match { case _: Leaf() => ... casel,k,r: Node(l,2*k,r) => ... case l,k,r: Node(l,2*k+1,Node(l’,k+1,r’)) => ... }

  23. Halving Functions using given defhalfToZero(x:Int) : Int = given k=> x==2*k have k else given k=> x==2*k+1 && k >= 0 havek else given k=> x==2*k - 1 && k <0 havek else error } defhalfToMinusInf(x:Int) : Int = given k=> x==2*k havek else given k=> x==2*k+1 && k >= 0 havek else given k=> x==2*k+1 && k < 0 havek else error } Note: error can never happen

  24. More Implicit Programming Constructs

  25. First-class constraints

  26. Example using Scala^Z3 find triples of integers x, y, z such that x > 0, y > x, 2x + 3y <= 40, x · z = 3y2, and y is prime model enumeration (currently: negate previous) val results = for( (x,y)  findAll((x: Var[Int], y: Var[Int]) ) => x > 0 && y > x && x * 2 + y * 3 <= 40); ifisPrime(y); z findAll((z: Var[Int]) ) => x * z=== 3 *y *y)) yield(x, y, z) user’s Scala function λ Scala’s existing mechanism for composing iterations(reduces to standard higher order functions such as flatMap-s) • Use Scala syntax to construct Z3 syntax trees • a type system prevents certain ill-typed Z3 trees • Obtain models as Scala values • Can also write own plugin decision procedures in Scala

  27. Interpretation versus Compilation

  28. How to execute choose by invoking SMT solver at run time defsecondsToTime(totalSeconds: Int) : (Int, Int, Int) = choose((h: Var[Int], m: Var[Int], s: Var[Int]) ⇒ ( h * 3600 + m * 60 + s == totalSeconds && 0 <= h && 0 <= m && m < 60 && 0 <= s && s < 60 )) need to find will be known at run-time syntax tree constructor exec (Z3 “h * 3600 + m * 60 + s == 3787 && ...”) satmodel: h=1, m=3, s=7 3787 seconds This approach works for constraints in theories for which SMT solver is complete and provides model generation.

  29. Scala^Z3Invoking Constraint Solver at Run-Time Java VirtualMachine - functional and imperative code - custom ‘decision procedure’ plugins Z3 SMT Solver Q: implicit constraint A: model Q: queries containing extension symbols A: custom theoryconsequences with: Philippe Suter, Ali SinanKöksal

  30. UDITA: Non-deterministic Language void generateDAG(IG ig) { for (int i = 0; i < ig.nodes.length; i++) { intnum = chooseInt(0, i); ig.nodes[i].supertypes = new Node[num]; for (int j = 0, k = −1; j < num; j++) { k = chooseInt(k + 1, i − (num − j)); ig.nodes[i].supertypes[j] = ig.nodes[k]; } } } We used to it to generate tests and find real bugs injavac, JPF itself, Eclipse, NetBeans refactoring On top of Java Pathfinder’s backtracking mechanism Can enumerate all executions Key technique: suspended execution of non-determinism Java + choose - integers - (fresh) objects with: M. Gligoric, T. Gvero, V. Jagannath, D. Marinov, S. Khurshid

  31. Comparison of Runtime Approaches • Scala^Z3 is a library approach to using a constraint solving • efficient solving of given formulas • nice interface to Z3 from Scala • UDITA is an improved JavaPathfinder, a non-deterministic JVM (much slower than JVM) • Recent work: Kaplan • integrates non-determinism through for comprehensions (iterate over solutions) • supports symbolic logical variables (postpone solving) • has first class constraints, so subsumes Scala^Z3

  32. What would ideal code look like? defsecondsToTime(totalSeconds: Int) : (Int, Int, Int) = choose((h: Int, m: Int, s: Int) ⇒ ( h * 3600 + m * 60 + s == totalSeconds && h ≥ 0 && m ≥ 0 && m < 60 && s ≥ 0 && s < 60 )) defsecondsToTime(totalSeconds: Int) : (Int, Int, Int) = val t1 = totalSecondsdiv 3600 valt2 = totalSeconds -3600 * t1 valt3 = t2 div 60 valt4 = totalSeconds -3600 * t1 -60 * t3 (t1, t3, t4) Philippe Suter, PLDI’10 Mikaël Mayer Ruzica Piskac

  33. Comparing with runtime invocation Pros of synthesis Pros of runtime invocation Conceptually simpler Can use off-the-shelf solver for now can be more expressive and even faster but: • Change in complexity: time is spent at compile time • Solving most of the problem only once • Partial evaluation: we get a specialized decision procedure • No need to ship a decision procedure with the program valtimes = for (secs ← timeStats) yieldsecondsToTime(secs)

  34. Compilation using Variable Eliminationfor Linear Integer Arithmetic

  35. Implicit Programming at All Levels requirements Opportunities for implicit programming in • Development within an IDE • InSynth tool • Compilation • Comfusy and RegSytools • Execution • Scala^Z3and UDITA tools I next examine these tools, from last to first, focusing on Compilation def f(x : Int) = { choose y st... } iload_0 iconst_1 call Z3  42

  36. Possible starting point: quantifier elimination • A specification statement of the form r = choose(x ⇒ F( a, x )) “let r be x such that F(a, x) holds” • Corresponds to constructively solving thequantifier eliminationproblemwherea is a parameter • Witness terms from QE are the generated program! ∃ x . F( a, x )

  37. choose((x, y) ⇒ 5 * x + 7 * y == a && x ≤ y) Corresponding quantifier elimination problem: ∃ x ∃ y . 5x + 7y = a ∧ x ≤ y Use extended Euclid’s algorithm to find particular solution to 5x + 7y = a: (5,7 are mutually prime, else we get divisibility pre.) x = 3a y = -2a Express general solution of equationsfor x, y using a new variable z: x = -7z + 3a y = 5z - 2a Rewrite inequations x ≤ y in terms of z: 5a ≤ 12z z ≥ ceil(5a/12) Obtain synthesized program: valz = ceil(5*a/12) valx = -7*z + 3*a valy = 5*z + -2*a z = ceil(5*31/12) = 13 x = -7*13 + 3*31 = 2 y = 5*13 – 2*31 = 3 For a = 31:

  38. choose((x, y) ⇒ 5 * x + 7 * y == a && x ≤ y && x ≥ 0) Express general solution of equationsfor x, y using a new variable z: x = -7z + 3a y = 5z - 2a Rewrite inequations x ≤ y in terms of z: z ≥ ceil(5a/12) Rewrite x ≥ 0: z ≤ floor(3a/7) Precondition on a: ceil(5a/12) ≤ floor(3a/7) (exact precondition) Obtain synthesized program: assert(ceil(5*a/12) ≤ floor(3*a/7)) valz = ceil(5*a/12) valx = -7*z + 3*a valy = 5*z + -2*a With more inequalities and divisibility: generate ‘for’ loop

  39. NP-Hard Constructs • Disjunctions • Synthesis of a formula computes program and exact precondition of when output exists • Given disjunctive normal form, use preconditionsto generate if-then-else expressions (try one by one) • Divisibility combined with inequalities: • corresponding to big disjunction in q.e. ,we will generate a for loop with constant bounds(could be expanded if we wish)

  40. Methodology QE  Synthesis • Each quantifier elimination ‘trick’ we found corresponds to a synthesis trick • Find the corresponding terms • Key techniques: • one point rule immediately gives a term • change variables, using a computable function • strengthen formula while preserving realizability • recursively eliminate variables one-by one • Example use • transform formula into disjunction • strengthen each disjunct using equality • apply one-point rule

  41. General Form of Synthesized Functions for Presburger Arithmetic choose x such that F(x,a)  x = t(a) Result t(a) is expressed in terms of +, -, C*, /C, if Need arithmetic for solving equations Need conditionals for • disjunctions in input formula • divisibility and inequalities (find a witness meeting bounds and divisibility by constants) t(a) = if P1(a) t1(a) elseif … elseifPn(a) tn(a) else error(“No solution exists for input”,a)

  42. Basic Compile-Time Analysis

  43. Compile-time warnings defsecondsToTime(totalSeconds: Int) : (Int, Int, Int) = choose((h: Int, m: Int, s: Int) ⇒ ( h * 3600 + m * 60 + s == totalSeconds && h ≥ 0 && h < 24 && m ≥ 0 && m < 60 && s ≥ 0 && s < 60 )) Warning: Synthesis predicate is not satisfiable for variable assignment: totalSeconds = 86400

More Related