Top Banner
Implicit Programming Viktor Kuncak EPF Lausanne http://lara.epfl.ch/w/impro
75

Implicit Programming Viktor Kuncak EPF Lausanne .

Jan 02, 2016

Download

Documents

Amberlynn Rice
Welcome message from author
This document is posted to help you gain knowledge. Please leave a comment to let me know what you think about it! Share it to your friends and learn new things together.
Transcript
Page 1: Implicit Programming Viktor Kuncak EPF Lausanne .

Implicit ProgrammingViktor Kuncak

EPF Lausannehttp://lara.epfl.ch/w/impro

Page 2: Implicit Programming Viktor Kuncak EPF Lausanne .

Joint work with

Ruzica Piskac Philippe Suter Tihomir Gvero Mikaël Mayer Ali Sinan Köksal

Barbara JobstmannVerimag

Jad HamzaENS Cachan

EPFL

Sebastien Vasey

Darko MarinovMilos Gligoric

Vilas JagannathUIUC

Sarfraz KhurshidUT Austin

Page 3: Implicit Programming Viktor Kuncak EPF Lausanne .

Notion of Implicit Programming

Page 4: Implicit Programming Viktor Kuncak EPF Lausanne .

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?) = y 5∙x2 + 2∙x + 3 = 42 f ’(t) = cos(t)

arithmetic

derivatives

algebraic equations

differential equations

Page 5: Implicit Programming Viktor Kuncak EPF Lausanne .

Calculus of ProgramsCompute 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

Page 6: Implicit Programming Viktor Kuncak EPF Lausanne .

Programming Activity

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) machineMore compute power available for each of these use it to improve programmer productivity

requirements

def f(x : Int) = { y = 2 * x + 1}

iload_0iconst_1iadd

42

Page 7: Implicit Programming Viktor Kuncak EPF Lausanne .

Implicit Programming

• A high-level programming model• In addition to traditional constructs, use

implicit 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

Page 8: Implicit Programming Viktor Kuncak EPF Lausanne .

Explicit DesignExplicit = written down, machine readableImplicit = 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

Page 9: Implicit Programming Viktor Kuncak EPF Lausanne .

Example: Date ConversionKnowing number of days since 1980, find current year and dayBOOL 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, 2008all music players of a major brand freeze

Page 10: Implicit Programming Viktor Kuncak EPF Lausanne .

Date Conversion in Kaplan System

val origin = 1980

val (year, day)=choose((year:Val[Int],day:Val[Int]) => { def leapYearsUpto(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

Let origin denote 1980. Choose year and day such that the property holds, where leadYearsUpto is defined by the given expression.

Page 11: Implicit Programming Viktor Kuncak EPF Lausanne .

Implicit Programming at All Levels

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

requirements

def f(x : Int) = { choose y st ...}

iload_0iconst_1call Z3

42

Page 12: Implicit Programming Viktor Kuncak EPF Lausanne .

Overview of Our Tools&PrototypesInSynth (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

Page 13: Implicit Programming Viktor Kuncak EPF Lausanne .

Implicit (Programming Language) Constructs

Page 14: Implicit Programming Viktor Kuncak EPF Lausanne .

A concrete language

Notation for functions in Scalax => x*x squaring function f, such that f(x)=x*x(x,y) => x+2*y example linear function of arguments x and yx => (x > 0) returning true iff the argument is positive(x,y) => x+y < 10true 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

Page 15: Implicit Programming Viktor Kuncak EPF Lausanne .

Algebraic Data Types and Pattern Matching

Objective Camltype tree = Leaf | Node of tree*int*tree

let rec elem x t = match t with | Leaf -> false | Node(l,y,r) -> if x=y then true else if x<y then elem x l else elem x r

Scalaabstract class Treecase class Leaf() extends Treecase class Node(left:Tree, data:Int, right:Tree)

extends Treedef elem(x:Int,t:Tree):Boolean= t match { case Leaf() => false case Node(l,y,r) => if (x==y) true else if (x<y) elem(x,l) else elem(x,r)}

Page 16: Implicit Programming Viktor Kuncak EPF Lausanne .

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 { case None() => print(“Nothing found”) case Some(v) => print(“Found: “ + v)}

Page 17: Implicit Programming Viktor Kuncak EPF Lausanne .

ConstraintsSemantically, constraint is a predicateSyntactically, we specify them (for now) using 1) variable binding and 2) boolean expression

x => (x*x==a) : Int => BooleanHere ‘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 is S(C) = {(x1,..., xn) | P(x1,..., xn, a1,...,an) }

Page 18: Implicit Programming Viktor Kuncak EPF Lausanne .

findAll and findC - 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 findAll as iterator and use a for loop 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 None

else 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) case None() => println(“a is not a square of an integer”) }

Page 19: Implicit Programming Viktor Kuncak EPF Lausanne .

find variations: choose and given// choose : (T => Boolean) => Tdef choose(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 rgiven (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 k else 3*k+1

given (_ => e) have q else r if (e) q else r

Page 20: Implicit Programming Viktor Kuncak EPF Lausanne .

def secondsToTime(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 ))

Example of using choose

3787 seconds 1 hour, 3 mins. and 7 secs.

Page 21: Implicit Programming Viktor Kuncak EPF Lausanne .

What Pattern Matching Meanssealed abstract class Treecase class Leaf() extends Treecase class Node(left:Tree, data:Int, right:Tree) extends Treet match { case Leaf() => q case Node(l,y,r) => r(l,y,r)}if (t == Leaf()) qelse 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)else throw new Exception(“unhandled match case”)

Page 22: Implicit Programming Viktor Kuncak EPF Lausanne .

Generalized pattern matching by translation to given

t match { case _: Leaf() => q case l,y,r: Node(l,y,r) => r(l,y,r)}

bound variables indicated explicitly, not by convention

t match { case _: Leaf() => ... case l,k,r: Node(l,2*k,r) => ... case l,k,r: Node(l,2*k+1,Node(l’,k+1,r’)) => ...}

... case v1,...,vn: pi(v1,...,vn) => qi(v1,...,vn) ...

... else given v1,...,vn => t==pi(v1,...,vn) have qi(v1,...,vn) ...

Page 23: Implicit Programming Viktor Kuncak EPF Lausanne .

Halving Functions using given

def halfToZero(x:Int) : Int = given k=> x==2*k have k else given k=> x==2*k+1 && k >= 0 have k else given k=> x==2*k - 1 && k < 0 have k else error}def halfToMinusInf(x:Int) : Int = given k=> x==2*k have k else given k=> x==2*k+1 && k >= 0 have k else given k=> x==2*k+1 && k < 0 have k else error}Note: error can never happen

Page 24: Implicit Programming Viktor Kuncak EPF Lausanne .

More Implicit Programming Constructs

Page 25: Implicit Programming Viktor Kuncak EPF Lausanne .

First-class constraints

Page 26: Implicit Programming Viktor Kuncak EPF Lausanne .
Page 27: Implicit Programming Viktor Kuncak EPF Lausanne .
Page 28: Implicit Programming Viktor Kuncak EPF Lausanne .
Page 29: Implicit Programming Viktor Kuncak EPF Lausanne .

Example using Scala^Z3find triples of integers x, y, z such that x > 0, y > x,2x + 3y <= 40, x · z = 3y2, and y is prime

val results = for( (x,y) findAll((x: Var[Int], y: Var[Int]) ) => x > 0 && y > x && x * 2 + y * 3 <= 40); if isPrime(y); z findAll((z: Var[Int]) ) => x * z === 3 * y * y)) yield (x, y, z)

model enumeration (currently: negate previous)

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 treesa type system prevents certain ill-typed Z3 trees

Obtain models as Scala valuesCan also write own plugin decision procedures in Scala

Page 30: Implicit Programming Viktor Kuncak EPF Lausanne .

Interpretation versus Compilation

Page 31: Implicit Programming Viktor Kuncak EPF Lausanne .

def secondsToTime(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 ))

How to execute choose by invoking SMT solver at run time

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.

will be known at run-time

syntax tree constructor

need to find

Page 32: Implicit Programming Viktor Kuncak EPF Lausanne .

Scala^Z3Invoking Constraint Solver at Run-Time

Java Virtual Machine- functional and imperative code

- custom ‘decision procedure’ plugins

Z3 SMT Solver

Q: implicit constraint

A: model

A: custom theoryconsequences

Q: queries containing extension symbols

with: Philippe Suter, Ali Sinan Köksal

Page 33: Implicit Programming Viktor Kuncak EPF Lausanne .

UDITA: Non-deterministic Language

void generateDAG(IG ig) { for (int i = 0; i < ig.nodes.length; i++) { int num = 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 in

javac, JPF itself, Eclipse, NetBeans refactoringOn top of Java Pathfinder’s backtracking mechanismCan enumerate all executionsKey technique: suspended execution of non-determinism

Java + choose - integers - (fresh) objects

with: M. Gligoric, T. Gvero, V. Jagannath, D. Marinov, S. Khurshid

Page 34: Implicit Programming Viktor Kuncak EPF Lausanne .
Page 35: Implicit Programming Viktor Kuncak EPF Lausanne .

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

Page 36: Implicit Programming Viktor Kuncak EPF Lausanne .
Page 37: Implicit Programming Viktor Kuncak EPF Lausanne .
Page 38: Implicit Programming Viktor Kuncak EPF Lausanne .

def secondsToTime(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 ))

What would ideal code look like?

def secondsToTime(totalSeconds: Int) : (Int, Int, Int) = val t1 = totalSeconds div 3600 val t2 = totalSeconds -3600 * t1 val t3 = t2 div 60 val t4 = totalSeconds -3600 * t1 -60 * t3 (t1, t3, t4)

Ruzica Piskac Philippe Suter, PLDI’10Mikaël Mayer

Page 39: Implicit Programming Viktor Kuncak EPF Lausanne .

Comparing with runtime invocation

Pros of synthesis• 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

Pros of runtime invocation• Conceptually simpler

• Can use off-the-shelf solver• for now can be more

expressive and even faster• but:

val times = for (secs ← timeStats) yield secondsToTime(secs)

Page 40: Implicit Programming Viktor Kuncak EPF Lausanne .

Compilation using Variable Eliminationfor Linear Integer Arithmetic

Page 41: Implicit Programming Viktor Kuncak EPF Lausanne .

Implicit Programming at All Levels

Opportunities for implicit programming in• Development within an IDE

– InSynth tool• Compilation

– Comfusy and RegSy tools• Execution

– Scala^Z3 and UDITA tools

I next examine these tools, from last to first, focusing on Compilation

requirements

def f(x : Int) = { choose y st ...}

iload_0iconst_1call Z3

42

Page 42: Implicit Programming Viktor Kuncak EPF Lausanne .
Page 43: Implicit Programming Viktor Kuncak EPF Lausanne .

Possible starting point: quantifier elimination

• A specification statement of the form

• Corresponds to constructively solving the quantifier elimination problem

where a is a parameter• Witness terms from QE are the generated program!

r = choose(x F( a, x ))⇒

∃ x . F( a, x )

“let r be x such that F(a, x) holds”

Page 44: Implicit Programming Viktor Kuncak EPF Lausanne .

val z = ceil(5*a/12)val x = -7*z + 3*aval y = 5*z + -2*a

choose((x, y) 5 * x + 7 * y == a && x ≤ y)⇒

z = ceil(5*31/12) = 13x = -7*13 + 3*31 = 2y = 5*13 – 2*31 = 3

∃ x y . 5x + 7y = a x ≤ y∃ ∧

x = 3ay = -2a

Use extended Euclid’s algorithm to find particular solution to 5x + 7y = a: (5,7 are mutually prime, else we get divisibility pre.)Express general solution of equations for x, y using a new variable z:

x = -7z + 3ay = 5z - 2a

Rewrite inequations x ≤ y in terms of z: 5a ≤ 12z z ≥ ceil(5a/12)

Obtain synthesized program:

For a = 31:

Corresponding quantifier elimination problem:

Page 45: Implicit Programming Viktor Kuncak EPF Lausanne .

choose((x, y) 5 * x + 7 * y == a && x ≤ y && x ≥ 0)⇒

Express general solution of equations for x, y using a new variable z:

x = -7z + 3ay = 5z - 2a

Rewrite inequations x ≤ y in terms of z: z ≥ ceil(5a/12)

assert(ceil(5*a/12) ≤ floor(3*a/7))val z = ceil(5*a/12)val x = -7*z + 3*aval y = 5*z + -2*a

Obtain synthesized program:

z ≤ floor(3a/7)Rewrite x ≥ 0:

ceil(5a/12) ≤ floor(3a/7)Precondition on a:(exact precondition)

With more inequalities and divisibility: generate ‘for’ loop

Page 46: Implicit Programming Viktor Kuncak EPF Lausanne .

NP-Hard Constructs

• Disjunctions– Synthesis of a formula computes program and exact

precondition of when output exists– Given disjunctive normal form, use preconditions

to 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)

Page 47: Implicit Programming Viktor Kuncak EPF Lausanne .

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

Page 48: Implicit Programming Viktor Kuncak EPF Lausanne .

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, ifNeed arithmetic for solving equationsNeed 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 … elseif Pn(a) tn(a)

else error(“No solution exists for input”,a)

Page 49: Implicit Programming Viktor Kuncak EPF Lausanne .

Basic Compile-Time Analysis

Page 50: Implicit Programming Viktor Kuncak EPF Lausanne .

Compile-time warningsdef secondsToTime(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

Page 51: Implicit Programming Viktor Kuncak EPF Lausanne .

Compile-time warningsdef secondsToTime(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 ))

Warning: Synthesis predicate has multiple solutions for variable assignment: totalSeconds = 60Solution 1: h = 0, m = 0, s = 60Solution 2: h = 0, m = 1, s = 0

Page 52: Implicit Programming Viktor Kuncak EPF Lausanne .

Handling Data Structures

Page 53: Implicit Programming Viktor Kuncak EPF Lausanne .

Synthesis for setsdef splitBalanced[T](s: Set[T]) : (Set[T], Set[T]) = choose((a: Set[T], b: Set[T]) (⇒ a union b == s && a intersect b == empty && a.size – b.size ≤ 1 && b.size – a.size ≤ 1 ))

def splitBalanced[T](s: Set[T]) : (Set[T], Set[T]) = val k = ((s.size + 1)/2).floor val t1 = k val t2 = s.size – k val s1 = take(t1, s) val s2 = take(t2, s minus s1) (s1, s2) a

b

s

Page 54: Implicit Programming Viktor Kuncak EPF Lausanne .

Synthesis for non-linear arithmetic

def decomposeOffset(offset: Int, dimension: Int) : (Int, Int) = choose((x: Int, y: Int) (⇒ offset == x + dimension * y && 0 ≤ x && x < dimension ))

• The predicate becomes linear at run-time• Synthesized program must do case analysis on

the sign of the input variables• Some coefficients are computed at run-time

Page 55: Implicit Programming Viktor Kuncak EPF Lausanne .

Experience with Comfusy • Works well for examples we encountered

– Needed: synthesis for more expressive logics, to handle more examples

– seems ideal for domain-specific languages• Efficient for conjunctions of equations

(could be made polynomial)• Extends to synthesis with parametric coefficients• Extends to logics that reduce to Presburger

arithmetic (implemented for BAPA)

Page 56: Implicit Programming Viktor Kuncak EPF Lausanne .

Comfusy for Arithmetic

• Limitations of Comfusy for arithmetic:– Naïve handling of disjunctions– Blowup in elimination, divisibility constraints– Complexity of running synthesized code (from QE):

doubly exponential in formula size– Not tested on modular arithmetic, or on

synthesis with optimization objectives– Arbitrary-precision arithmetic with multiple

operations generates time-inefficient code– Cannot do bitwise operations (not in PA)

Page 57: Implicit Programming Viktor Kuncak EPF Lausanne .

Arithmetic Synthesis using Automata

Page 58: Implicit Programming Viktor Kuncak EPF Lausanne .

RegSy

Synthesis for regular specifications over unbounded domains

J. Hamza, B. Jobstmann, V. KuncakFMCAD 2010

Page 59: Implicit Programming Viktor Kuncak EPF Lausanne .

Synthesize Functions over Integers

• Given weight w, balance beam using weights 1kg, 3kg, and 9kg

• Where to put weights if w=7kg?

1 39

w

Page 60: Implicit Programming Viktor Kuncak EPF Lausanne .

Synthesize Functions over Integers

• Given weight w, balance beam using weights 1kg, 3kg, and 9kg

• Where to put weights if w=7kg?• Synthesize program that computes correct

positions of 1kg, 3kg, and 9kg for any w?

97

3 1

Page 61: Implicit Programming Viktor Kuncak EPF Lausanne .

Synthesize Functions over Integers

97

1,1,1

9393

,

993311

931931

931931

rlrlrl

rrrlllw

rrrlll

w

+ + + ++=++

that such ,,,,, for values (minimal) computes weight given that, function Synthesize

3 1

Assumption: Integers are non-negative

Page 62: Implicit Programming Viktor Kuncak EPF Lausanne .

Expressiveness of Spec Language

• Non-negative integer constants and variables • Boolean operators• Linear arithmetic operator• Bitwise operators• Quantifiers over numbers and bit positions

PAbit = Presburger arithmetic with bitwise operators WS1S= weak monadic second-order logic of one successor

(, c x)

(|, &, !)

( , ,)

Page 63: Implicit Programming Viktor Kuncak EPF Lausanne .

Problem FormulationGiven

– relation R over bit-stream (integer) variables in WS1S (PAbit)

– partition of variables into inputs and outputs

Constructs program that, given inputs, computescorrect output values, whenever they exist.

Unlike Church synthesis problem, we do not require causality (but if spec has it, it helps us)

Page 64: Implicit Programming Viktor Kuncak EPF Lausanne .

Basic Idea• View integers as finite (unbounded) bit-streams

(binary representation starting with LSB)• Specification in WS1S (PAbit)• Synthesis approach:

– Step 1: Compile specification to automaton over combined input/output alphabet (automaton specifying relation)

– Step 2: Use automaton to generate efficient function from inputs to outputs realizing relation

010001101010101010101010101101111111110101010101100000000010101010100011010101

Page 65: Implicit Programming Viktor Kuncak EPF Lausanne .

Inefficient but Correct Method

• Run over a deterministic automaton over inputs and outputs

• Becomes run of a non-deterministic if we look only at outputs

• Simulate all branches until the end of input• Successful branches indicate outputs that work

Page 66: Implicit Programming Viktor Kuncak EPF Lausanne .

WS1Sspec Mona

Synthesis:1. Det. automaton for spec over joint alphabet2. Project, determinize, extract lookup table

Execution: 1. Run A on input w and record trace2. Use table to run backwards and output

Our Approach: Precompute

Synthesized program: Automaton + lookup table

Input word

Output word

without losing backward information

Page 67: Implicit Programming Viktor Kuncak EPF Lausanne .

Experiments

• Linear scaling observed in length of input

No Example MONA (ms) Syn (ms) |A| |A’| 512b 1024b 2048b 4096b

1 addition 318 132 4 9 509 995 1967 3978

2 approx 719 670 27 35 470 932 1821 3641

3 company 8291 1306 58 177 608 1312 2391 4930

4 parity 346 108 4 5 336 670 1310 2572

5 mod-6 341 242 23 27 460 917 1765 3567

6 3-weights-min

26963 640 22 13 438 875 1688 3391

7 4-weights 2707 1537 55 19 458 903 1781 3605

8 smooth-4b 51578 1950 1781 955 637 1271 2505 4942

9 smooth-f-2b 569 331 73 67 531 989 1990 3905

10 smooth-b-2b 569 1241 73 342 169 347 628 1304

11 6-3n+1 834 1007 233 79 556 953 1882 4022

In 3 seconds solve constraint, minimizing the output; Inputs and outputs are of order 24000

Page 68: Implicit Programming Viktor Kuncak EPF Lausanne .

More on Compilation

• Essence: partial evaluation• Recent work: partially evaluate Simplex

– repeatedly solve same formula (with different parameters)

– obtaining orders of magnitude speedups• Work by Sebastien Vasey

Page 69: Implicit Programming Viktor Kuncak EPF Lausanne .

Implicit Programming at All Levels

Opportunities for implicit programming in• Development within an IDE

– InSynth tool• Compilation

– Comfusy and RegSy tools• Execution

– Scala^Z3 and UDITA tools

requirements

def f(x : Int) = { choose y st ...}

iload_0iconst_1call Z3

42

Page 70: Implicit Programming Viktor Kuncak EPF Lausanne .

Example

tool

all : SequenceInputStream =

Page 71: Implicit Programming Viktor Kuncak EPF Lausanne .

InSynth - Interactive Synthesis of Code Snippets

def map[A,B](f:A => B, l:List[A]): List[B] = { ... }def stringConcat(lst : List[String]): String = { ... }...def printInts(intList:List[Int], prn: Int => String): String =

Returned value:stringConcat(map (prn, intList))

Is there a term of given type in given environment?Monorphic: decidable. Polymorphic: undecidable

joint work with: Tihomir Gvero, Ruzica Piskac

Page 72: Implicit Programming Viktor Kuncak EPF Lausanne .

Program point

Max steps

Create clauses:- encode in FOL - assign weights

Find all visible symbols

Resolution algorithm with weights

…………………………………………………………………………………………………………………………………………………………………………………………………………………………………

Code snippets

Code Synthesis inside IDE

Page 73: Implicit Programming Viktor Kuncak EPF Lausanne .

Relationship to Verification

• Some functionality is best synthesized from specs– other: better implemented, verified (and put into library)

• Currently, no choice –must always implement– specifications and verification are viewed as overhead

• Goal: make specifications intrinsic part of programs, with clear benefits to programmers – they run!

• Example: write an assertion, not how to establish it• This will help both

– verifiability: document, not reverse-engineer the invariants– productivity: avoid writing messy implementation

Page 74: Implicit Programming Viktor Kuncak EPF Lausanne .

Conclusion: Implicit ProgrammingDevelopment within an IDE

– InSynth tool – theorem proving as code completion

Compilation– Comfusy : decision procedure synthesis procedure

Scala implementation for integer arithmetic, BAPA– RegSy : solving WS1S constraints

Execution– Scala^Z3 : constraint programming– UDITA: Java + choice as test generation language

Future: linked structures and distributed systemshttp://lara.epfl.ch/w/impro

Page 75: Implicit Programming Viktor Kuncak EPF Lausanne .

Runtime Invocation vs Compilation

Pros of synthesis• 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

Pros of runtime invocation• Conceptually simpler

• Can use off-the-shelf solver• for now can be more

expressive and even faster• but:

val times = for (secs ← timeStats) yield secondsToTime(secs)