Tower of Hanoi · Amb and search Review of analyzing interpreter Continuations and an...

37
1 Nondeterministic Evaluation CS 550 Programming Languages Jeremy Johnson

Transcript of Tower of Hanoi · Amb and search Review of analyzing interpreter Continuations and an...

1

Nondeterministic Evaluation

CS 550 Programming LanguagesJeremy Johnson

2

ThemeThis lecture explores a language feature that

provides for nondeterministic computing. It allows a declarative style of programming, that supports the “generate and test” paradigm, where the programmer provides what is to be computed and the underlying language implementation provides the control mechanism (search with backtracking) to carry out the computation.

Implementation relies on “continuations” which encapsulate control flow choices.

3

Outline

Motivating exampleAmb and searchReview of analyzing interpreterContinuations and an implementation of the

Amb Interpreter

4

Motivating Example(define (prime-sum-pair list1 list2)

(let ((a (an-element-of list1))(b (an-element-of list2)))

(require (prime? (+ a b)))(list a b)))

5

Motivating Example(define (search-prime-pairs L1 L2)

(define (search-fixed x L)(if (null? L) null

(if (prime? (+ x (first L)))(list x (first L) (+ x (first L)))(search-fixed x (rest L)))))

(if (null? L1)'()(let ((p (search-fixed (first L1) L2)))

(if (not (null? p)) p(search-prime-pairs (rest L1) L2))))) ;;; backtrack

> (search-prime-pairs '(1 3 5 8) '(20 35 110))'(3 20 23)

6

Motivating Example(define (search-all-prime-pairs L1 L2)

(define (search-fixed x L)(if (null? L) null

(if (prime? (+ x (first L)))(cons (list x (first L) (+ x (first L)))

(search-fixed x (rest L))) ;;; continue search(search-fixed x (rest L)))))

(if (null? L1) '()(let ((P (search-fixed (first L1) L2)))

(append P (search-all-prime-pairs (rest L1) L2)))))

> (search-all-prime-pairs '(1 3 5 8) '(20 35 110))'((3 20 23) (3 110 113) (8 35 43))

7

Motivating Example(define (all-pairs L1 L2)

(if (or (null? L1)(null? L2))null(append(map (lambda (x) (list (first L1) x)) L2)(all-pairs (rest L1) L2))))

> (filter (lambda (p) (prime? (+ (first p) (second p)))) (all-pairs '(1 3 5 8) '(20 35 110)))

'((3 20) (3 110) (8 35))

8

Motivating Example(define (all-pairs-streams L1 L2)

(if (or (stream-empty? L1)(stream-empty? L2))empty-stream(stream-append(stream-map (lambda (x) (list (stream-first L1) x)) L2)

(all-pairs-streams (stream-rest L1) L2))))

> (stream-first (stream-filter (lambda (p) (prime? (+ (first p) (second p)))) (all-pairs-streams '(1 3 5 8) '(20 35 110))))

'(3 20)

9

Motivating Example(define (prime-sum-pair list1 list2)

(let ((a (an-element-of list1))(b (an-element-of list2)))

(require (prime? (+ a b)))(list a b)))

;;; Amb-Eval input:(prime-sum-pair '(1 3 5 8) '(20 35 110));;; Starting a new problem;;; Amb-Eval value:(3 20)

10

Motivating Example;;; Amb-Eval input:(prime-sum-pair '(1 3 5 8) '(20 35 110));;; Starting a new problem;;; Amb-Eval value:(3 20);;; Amb-Eval input:try-again;;; Amb-Eval value:(3 110);;; Amb-Eval input:try-again;;; Amb-Eval value:(8 35)

;;; Amb-Eval input:try-again;;; There are no more values of(prime-sum-pair (quote (1 3 5 8)) (quote (20 35 110)));;; Amb-Eval input:(prime-sum-pair '(19 27 30) '(11 36 58));;; Starting a new problem;;; Amb-Eval value:(30 11)

11

Amb Construct

The (amb <e1> … <en>) “ambiguously” returns one of the values <ei>

Example(list (amb 1 2 3) (amb 'a 'b)) Chooses one of the following (1 a) (1 b) (2 a) (2 b) (3 a) (3 b)

12

Nondeterministic Branching

amb splits the computation into branches where computation continues on each branch with one possible value. amb is a non-deterministic choice point Failure causes backtrackingImplementation uses depth-first seach

“chronological backtracking”Driver loop can be prompted with “try-

again” to continue search for more solutions

13

Nondeterministic Selection(define (require p)

(if (not p) (amb))) ;;; (amb) fails

(define (an-element-of items)(require (not (null? items)))(amb (car items) (an-element-of (cdr items))))

(define (an-integer-starting-from n)(amb n (an-integer-starting-from (+ n 1))))

(define (naturals) (an-integer-starting-from 0))

Backtracking

(prime-sum-pair '(1 3 5 8) '(20 35 110))

(amb 1 3 5 8)

(amb 20 35 110) (amb 20 35 110) (amb 20 35 110) (amb 20 35 110)

1 3 58

2035

110

15

Logic ConstraintsBaker, Cooper, Fletcher, Miller, and Smith live on different floors of an apartment house that contains only five floors. Baker does not live on the top floor. Cooper does not live on the bottom floor. Fletcher does not live on either the top or the bottom floor. Miller lives on a higher floor than does Cooper. Smith does not live on a floor adjacent to Fletcher's. Fletcher does not live on a floor adjacent to Cooper's. Where does everyone live?

16

Logic Constraints(define (multiple-dwelling)

(let ((baker (amb 1 2 3 4 5))(cooper (amb 1 2 3 4 5))(fletcher (amb 1 2 3 4 5))(miller (amb 1 2 3 4 5))(smith (amb 1 2 3 4 5)))

(require(distinct? (list baker cooper fletcher miller smith)))

(require (not (= baker 5)))(require (not (= cooper 1)))(require (not (= fletcher 5)))(require (not (= fletcher 1)))(require (> miller cooper))(require (not (= (abs (- smith fletcher)) 1)))(require (not (= (abs (- fletcher cooper)) 1)))(list (list 'baker baker)

(list 'cooper cooper)(list 'fletcher fletcher)(list 'miller miller)(list 'smith smith))))

(multiple-dwelling)

=>

((baker 3) (cooper 2) (fletcher 4) (miller 5) (smith 1))

17

Implementation

Modify analyzing evaluatorEach execution procedure now takes three

arguments and environment and two functions called continuations to complete the computation Success continuation Failure continuation

If a value is returned the success continuation is called with that valueIf the evaluation results in a dead end, the failure

continuation is called

18

Continuations

The job of the success continuation is to receive a value and proceed with the computationThe job of the failure continuation is to try

another branchMay result from (amb)Try another non-deterministic choiceIf none, a failure at an earlier choice point is

triggered

19

Structure of Amb-eval A success continuation is a procedure of two

arguments: the value just obtained and another failure continuation to be used if that value leads to a subsequent failure.

A failure continuation is a procedure of no arguments

(define (ambeval exp env succeed fail)((analyze exp) env succeed fail))

(ambeval <exp>the-global-environment(lambda (value fail) value)(lambda () 'failed))

20

To Be Continued

21

Creating Iterators(define (make-it L)

(let ((Lp L))(lambda ()

(if (null? Lp)'fail(let ((val (first Lp)))

(begin (set! Lp (rest Lp)) val))))))

(define (until iter done?)(let ((p (iter)))(if (eq? p 'fail)

'fail(if (done? p) p (until iter done?)))))

22

Using Iterators> (define next (make-it '(12 18 21)))> (next)12> (next)18> (next)21> (next)'fail> (define next (make-it '(12 18 21 23 33 37)))> (until next prime?)23

23

Motivating Example(define (it-pairs L1 L2)

(let ((L1p L1) (L2p L2))(lambda ()(if (or (null? L1) (null? L2)) 'fail(if (not (null? L2p))

(let ((val (list (first L1p) (first L2p))))(begin (set! L2p (rest L2p)) val))

(begin (set! L2p L2) (set! L1p (rest L1p))(if (null? L1p)

'fail(let ((val (list (first L1p) (first L2p))))(begin (set! L2p (rest L2p)) val)))))))))

24

Motivating Example> (define next-pair (it-pairs '(1 3 5 8) '(20 35 110)))

> (until next-pair (lambda (p) (prime? (+ (first p) (second p)))))

'(3 20)

25

Iterator with Continuation(define (make-continue-it L testp)

(let ((Lp L)) (lambda (succeed fail)(define (try-next Lp)

(if (null? Lp)(fail)(testp (first Lp) succeed (lambda () (try-next (cdr Lp))))))

(try-next L))))

26

Using Continuations(define (testodd? x succeed fail)

(if (odd? x) (succeed x fail) (fail)))

> (define it (make-continue-it '(2 5 4 7) testodd?))> (it (lambda (val fail) val) (lambda () 'fail))5> (it (lambda (val fail) (display val) (newline) (fail)) (lambda () 'fail))57'fail> (it (lambda (val fail) (cons val (fail))) (lambda () '()))'(5 7)

27

ResumeImplementing ambeval

28

Analyzing Interpreter(define (eval exp env)((analyze exp) env))

(define (analyze exp)(cond ((self-evaluating? exp)

(analyze-self-evaluating exp))((quoted? exp) (analyze-quoted exp))((variable? exp) (analyze-variable exp))((assignment? exp) (analyze-assignment exp))((definition? exp) (analyze-definition exp))((if? exp) (analyze-if exp))((lambda? exp) (analyze-lambda exp))((begin? exp) (analyze-sequence (begin-actions exp)))((cond? exp) (analyze (cond->if exp)))((application? exp) (analyze-application exp))(else(error "Unknown expression type -- ANALYZE" exp))))

29

Simple Expressions(define (analyze-self-evaluating exp)(lambda (env) exp))

(define (analyze-variable exp)(lambda (env) (lookup-variable-value exp env)))

(define (analyze-assignment exp)(let ((var (assignment-variable exp))

(vproc (analyze (assignment-value exp))))(lambda (env)(set-variable-value! var (vproc env) env)'ok)))

30

Conditional(define (analyze-if exp)(let ((pproc (analyze (if-predicate exp)))

(cproc (analyze (if-consequent exp)))(aproc (analyze (if-alternative exp))))

(lambda (env)(if (true? (pproc env))

(cproc env)(aproc env)))))

(define (analyze-lambda exp)(let ((vars (lambda-parameters exp))

(bproc (analyze-sequence (lambda-body exp))))(lambda (env) (make-procedure vars bproc env))))

; analyze-sequence composes the functions in the sequence

31

Amb Interpreter(define (ambeval exp env succeed fail)((analyze exp) env succeed fail))

(define (analyze exp)(cond ((self-evaluating? exp)

(analyze-self-evaluating exp))((quoted? exp) (analyze-quoted exp))((variable? exp) (analyze-variable exp))((assignment? exp) (analyze-assignment exp))((definition? exp) (analyze-definition exp))((if? exp) (analyze-if exp))((lambda? exp) (analyze-lambda exp))((begin? exp) (analyze-sequence (begin-actions exp)))((cond? exp) (analyze (cond->if exp)))((let? exp) (analyze (let->combination exp))) ;**((amb? exp) (analyze-amb exp)) ;**((application? exp) (analyze-application exp))(else(error "Unknown expression type -- ANALYZE" exp))))

32

Calling Amb Interpreter(define (ambeval exp env succeed fail)((analyze exp) env succeed fail))

(ambeval expthe-global-environment(lambda (val fail) val)(lambda () ‘fail))

33

Simple Expressions(define (analyze-self-evaluating exp)

(lambda (env succeed fail)(succeed exp fail)))

(define (analyze-variable exp)(lambda (env succeed fail)(succeed (lookup-variable-value exp env)

fail)))

34

Conditionals(define (analyze-if exp)

(let ((pproc (analyze (if-predicate exp)))(cproc (analyze (if-consequent exp)))(aproc (analyze (if-alternative exp))))

(lambda (env succeed fail)(pproc env

;; success continuation for evaluating the predicate;; to obtain pred-value(lambda (pred-value fail2)

(if (true? pred-value)(cproc env succeed fail2)(aproc env succeed fail2)))

;; failure continuation for evaluating the predicatefail))))

35

Assignment(define (analyze-assignment exp)(let ((var (assignment-variable exp))

(vproc (analyze (assignment-value exp))))(lambda (env succeed fail)(vproc env

(lambda (val fail2) ; *1*(let ((old-value

(lookup-variable-value var env))) (set-variable-value! var val env)(succeed 'ok

(lambda () ; *2*(set-variable-value! var

old-valueenv)

(fail2)))))fail))))

36

Amb(define (analyze-amb exp)

(let ((cprocs (map analyze (amb-choices exp))))(lambda (env succeed fail)

(define (try-next choices)(if (null? choices)

(fail)((car choices) env

succeed(lambda ()

(try-next (cdr choices))))))(try-next cprocs))))

37

Driver Loop(define (driver-loop)(define (internal-loop try-again)

(prompt-for-input input-prompt)(let ((input (read)))(if (eq? input 'try-again)

(try-again)(begin(newline)(display ";;; Starting a new problem ")(ambeval input

the-global-environment;; ambeval success(lambda (val next-alternative)(announce-output output-prompt)(user-print val)(internal-loop next-alternative))

;; ambeval failure(lambda ()(announce-output";;; There are no more values of")(user-print input)(driver-loop)))))))

(internal-loop(lambda ()(newline)(display ";;; There is no current problem")(driver-loop))))