约束的传播

;连接器的表示
;user不需要也不能添加进constraints表里面,并且只有实现connect过的constraint才能进行set-value!
(define (make-connector)
  (let ((value false) (informant false) (constraints '()))
    (define (set-my-value! new-value setter)
      (cond ((not (has-value? me)) (set! value new-value) (set! informant setter) (foreach-except setter inform-about-value constraints))
            ((not (= value new-value)) (error "set-value!: contradiction" (list value new-value)))))
    (define (forget-my-value! retractor)
      (cond ((eq? informant retractor) (set! informant false) (foreach-except retractor inform-about-no-value constraints))
            (else 'ignored)))
    (define (connect new-constraint)
      (if (not (memq? new-constraint constraints))
          (set! constraints (cons new-constraint constraints)))
      (if (has-value? me)
          (inform-about-value new-constraint))
      'done)
    (define (me request)
      (cond ((eq? request 'has-value?) (if informant true false))
            ((eq? request 'get-value) value)
            ((eq? request 'set-value!) set-my-value!)
            ((eq? request 'forget-value!) forget-my-value!)
            ((eq? request 'connect) connect)
            (else (error "make-connector: wrong request" request))))
    me))
(define (has-value? connector)
  (connector 'has-value?))
(define (get-value connector)
  (connector 'get-value))
(define (set-value! connector new-value informant)
  ((connector 'set-value!) new-value informant))
(define (forget-value! connector retractor)
  ((connector 'forget-value!) retractor))
(define (connect connector new-constraint)
  ((connector 'connect) new-constraint))
(define (foreach-except exception proc list)
  (cond ((null? list) 'done)
        ((eq? exception (car list))
         (foreach-except exception proc (cdr list)))
        (else (proc (car list))
              (foreach-except exception proc (cdr list)))))
(define (memq? item list)
  (cond ((null? list) false)
        ((eq? item (car list)) true)
        (else (memq? item (cdr list)))))
;约束系统的实现
(define (adder a1 a2 sum)
  (define (process-new-value)
    (cond ((and (has-value? a1) (has-value? a2))
           (set-value! sum (+ (get-value a1) (get-value a2)) me))
          ((and (has-value? a1) (has-value? sum))
           (set-value! a2 (- (get-value sum) (get-value a1)) me))
          ((and (has-value? a2) (has-value? sum))
           (set-value! a1 (- (get-value sum) (get-value a2)) me))))
  (define (process-forget-value)
    (forget-value! a1 me)
    (forget-value! a2 me)
    (forget-value! sum me)
    (process-new-value))
  (define (me request)
    (cond ((eq? request 'I-have-a-value) (process-new-value))
          ((eq? request 'I-have-no-value) (process-forget-value))
          (else (error "adder: wrong operation type--" request))))
  (connect a1 me)
  (connect a2 me)
  (connect sum me)
  me)
(define (multiplier a1 a2 product)
  (define (process-new-value)
    (cond ((or (and (has-value? a1) (= (get-value a1) 0)) (and (has-value? a2) (= (get-value a2) 0)))
           (set-value! product 0 me))
          ((and (has-value? a1) (has-value? a2))
              (set-value! product (* (get-value a1) (get-value a2)) me))
          ((and (has-value? a1) (has-value? product))
           (set-value! a2 (/ (get-value product) (get-value a1)) me))
          ((and (has-value? a2) (has-value? product))
           (set-value! a1 (/ (get-value product) (get-value a2)) me))))
  (define (process-forget-value)
    (forget-value! a1 me)
    (forget-value! a2 me)
    (forget-value! product me)
    (process-new-value))
  (define (me request)
    (cond ((eq? request 'I-have-a-value) (process-new-value))
          ((eq? request 'I-have-no-value) (process-forget-value))
          (else
           (error "multiplier: wrong operation type--" request))))
  (connect a1 me)
  (connect a2 me)
  (connect product me)
  me)
(define (constant num connector)
  (define (me request)
    (error "constant: wrong-operation-type--" request))
  (connect connector me)
  (set-value! connector num me)
  me)
(define (probe name connector)
  (define (me request)
    (cond ((eq? request 'I-have-a-value)
           (newline)
           (display "probe: ")
           (display name)
           (display " = ")
           (display (get-value connector)))
          ((eq? request 'I-have-no-value)
           (newline)
           (display "probe: ")
           (display name)
           (display " = ")
           (display "?"))
          (else
           (error "probe: wrong operation type--" request))))
  (connect connector me)
  me)
(define (inform-about-value constraint)
  (constraint 'I-have-a-value))
(define (inform-about-no-value constraint)
  (constraint 'I-have-no-value))
;约束系统的使用
(define (celsius-fahrenheit-converter c f)
  (let ((w (make-connector))
        (u (make-connector))
        (v (make-connector))
        (x (make-connector))
        (y (make-connector)))
    (multiplier c w u)
    (multiplier v x u)
    (adder v y f)
    (constant 9 w)
    (constant 5 x)
    (constant 32 y)
    'ok))
(define c (make-connector))
(define f (make-connector))
(celsius-fahrenheit-converter c f)
(probe "Celsius temp" c)
(probe "Fahrenheit temp" f)
(set-value! c 25 'user)
(set-value! f 212 'user)
(forget-value! c 'user)
(set-value! f 212 'user)
;3.33
(define (averager a b c)
  (let ((d (make-connector))
        (e (make-connector)))
    (adder a b d)
    (multiplier c e d)
    (constant 2 e)))
(define a (make-connector))
(define b (make-connector))
(define c (make-connector))
(probe 'a a)
(probe 'b b)
(probe 'c c)
(averager a b c)
(set-value! a 2 'user)
(set-value! b 4 'user)
(forget-value! a 'user)
(set-value! c 10 'user)
;3.34
(define (cv num)
  (let ((a (make-connector)))
    (constant num a)
    a))
(define (c+ a1 a2)
  (let ((sum (make-connector)))
    (adder a1 a2 sum)
    sum))
(define (c* m1 m2)
  (let ((product (make-connector)))
    (multiplier m1 m2 product)
    product))
(define (c- a b)
  (let ((c (make-connector)))
    (adder c b a)
    c))
(define (c/ a b)
  (let ((c (make-connector)))
    (multiplier c b a)
    c))
(define (celsius-fahrenheit-converter-2 c)
  (c+ (cv 32) (c* c (c/ (cv 9) (cv 5)))))
(define c (make-connector))
(probe 'c c)
(define f (celsius-fahrenheit-converter-2 c))
(probe 'f f)
(set-value! c 25 'user)
(forget-value! c 'user)
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值