基于分析的amb求值器,及其分析

来源:互联网 发布:esp8266 51单片机例程 编辑:程序博客网 时间:2024/04/28 02:39

一下代码在mit-scheme下解释并编译通过。e并完成基本功能测试。敲打敲打发火

这个解释器在原SICP基础上加入了require和let的基本形式,,,,,大哭大哭

;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;other Codes
(define (length items)
 (if (null? items)
     0
     (+ 1 (length (cdr items)))))
(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 'miller miller)
         (list 'smith smith))))
(define (require p)
  (if (not p) (amb)))
(define (am-element-of items)
   (require (not (null? items)))
   (amb (car items) (am-element-of (cdr items)))) 
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;求值器的内核部分
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;     ambeval  的定义
(define (ambeval exp env succeed fail)
   ((analyze exp) env succeed fail))
(define (analyze exp)
   (cond ((self-evaluation? exp)
          (analyze-self-evaluating exp))
         ((quoted? exp) (analyze-quoted exp))
         ((let? exp) (let->combinition (let-pairs exp)
                                       (let-body 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)))
         ((require? exp) (analyze-require exp))
         ((amb? exp) (analyze-amb exp))
         ((application? exp) (analyze-application exp))
         (else
            (error "unknwn expression type --ANLYZE" exp))))
            
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
(define (analyze-self-evaluating exp)
  (lambda (env succeed fail)
    (succeed exp fail)))
(define (analyze-quoted exp)
   (let ((qval (text-of-quotation exp)))
     (lambda (env succeed fail)
       (succeed qval fail))))
(define (analyze-variable exp)
  (lambda (env succeed fail)
    (succeed (lookup-variable-value exp env)
             fail)))
(define (analyze-lambda exp)
  (let ((vars (lambda-parameters exp))
        (bproc (analyze-sequence (lambda-body exp))))
     (lambda (env succeed fail)
       (succeed (make-procedure vars bproc env)
               fail))))
;;;;;;;;;;;;;;;
(define (let->combinition pairs body)
    (let ((let-vars (get-make-var-pairs pairs))
          (let-exps (get-make-exp-pairs pairs)))
       (analyze (make-lambda-procedure let-vars body let-exps))))
(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
               (lambda (pred-value fail2)
                  (if (true? pred-value)
                      (cproc env succeed fail2)
                      (aproc env succeed fail2)))
               fail)))) 
(define (analyze-sequence exps)
   (define (sequentially a b)
      (lambda (env succeed fail)
         (a env
            (lambda (a-value fail2)
              (display a-value)
             (b env succeed fail2))
            fail)))
   (define (loop first-proc rest-procs)
      (if (null? rest-procs)
          first-proc
          (loop (sequentially first-proc (car rest-procs))
                (cdr rest-procs))))
    (let ((procs (map analyze exps)))
       (if (null? procs)
           (error "Empty sequence --ANALYZE"))
       (loop (car procs) (cdr procs))))
(define (analyze-definition exp)
   (let ((var (definition-variable exp))
         (vproc (analyze (definition-value exp))))
     (lambda (env succeed fail)
        (vproc env
               (lambda (val fail2)
                   (define-variable! var val env)
                   (succeed 'ok fail2))
               fail))))
(define (analyze-assignment exp)
   (let ((var (assignment-variable exp))
         (vproc (analyze (assignment-value exp))))
     (lambda (env succeed fail)
        (vproc env
               (lambda (val fail2)
                  (let ((old-value
                          (lookup-variable-value var env)))
                    (set-variable-value! var val env)
                    (succeed 'ok
                             (lambda ()
                               (set-variable-value! var 
                                                    old-value
                                                    env)
                             (fail2)))))
               fail))))
(define (analyze-application exp)
   (let ((fproc (analyze (operator exp)))
         (aprocs (map analyze (operands exp))))
      (lambda (env succeed fail)
         (fproc env
                (lambda (proc fail2)
                  (get-args aprocs
                            env
                            (lambda (args fail3)
                              (execute-application
                                 proc args succeed fail3))
                            fail2))
                fail))))
(define (get-args aprocs env succeed fail)
    (if (null? aprocs)
        (succeed () fail)
        ((car aprocs) env
                      (lambda (arg fail2)
                         (display arg)
                         (get-args (cdr aprocs)
                                   env
                                   (lambda (args fail3)
                                      (succeed (cons arg args)
                                               fail3))
                                   fail2))
                      fail)))
(define (execute-application proc args succeed fail)
   (cond ((primitive-procedure? proc)
          (succeed (apply-primitive-procedure proc args)
                   fail))
         ((compound-procedure? proc)
           ((procedure-body proc)
             (extend-environment (procedure-parameters proc)
                                 args
                                 (procedure-environment proc))
             succeed
             fail))
         (else
           (error 
              "unknown procedure type -- EXECUTE-APPLICATION"
              proc))))
(define (analyze-amb exp)
   (let ((cprocs (map analyze (amb-choices exp))))
     (lambda (env succeed fail)
        (define (try-next choices)
          (if (null? choices)
          ;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;changed
              (begin (display "Fail procedure was called") (fail))
              ((car choices) env
                             succeed
                             (lambda ()
                                 (try-next (cdr choices))))))
        (try-next cprocs))))
(define (analyze-require exp)
      (let ((pproc (analyze (require-predicate exp))))
        (lambda (env succeed fail)
           (pproc env
                  (lambda (pred-value fail2)
                     (if (not pred-value)
                         (fail2)
                         (succeed 'ok fail2)))
                  fail))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;         赋值和定义
(define (assignment? exp)
    (tagged-list? exp 'set!))
(define (assignment-variable exp) (cadr exp))
(define (assignment-value exp) (caddr exp))


;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 表达式的表示
(define (require? exp) (tagged-list? exp 'require))
(define (require-predicate exp) (cadr exp))


(define (self-evaluation? exp)
   (cond ((number? exp) true)
         ((string? exp) true)
         (else false)))
(define (variable? exp) (symbol? exp))
(define (quoted? exp)
    (tagged-list? exp 'quote))
(define (text-of-quotation exp) (cadr exp))
(define (tagged-list? exp tag)
    (if (pair? exp)
        (eq? (car exp) tag)
        false))


(define (amb? exp) (tagged-list? exp 'amb))
(define (amb-choices exp) (cdr exp))


(define (definition? exp)
    (tagged-list? exp 'define))
(define (definition-variable exp)
    (if (symbol? (cadr exp))
        (cadr exp)
        (caadr exp)))
(define (definition-value exp)
   (if (symbol? (cadr exp))
       (caddr exp)
       (make-lambda (cdadr exp)
                    (cddr exp))))


(define (lambda? exp) (tagged-list? exp 'lambda))
(define (lambda-parameters exp) (cadr exp))
(define (lambda-body exp) (cddr exp))
(define (make-lambda parameters body)
     (cons 'lambda (cons parameters body)))


(define (if? exp) (tagged-list? exp 'if))
(define (if-predicate exp) (cadr exp))
(define (if-consequent exp) (caddr exp))
(define (if-alternative exp)
    (if (not (null? (cdddr exp)))
        (cadddr exp)
        'false))
(define (make-if predicate consequent alternative)
    (list 'if predicate consequent alternative))




(define (begin? exp) (tagged-list? exp 'begin))
(define (begin-actions exp) (cdr exp))
(define (last-exp? seq) (null? (cdr seq)))
(define (first-exp seq) (car seq))
(define (rest-exps seq) (cdr seq))      
(define (sequence->exp seq)
   (cond ((null? seq) seq)
         ((last-exp? seq) (first-exp seq))
         (else (make-begin seq))))
(define (make-begin seq) (cons 'begin seq))


(define (application? exp) (pair? exp))
(define (operator exp) (car exp))
(define (operands exp) (cdr exp))
(define (no-operands? ops) (null? ops))
(define (first-operand ops) (car ops))
(define (rest-operands ops) (cdr ops))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;派生表达式
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;cond
(define (cond? exp) (tagged-list? exp 'cond))
(define (cond-clauses exp) (cdr exp))
(define (cond-else-clause? clause)
    (eq? (cond-predicate clause) 'else))
(define (cond-predicate clause) (car clause))
(define (cond-actions clause) (cdr clause))
(define (cond->if exp)
    (expand-clauses (cond-clauses exp)))
(define (expand-clauses clauses)
    (if (null? clauses)
        'false
        (let ((first (car clauses))
              (rest (cdr clauses)))
          (if (cond-else-clause? first)
              (if (null? rest)
                  (sequece->exp (cond-actions first))
                  (error "ELSE clause is'nt last -- COND->IF"
                        clauses))
              (make-if (cond-predicate first)
                       (sequence->exp (cond-actions first))
                       (expand-clauses rest))))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;let
(define (let? exp) 
  (tagged-list? exp 'let))
(define (let-body exp) 
 (cddr exp))
(define (let-pairs exp) (cadr exp))
(define (var-let-pair pair) (car pair))
(define (exp-let-pair pair) (cadr pair))
(define (get-make-var-pairs pairs)
  (if (not (null? pairs))
      (cons (var-let-pair (car pairs))
            (get-make-var-pairs (cdr pairs)))
      pairs))
(define (get-make-exp-pairs pairs)
  (if (not (null? pairs))
      (cons (exp-let-pair (car pairs))
            (get-make-exp-pairs (cdr pairs)))
      pairs))
(define (make-lambda-procedure vars body exps)
    (cons (cons 'lambda (cons vars body)) exps))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;; 求值器的数据结构
;;;;;;;;;;;;;;;;;;;;;;;;;谓词检测
(define (true? x)
   (not (eq? x false)))
(define (false? x)
   (eq? x false))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;过程的表示
(define (make-procedure parameters body env)
    (list 'procedure parameters body env))
(define (compound-procedure? p)
    (tagged-list? p 'procedure))
(define (procedure-parameters p) (cadr p))
(define (procedure-body p) (caddr p))
(define (procedure-environment p) (cadddr p))
;;;;;;;;;;;;;;;;;;;;;;;;;;;对环境的操作
(define (enclosing-environment env) (cdr env))
(define (first-frame env) (car env))
(define the-empty-environment ())


(define (make-frame variables values)
    (cons variables values))
(define (frame-variables frame) (car frame))
(define (frame-values frame) (cdr frame))
(define (add-binding-to-frame! var val frame)
    (set-car! frame (cons var (car frame)))
    (set-cdr! frame (cons val (cdr frame))))
    
(define (extend-environment vars vals base-env)
    (if (= (length vars) (length vals))
        (cons (make-frame vars vals) base-env)
        (if (< (length vars) (length vals))   
           (error "Too many arguments supplied" vars vals)
           (error "Too few arguments supplied" vars vals))))
(define (lookup-variable-value var env)
    (define (env-loop env)
       (define (scan vars vals)
          (cond ((null? vars)
                   (env-loop (enclosing-environment env)))
                ((eq? var (car vars))
                 (car vals))
                (else (scan (cdr vars) (cdr vals)))))
       (if (eq? env the-empty-environment)
           (error "Unbound variable" var)
           (let ((frame (first-frame env)))
              (scan (frame-variables frame)
                    (frame-values frame)))))
    (env-loop env))
(define (set-variable-value! var val env)
   (define (env-loop env)
       (define (scan vars vals)
          (cond ((null? vars)
                 (env-loop (enclosing-environment env)))
                ((eq? var (car vars))
                 (set-car! vals val))
                (else (scan (cdr vars) (cdr vals)))))
        (if (eq? env the-empty-environment)
            (error "Unbound variable -- SET!" var)
            (let ((frame (first-frame env)))
              (scan (frame-variables frame)
                    (frame-values frame)))))
   (env-loop env))            
(define (define-variable! var val env)
    (let ((frame (first-frame env)))
      (define (scan vars vals)
         (cond ((null? vars)
                (add-binding-to-frame! var val frame))
               ((eq? var (car vars))
                (set-car! vals val))
               (else (scan (cdr vars) (cdr vals)))))
      (scan (frame-variables frame)
            (frame-values frame))))
;;;;;;;;;;;;;;;;;;;;;;;;;;;作为程序运行这个求值器
(define primitive-procedures
    (list (list 'car car)
          (list 'cdr cdr)
          (list 'list list)
          (list 'eq? eq?)
          (list 'cons cons)
          (list 'null? null?)
          (list '+ +)
          (list '- -)
          (list '* *)
          (list '/ /)
          (list '< <)
          (list '> >)
          (list '= =)
          (list 'not not)
          (list 'abs abs)
          (list 'cadr cadr)
          (list 'caddr caddr)
          (list 'display display)
          (list 'newline newline)
          (list 'map map)))


(define (primitive-procedure-names)
   (map car 
        primitive-procedures))
(define (primitive-procedure-objects)
   (map (lambda (proc) (list 'primitive (cadr proc)))
        primitive-procedures))


(define (setup-environment)
    (let ((initial-env
            (extend-environment (primitive-procedure-names)
                                (primitive-procedure-objects)
                                the-empty-environment)))
     (define-variable! 'true true initial-env)
     (define-variable! 'false false initial-env)
     initial-env))
(define the-global-environment (setup-environment))


(define (primitive-procedure? proc)
    (tagged-list? proc 'primitive))
(define (primitive-implementation proc) (cadr proc))


(define (apply-primitive-procedure proc args)
   (apply
       (primitive-implementation proc) args))
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;驱动循环
(define input-prompt ";;; Amb-Eval input:")
(define output-prompt ";;;Amb-Eval value:")


(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
                        (lambda (val next-alternative)
                           (announce-output output-prompt)
                           (user-print val)
                           (internal-loop next-alternative))
                        (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))))
(define (prompt-for-input string)
   (newline) (newline) (display string) (newline))
(define (announce-output string)
    (newline) (display string) (newline))
(define (user-print object)
   (if (compound-procedure? object)
       (display (list 'compound-procedure
                      (procedure-parameters object)
                      (procedure-body object)))
       (display object)))              
(define the-global-environment (setup-environment))


(driver-loop)   
        
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;test 

现在开始直接分析这个求值器了,

   require和let形式是自己写的。就懒得分析了。这个求值器是在原来分析求值器的基础上修改的。   amb求值器是为了实现非确定性计算而设计的,这使得简单的描述一个问题就能得到结果成为可能。如:(在所有自然数里,找到所有的素数)这本身是问题的描述,但也可以成为解决问题的全部内容。为了实现这样的形式,(in all z*,require prime z,list z),即可找到第一个素数,但为了找到全部解,提供一个try-again使得求值器能按要求解出表达式的解(就像解方程一样,自动解方程),其他部分继承了分析求值器的功能。这些是amb求值器的设计目标。

     amb形式能有返回一个表中的任意一个值。require疑问疑问能够使amb的值为满足要求的第一个值。有了这两个形式就能实现非确定性计算(原来是约翰。麦卡锡提出的非确定性程序设计的amb思想,他还是lisp之父,可惜2011年死了。这么牛的程序员怎么就死了。不知道他老了的时候手指还好不好使。抓狂抓狂还是专心去培养后人了。去看了他的文章《A BASIS FOR A MATHEMATICAL THEORY OF COMPUTATION》........大笑惊恐结果没看完,计算理论什么的简直难爆了)看了下论文中关于ambguous Function的描述。amb并不是一个function所以把amb放进求值器里作为一种形式--------简直神逻辑。他提出用文中的理论可以实现amb形式,但没说是怎么实现。怎么看那篇文章都是在讲lisp的数学理论什么的。 而lisp的创立时间也和文章的时间差不多,约翰麦卡锡在刚创立语言之初就能预见到lisp可以实现非确定性计算吗?敲打敲打尴尬尴尬,这里虽然是scheme但也是lisp变来的。他怎么可能有这么强的先见性。大牛的思维简直吓死人大哭大哭大哭大哭大哭大哭。。。 已瞎))算了,后人实现了amb形式。从他论文那里看来我之前的分析是错误的。amb形式和require形式不是独立的。require是由amb形式所实现的(而事实上SICP上就是这么实现的。写道这里麦卡锡简直是大魔神,)既然这样我就require以amb表示。根据论文里

ult(n)=(n=0->0,T->ult(less (n)))  应该用条件语句实现(if (not p) procedure)。这种形式这里的procedure要满足能够减少amb的可能值,并能判断下一个amb的值是否满足条件,还要能提供递归下去。在sicp中提供一种成功继续与失败继续的过程。而(amb)过程会直接执行失败继续。这个失败继续是由调用(amb) 的成功继续传递过来。这个成功继续在if语句里是predicate的成功继续。(这个地方的分析,成功继续与失败继续的机制目前还是空穴来风,不知道作者怎么想的,之后再来解决,先继续下去)

而predicate包含以amb值为参数的过程基于分析求值器的ambeval会分析predicate,amb参数会最后被分析,最先被求值。这样amb能构造出失败继续,选择下一个值传给succeed继续下去闭嘴奋斗,再求一次if过程。我突然想起来还有点测试代码没去掉,到时候会有乱七八糟的东西打印出来。敲打敲打现在开始考虑前面的analyze过程,对比之前分析求值器,相同的地方就不分析了,略微的改变也不分析。为了实现前面失败继续的回溯机制。分析表达式是要注意顺序,表达式的分析执行总是由内向外的,这样在调用fail继续的时候才能回溯到之前的地方在求值一次。(要注意的是我们构造自己的失败继续的地方,只有analyze-amb ,analyze-assignment,和最初的失败继续。其他的分析只是将上层的fail简单的传递到下层成功继续里,因为其他表达式并不需要回溯。调用失败继续的有(amb),driver-loop的最初失败继续。以及(try-again)过程。回溯机制就到这里。考虑有多个amb表达式嵌套的情况下再执行后调用失败继续会发生什么-------分析amb过程,以一个succed继续和失败继续开始执行。若分析到第二个amb表达式,它接收到的fail继续是第一个amb过程自己定义的,而succeed继续与第一个相同,以此类推,知道最后一个amb表达式,其返回一不包含amb的表达式的值转给succeed,向外层执行。解决这种问题不能跟踪程序,而是只需要知道下一步该去哪。和前一步。并且知道analyse总能做到令人满意的形式。想模块化程序设计一样。但也不同。amb求值器的运行机理就到这里了。

最后还有一个之前没解决的问题,为何要使用成功继续与失败继续的求值器来实现非确定性求值?

   使用求值器的原因之前说过,amb不能实现为函数,所以在求值器里实现为一种形式;

 amb表达式会先返回第一个元素,还需提供一种方法使得,一定情况下是amb返回第二个元素,再重新执行一次。这里再重新执行一次就是回溯。为实现回溯可以把表达式的执行当作单链表一样,在当前执行的表达式里包含以后所执行的所有表达式的“指针”。另外为了在未来调用回溯实现回溯到特殊的指定位置重新执行,需要大毅力,呃不是。需要将返回点传递下去。由此得到成功继续与失败继续机制。。。。。。。。。。。到此为止了发火发火发火这个好像超级赛亚人。人。。。。。。。。。。。。。。。。。。。。。。。气死我了昨天关键时刻断网了,,,,,没保存


        
        
        
        
        
        
        
        
        
        
        
        
        
        

0 0
原创粉丝点击