首页 > 其他分享 >sicp每日一题[2.73]

sicp每日一题[2.73]

时间:2024-11-09 22:20:46浏览次数:1  
标签:make deriv 2.73 number sicp exp var 每日 define

最近状态不太好,再加上2.73前面的内容有点多,学的有点吃力,所以昨天就没做。。

Exercise 2.73

Section 2.3.2 described a program that performs symbolic differentiation:

(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp)
         (if (same-variable? exp var) 1 0))
        ((sum? exp)
         (make-sum (deriv (addend exp) var)
                   (deriv (augend exp) var)))
        ((product? exp)
         (make-sum (make-product
                    (multiplier exp)
                    (deriv (multiplicand exp) var))
                   (make-product
                    (deriv (multiplier exp) var)
                    (multiplicand exp))))
        ⟨more rules can be added here⟩
        (else (error "unknown expression type: DERIV" exp))))

We can regard this program as performing a dispatch on the type of the expression to be differentiated. In this situation the “type tag” of the datum is the algebraic operator symbol (such as +) and the operation being performed is deriv. We can transform this program into data-directed style by rewriting the basic derivative procedure as

(define (deriv exp var)
  (cond ((number? exp) 0)
        ((variable? exp) (if (same-variable? exp var) 1 0))
        (else ((get 'deriv (operator exp))
               (operands exp) var))))

(define (operator exp) (car exp))
(define (operands exp) (cdr exp))

a. Explain what was done above. Why can’t we assimilate the predicates number? and variable? into the data-directed dispatch?
b. Write the procedures for derivatives of sums and products, and the auxiliary code required to install them in the table used by the program above.
c. Choose any additional differentiation rule that you like, such as the one for exponents (Exercise 2.56), and install it in this data-directed system.
d. In this simple algebraic manipulator the type of an expression is the algebraic operator that binds it together. Suppose, however, we indexed the procedures in the opposite way, so that the dispatch line in deriv looked like

((get (operator exp) 'deriv) (operands exp) var)

What corresponding changes to the derivative system are required?


首先做这道题之前要先把 put 和 get 函数给加进来

(define *operation-table* (make-hash))

(define (put op-type op-name procedure)
  (hash-set! *operation-table* (list op-type op-name) procedure))

(define (get op-type op-name)
  (hash-ref *operation-table* (list op-type op-name) #f))

a. 上面的程序就是从 data-directed dispatch 表里取出一个操作为 deriv,类型为 (operator exp) 的过程,并把表达式和变量传给这个提取出的过程。不把 number? 和 variable? 放到 data-directed dispatch 表的原因是因为它们两个只需要一个参数,而这个程序会给取出的过程2个参数。我看到别人的答案基本都是说这两个过程没有标签,而且不需要加标签,所以不能放入 data-directed dispatch 表,但是题目问的是 why can't,它们的解释不是 can't 而是 needn't,不知道我的理解对不对。
b&c. 这两问情况一样,难度也不大,参考 2.56 的练习,只需要修改一下取操作数的逻辑就可以了,因为 “+, *, **” 本身已经作为区分采用哪个过程的符号,所以取操作数不是从第二个取,而是第一个,其他地方就照搬过来就可以了。

(define (install-deriv-package)
  ;; internal procedures
  ;; sum
  (define (make-sum a1 a2)
    (cond ((=number? a1 0) a2)
          ((=number? a2 0) a1)
          ((and (number? a1) (number? a2)) (+ a1 a2))
          (else (list '+ a1 a2))))

  (define (sum? x) (and (pair? x) (eq? (car x) '+)))

  (define (addend s) (car s))

  (define (augend s) (cadr s))

  (define (sum-deriv expr var) 
    (make-sum (deriv (addend expr) var) 
              (deriv (augend expr) var))) 

  ;; product
  (define (make-product m1 m2)
    (cond ((or (=number? m1 0) (=number? m2 0)) 0)
          ((=number? m1 1) m2)
          ((=number? m2 1) m1)
          ((and (number? m1) (number? m2)) (* m1 m2))
          (else (list '* m1 m2))))

  (define (product? x) (and (pair? x) (eq? (car x) '*)))

  (define (multiplier p) (car p))

  (define (multiplicand p) (cadr p))

  (define (product-deriv expr var) 
    (make-sum (make-product (deriv (multiplier expr) var) 
                            (multiplicand expr))
              (make-product (multiplier expr)
                            (deriv (multiplicand expr) var))))

  ;; exponentiate
  (define (make-exponentiation base exponent)
    (cond ((=number? base 0) 0)
          ((=number? base 1) 1)
          ((and (number? base) (=number? exponent 0)) 1)
          ((and (number? base) (=number? exponent 1)) base)
          ((and (number? base) (number? exponent)) (* base (make-exponentiation base (- exponent 1))))
          (else (list '** base exponent))))

  (define (base e) (car e))

  (define (exponent e) (cadr e))

  (define (exponentation-deriv expr var) 
    (make-product (exponent expr) 
                  (make-product  
                   (make-exponentiation (base expr) 
                                        (make-sum (exponent expr) -1)) 
                   (deriv (base expr) var))))
               
  ;; interface to the rest of the system
  (put 'deriv '+ sum-deriv)
  (put 'deriv '* product-deriv)
  (put 'deriv '** exponentation-deriv)
  'done)


(install-deriv-package)


(deriv '(+ x x x) 'x) 
(deriv '(* x x x) 'x) 
(deriv '(+ x (* x  (+ x (+ y 2)))) 'x) 
(deriv '(+ x (* 3 (+ x (+ y 2)))) 'x)
(deriv '(** x 3) 'x) 

; 结果如下
'done
2
'(+ x x)
'(+ 1 (+ (+ x (+ y 2)) x))
4
'(* 3 (** x 2))

d. 这样的话,只要在使用 put 函数的时候也先传类型,再传操作就可以了。

标签:make,deriv,2.73,number,sicp,exp,var,每日,define
From: https://www.cnblogs.com/think2times/p/18537391

相关文章

  • 每日OJ题_牛客_BC157素数回文_数学_C++_Java
    目录牛客_BC157素数回文_数学题目解析C++代码Java代码牛客_BC157素数回文_数学素数回文_牛客题霸_牛客网描述:现在给出一个素数,这个素数满足两点:1、  只由1-9组成,并且每个数只出现一次,如13,23,1289。2、  位数从高到低为递减或递增,如2459,87631。请你判断一下,这......
  • GitHub每日最火火火项目(11.7)
    项目名称:DataExpert-io/data-engineer-handbook项目介绍:“DataExpert-io/data-engineer-handbook”是一个非常有价值的资源库。这个项目收集了与数据工程相关的各种学习链接,涵盖了数据工程领域的方方面面。对于想要深入了解数据工程的人来说,它就像是一个知识宝库。无论是......
  • Leetcode 每日一题 135.分发糖果
    问题描述给定一个整数数组ratings,表示一排孩子的评分。我们需要按照以下规则给孩子们分发糖果:每个孩子至少得到1个糖果。相邻两个孩子中,评分更高的孩子会得到更多的糖果。我们的目标是计算出按照这些规则分发糖果所需的最少糖果数。输入输出格式输入:一个整数数组 rating......
  • 高级java每日一道面试题-2024年10月29日-JVM篇-简述分代垃圾回收器是怎么工作的?
    如果有遗漏,评论区告诉我进行补充面试官:简述分代垃圾回收器是怎么工作的?我回答:在Java高级面试中,分代垃圾回收器的工作原理是一个重要的考点。下面将详细解释分代垃圾回收器是如何工作的:分代垃圾回收器的基本概念分代垃圾回收器是一种基于对象生命周期的垃圾回收方......
  • 高级java每日一道面试题-2024年10月28日-RabbitMQ篇-RabbitMQ的使用场景有哪些?
    如果有遗漏,评论区告诉我进行补充面试官:RabbitMQ的使用场景有哪些?我回答:RabbitMQ是一个开源的消息代理和队列服务器,它遵循高级消息队列协议(AMQP)。RabbitMQ的核心作用是作为应用程序之间的中介,实现异步消息传递。它可以帮助解耦系统组件、提供消息的持久化、支持消息......
  • sicp每日一题[2.72]
    Exercise2.72ConsidertheencodingprocedurethatyoudesignedinExercise2.68.Whatistheorderofgrowthinthenumberofstepsneededtoencodeasymbol?Besuretoincludethenumberofstepsneededtosearchthesymbollistateachnodeencounter......
  • 算法每日双题精讲——双指针(移动零,复写零)
    ......
  • 使用 vscode 简单配置 ESP32 连接 Wi-Fi 每日定时发送 HTTP 和 HTTPS 请求
    最新博客文章链接文字更新时间:2024/11/07由于学校校园网,如果长时间不重新登陆的话,网速会下降,所以想弄个能定时发送HTTP请求的东西。由于不想给路由器刷系统,也麻烦。就开始考虑使用局域网内的服务器,不过由于服务器没有Wi-Fi模块,也不想搞USB无线wifi网卡,就想着干脆用单......
  • sicp每日一题[2.71]
    Exercise2.71SupposewehaveaHuffmantreeforanalphabetofnsymbols,andthattherelativefrequenciesofthesymbolsare1,2,4,...,2n1.Sketchthetreeforn=5;forn=10.Insuchatree(forgeneraln)howmanybitsarerequiredtoencode......
  • 20241107,LeetCode 每日一题,使用 Go 计算两数相加
    思路模拟加法:链表存储的是逆序数位,因此从头节点开始,逐位相加可以模拟正常的加法。每两个节点的值相加,并记录进位。逐节点相加:创建一个新的链表,用于存储结果,每次将两个链表对应节点的值加上进位值,结果存储到新链表的节点中。计算过程中,将(l1.Val+l2.Val+carry)相加的......