Ремонт принтеров, сканнеров, факсов и остальной офисной техники


назад Оглавление вперед




[47]

((product? exp) (make-sum

(make-product (multiplier exp)

(deriv (multiplicand exp) var)) (make-product (deriv (multiplier exp) var) (multiplicand exp))))

(else

(error "неизвестный тип выражения -- DERIV" exp))))

Процедура deriv заключает в себе весь алгоритм дифференцирования. Поскольку она выражена в терминах абстрактных данных, она будет работать, как бы мы ни представили алгебраические выражения, если только у нас будут соответствующие селекторы и конструкторы. Именно этим вопросом нам и нужно теперь заняться.

Представление алгебраических выражений

Можно представить себе множество способов представления алгебраических выражений с помощью списковых структур. Например, можно использовать списки символов, которые отражали бы обычную алгебраическую нотацию, так что ax + b представлялось бы как список (a * x + b). Однако естественней всего использовать ту же скобочную префиксную запись, с помощью которой в Лиспе представляются комбинации; то есть представлять ax + b в виде (+ (* a x) b) . Тогда наше представление данных для задачи дифференцирования будет следующим:

•Переменные - это символы. Они распознаются элементарным предикатом symbol?:

(define (variable? x) (symbol? x))

•Две переменные одинаковы, если для представляющих их символов выполняется eq?:

(define (same-variable? v1 v2)

(and (variable? v1) (variable? v2) (eq? v1 v2)))

•Суммы и произведения конструируются как списки: (define (make-sum a1 a2) (list + a1 a2)) (define (make-product m1 m2) (list * m1 m2))

•Сумма - это список, первый элемент которого символ +:

(define (sum? x)

(and (pair? x) (eq? (car x) +)))

•Первое слагаемое - это второй элемент списка, представляющего сумму: (define (addend s) (cadr s))

• Второе слагаемое - это третий элемент списка, представляющего сумму:


(define (augend s) (caddr s))

•Произведение - это список, первый элемент которого символ *:

(define (product? x)

(and (pair? x) (eq? (car x) *)))

•Первый множитель - это второй элемент списка, представляющего произведение:

(define (multiplier p) (cadr p))

•Второй множитель - это третий элемент списка, представляющего произведение:

(define (multiplicand p) (caddr p))

Таким образом, нам осталось только соединить это представление с алгоритмом, заключенным в процедуре deriv, и мы получаем работающую программу символьного дифференцирования. Посмотрим на некоторые примеры ее поведения:

(deriv (+ x 3) x) (+ 1 0)

(deriv (* x y) x) (+ (* x 0) (* 1 y))

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

(+ (* (* x y) (+ 1 0)) (* (+ (* x 0) (* 1 y)) (+ x 3)))

Ответы, которые выдает программа, правильны; однако их нужно упрощать. Верно, что

d(xy) п , ,

-:- = X 0 + 1 • у

dx

но нам хотелось бы, чтобы программа знала, что x • 0 = 0, 1 • y = y, а 0 + y = y. Ответом на второй пример должно быть просто у. Как видно из третьего примера, при усложнении выражений упрощение превращается в серьезную проблему.

Наши теперешние затруднения очень похожи на те, с которыми мы столкнулись при реализации рациональных чисел: мы не привели ответы к простейшей форме. Чтобы произвести приведение рациональных чисел, нам потребовалось изменить только конструкторы и селекторы в нашей реализации. Здесь мы можем применить подобную же стратегию. Процедуру deriv мы не будем изменять вовсе. Вместо этого мы изменим make-sum так, что если оба слагаемых являются числами, она их сложит и вернет их сумму. Кроме того, если одно из слагаемых равно 0, то make-sum вернет другое.


(define (make-sum al a2) (cond ((=number? al 0) a2) ((=number? a2 0) al)

((and (number? al) (number? a2)) (+ al a2)) (else (list + al a2))))

Здесь используется процедура =number?, которая проверяет, не равно ли выражение определенному числу:

(define (=number? exp num)

(and (number? exp) (= exp num)))

Подобным же образом мы изменим и make-product, так. чтобы встроить в него правила, что нечто, умноженное на 0, есть 0, а умноженное на 1 равно самому себе:

(define (make-product ml m2)

(cond ((or (=number? ml 0) (=number? m2 0)) 0) ((=number? ml l) m2) ((=number? m2 l) ml)

((and (number? ml) (number? m2)) (* ml m2)) (else (list * ml m2))))

Вот как эта версия работает на наших трех примерах:

(deriv (+ x 3) x) 1

(deriv (* x y) x)

y

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

Хотя это заметное улучшение, третий пример показывает, что нужно многое еще сделать, прежде чем мы получим программу, приводящую выражения к форме, которую мы согласимся считать «простейшей». Задача алгебраического упрощения сложна, среди прочего, еще и потому, что форма, которая является простейшей для одних целей, может таковой не являться для других.

Упражнение 2.56.

Покажите, как расширить простейшую программу дифференцирования так, чтобы она воспринимала больше разных типов выражений. Например, реализуйте правило взятия производной

d(un) nun-i,du-, dxdx;

добавив еще одну проверку к программе deriv и определив соответствующие процедуры exponentiation?, base, exponent и make-exponentiation (обозначать возведение в степень можно символом **). Встройте правила, что любое выражение, возведенное в степень 0, дает 1, а возведенное в степень 1 равно самому себе.

Упражнение 2.57.

Расширьте программу дифференцирования так, чтобы она работала с суммами и произведениями любого (больше двух) количества термов. Тогда последний из приведенных выше примеров мог бы быть записан как



[стр.Начало] [стр.1] [стр.2] [стр.3] [стр.4] [стр.5] [стр.6] [стр.7] [стр.8] [стр.9] [стр.10] [стр.11] [стр.12] [стр.13] [стр.14] [стр.15] [стр.16] [стр.17] [стр.18] [стр.19] [стр.20] [стр.21] [стр.22] [стр.23] [стр.24] [стр.25] [стр.26] [стр.27] [стр.28] [стр.29] [стр.30] [стр.31] [стр.32] [стр.33] [стр.34] [стр.35] [стр.36] [стр.37] [стр.38] [стр.39] [стр.40] [стр.41] [стр.42] [стр.43] [стр.44] [стр.45] [стр.46] [стр.47] [стр.48] [стр.49] [стр.50] [стр.51] [стр.52] [стр.53] [стр.54] [стр.55] [стр.56] [стр.57] [стр.58] [стр.59] [стр.60] [стр.61] [стр.62] [стр.63] [стр.64] [стр.65] [стр.66] [стр.67] [стр.68] [стр.69] [стр.70] [стр.71] [стр.72] [стр.73] [стр.74] [стр.75] [стр.76] [стр.77] [стр.78] [стр.79] [стр.80] [стр.81] [стр.82] [стр.83] [стр.84] [стр.85] [стр.86] [стр.87] [стр.88] [стр.89] [стр.90] [стр.91] [стр.92] [стр.93] [стр.94] [стр.95] [стр.96] [стр.97] [стр.98] [стр.99] [стр.100] [стр.101] [стр.102] [стр.103] [стр.104] [стр.105] [стр.106] [стр.107] [стр.108] [стр.109] [стр.110] [стр.111] [стр.112] [стр.113] [стр.114] [стр.115] [стр.116] [стр.117] [стр.118] [стр.119] [стр.120] [стр.121] [стр.122] [стр.123] [стр.124] [стр.125] [стр.126] [стр.127] [стр.128] [стр.129] [стр.130] [стр.131] [стр.132] [стр.133] [стр.134] [стр.135] [стр.136] [стр.137] [стр.138] [стр.139] [стр.140] [стр.141] [стр.142] [стр.143] [стр.144] [стр.145] [стр.146] [стр.147] [стр.148] [стр.149] [стр.150] [стр.151] [стр.152] [стр.153] [стр.154] [стр.155] [стр.156] [стр.157] [стр.158] [стр.159] [стр.160] [стр.161] [стр.162] [стр.163] [стр.164] [стр.165] [стр.166] [стр.167] [стр.168] [стр.169] [стр.170] [стр.171] [стр.172] [стр.173] [стр.174] [стр.175] [стр.176] [стр.177] [стр.178] [стр.179] [стр.180] [стр.181] [стр.182] [стр.183] [стр.184] [стр.185] [стр.186] [стр.187] [стр.188] [стр.189] [стр.190] [стр.191] [стр.192] [стр.193] [стр.194] [стр.195] [стр.196]