Building a system for symbolic differentiation

Similar documents
Building a system for symbolic differentiation

Using Symbols in Expressions (1) evaluate sub-expressions... Number. ( ) machine code to add

An Explicit-Continuation Metacircular Evaluator

A Brief Introduction to Scheme (II)

6.001: Structure and Interpretation of Computer Programs

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

6.184 Lecture 4. Interpretation. Tweaked by Ben Vandiver Compiled by Mike Phillips Original material by Eric Grimson

Why do we need an interpreter? SICP Interpretation part 1. Role of each part of the interpreter. 1. Arithmetic calculator.

Functional Programming. Pure Functional Programming

Computer Science 21b (Spring Term, 2015) Structure and Interpretation of Computer Programs. Lexical addressing

Fall Semester, The Metacircular Evaluator. Today we shift perspective from that of a user of computer langugaes to that of a designer of

6.945 Adventures in Advanced Symbolic Programming

regsim.scm ~/umb/cs450/ch5.base/ 1 11/11/13

6.037 Lecture 4. Interpretation. What is an interpreter? Why do we need an interpreter? Stages of an interpreter. Role of each part of the interpreter

CS61A Midterm 2 Review (v1.1)

6.001 Notes: Section 8.1

Documentation for LISP in BASIC

Project 2: Scheme Interpreter

Deferred operations. Continuations Structure and Interpretation of Computer Programs. Tail recursion in action.

Discussion 12 The MCE (solutions)

CS 314 Principles of Programming Languages. Lecture 16

CS 314 Principles of Programming Languages

CSc 520 Principles of Programming Languages

Summer 2017 Discussion 10: July 25, Introduction. 2 Primitives and Define

User-defined Functions. Conditional Expressions in Scheme

Syntactic Sugar: Using the Metacircular Evaluator to Implement the Language You Want

Announcements. The current topic: Scheme. Review: BST functions. Review: Representing trees in Scheme. Reminder: Lab 2 is due on Monday at 10:30 am.

Streams, Delayed Evaluation and a Normal Order Interpreter. CS 550 Programming Languages Jeremy Johnson

Fall 2018 Discussion 8: October 24, 2018 Solutions. 1 Introduction. 2 Primitives

Simplifying Logical Formulas

SCHEME 10 COMPUTER SCIENCE 61A. July 26, Warm Up: Conditional Expressions. 1. What does Scheme print? scm> (if (or #t (/ 1 0)) 1 (/ 1 0))

Modern Programming Languages. Lecture LISP Programming Language An Introduction

;; definition of function, fun, that adds 7 to the input (define fun (lambda (x) (+ x 7)))

Introduction to Scheme

An introduction to Scheme

CS 61A, Fall, 2002, Midterm #2, L. Rowe. 1. (10 points, 1 point each part) Consider the following five box-and-arrow diagrams.

Normal Order (Lazy) Evaluation SICP. Applicative Order vs. Normal (Lazy) Order. Applicative vs. Normal? How can we implement lazy evaluation?

Interpreters and Tail Calls Fall 2017 Discussion 8: November 1, 2017 Solutions. 1 Calculator. calc> (+ 2 2) 4

Below are example solutions for each of the questions. These are not the only possible answers, but they are the most common ones.

6.001, Spring Semester, 1998, Final Exam Solutions Your Name: 2 Part c: The procedure eval-until: (define (eval-until exp env) (let ((return (eval-seq

CSE 341 Lecture 16. More Scheme: lists; helpers; let/let*; higher-order functions; lambdas

Procedural abstraction SICP Data abstractions. The universe of procedures forsqrt. Procedural abstraction example: sqrt

CS450 - Structure of Higher Level Languages

SCHEME 7. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. October 29, 2015

6.001 Notes: Section 15.1

Functional Programming. Pure Functional Languages

Scheme. Functional Programming. Lambda Calculus. CSC 4101: Programming Languages 1. Textbook, Sections , 13.7

Building up a language SICP Variations on a Scheme. Meval. The Core Evaluator. Eval. Apply. 2. syntax procedures. 1.

Scheme Quick Reference

Lecture Notes on Lisp A Brief Introduction

CS 61A Interpreters, Tail Calls, Macros, Streams, Iterators. Spring 2019 Guerrilla Section 5: April 20, Interpreters.

From Syntactic Sugar to the Syntactic Meth Lab:

CS 314 Principles of Programming Languages

FUNKCIONÁLNÍ A LOGICKÉ PROGRAMOVÁNÍ 3. LISP: ZÁKLADNÍ FUNKCE, POUŽÍVÁNÍ REKURZE,

;;; Determines if e is a primitive by looking it up in the primitive environment. ;;; Define indentation and output routines for the output for

Lisp Basic Example Test Questions

Scheme Quick Reference

University of Massachusetts Lowell

4.2 Variations on a Scheme -- Lazy Evaluation

6.034 Artificial Intelligence February 9, 2007 Recitation # 1. (b) Draw the tree structure corresponding to the following list.

CS 275 Name Final Exam Solutions December 16, 2016

Fall 2017 Discussion 7: October 25, 2017 Solutions. 1 Introduction. 2 Primitives

Functional Programming. Pure Functional Languages

CS61A Summer 2010 George Wang, Jonathan Kotker, Seshadri Mahalingam, Eric Tzeng, Steven Tang

C311 Lab #3 Representation Independence: Representation Independent Interpreters

Type Inference and Type Habitation (5/10/2004)

CSc 520. Principles of Programming Languages 7: Scheme List Processing

15 Unification and Embedded Languages in Lisp

Functional Programming - 2. Higher Order Functions

cs61amt2_4 CS 61A Midterm #2 ver March 2, 1998 Exam version: A Your name login: cs61a- Discussion section number TA's name

SCHEME 8. 1 Introduction. 2 Primitives COMPUTER SCIENCE 61A. March 23, 2017

Lecture #24: Programming Languages and Programs

LECTURE 16. Functional Programming

CSc 520 Principles of Programming Languages. Examining Lists. Constructing Lists... 7: Scheme List Processing


ALISP interpreter in Awk

Sample Final Exam Questions

Lexical vs. Dynamic Scope

A Small Interpreted Language

(scheme-1) has lambda but NOT define

Imperative, OO and Functional Languages A C program is

Typed Scheme: Scheme with Static Types

Project 5 - The Meta-Circular Evaluator

Spring 2018 Discussion 7: March 21, Introduction. 2 Primitives

6.001 Notes: Section 6.1

COP4020 Programming Languages. Functional Programming Prof. Robert van Engelen

Lecture 09: Data Abstraction ++ Parsing is the process of translating a sequence of characters (a string) into an abstract syntax tree.

Programming Languages

COP4020 Programming Assignment 1 - Spring 2011

CS 61A Midterm #2 ver March 2, 1998 Exam version: A. Your name. login: cs61a- Discussion section number. TA's name

FUNKCIONÁLNÍ A LOGICKÉ PROGRAMOVÁNÍ 2. ÚVOD DO LISPU: ATOMY, SEZNAMY, FUNKCE,

MORE SCHEME. 1 What Would Scheme Print? COMPUTER SCIENCE MENTORS 61A. October 30 to November 3, Solution: Solutions begin on the following page.

SCHEME AND CALCULATOR 5b

PROFESSOR: Well, yesterday we learned a bit about symbolic manipulation, and we wrote a rather stylized

Principles of Programming Languages 2017W, Functional Programming

Proving Properties of Recursive Functions and Data Structures. CS 270 Math Foundations of CS Jeremy Johnson

Lists in Lisp and Scheme

Administrivia. Simple data types

YOUR NAME PLEASE: *** SOLUTIONS ***

Notes on Higher Order Programming in Scheme. by Alexander Stepanov

Transcription:

Computer Science 21b Structure and Interpretation of Computer Programs Building a system for symbolic differentiation Selectors, constructors and predicates: (constant? e) Is e a constant? (variable? e) Is e a variable? (same-variable? v 1 v 2 ) Are v 1 and v 2 the same variable? (sum? e) Is e a sum? (product? e) Is e a product? (addend e) Addend of the sum e. (augend e) Augend of the sum e. (multiplier e) Multiplier of the product e. (multiplicand e) Multiplicand of the product e. (make-constant c) Construct the constant c. (make-sum a 1 a 2 ) Construct the sum of a 1 and a 2. (make-product m 1 m 2 ) Construct product of m 1 and m 2. Differentiation procedure: (define (deriv exp var) (cond ((constant? exp) (make-constant 0)) ((variable? exp) (if (same-variable? exp var) (make-constant 1) (make-constant 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)))))) d Recall x = 1, d y = 0, d (U + V ) = d U + d V, d (UV ) = U d V + V d U, and even dx dx dx dx dx dx dx dx d hi dx ho = ho d d hi hi dx hoho dx ho. 1

Simple representations: (define (constant? x) (number? x)) (define (variable? x) (symbol? x)) (define (same-variable? v1 v2) (and (variable? v1) (variable? v2) (eq? v1 v2))) (define (make-constant x) x) (define (make-sum a1 a2) (list + a1 a2)) (define (make-product m1 m2) (list * m1 m2)) (define (sum? x) (if (not (atom? x)) (eq? (car x) +) nil)) (define (addend s) (cadr s)) (define (augend s) (caddr s)) (define (product? x) (if (not (atom? x)) (eq? (car x) *) nil)) (define (multiplier p) (cadr p)) (define (multiplicand p) (caddr p)) Simplification: (define (make-sum a1 a2) (cond ((and (number? a1) (number? a2)) (+ a1 a2)) ((number? a1) (if (= a1 0) a2 (list + a1 a2))) ((number? a2) (if (= a2 0) a1 (list + a1 a2))) (else (list + a1 a2)))) (define (make-product m1 m2) (cond ((and (number? m1) (number? m2)) (* m1 m2)) ((number? m1) (cond ((= m1 0) (make-constant 0)) ((= m1 1) m2) (else (list * m1 m2)))) ((number? m2) (cond ((= m2 0) (make-constant 0)) ((= m2 1) m1) (else (list * m1 m2)))) (else (list * m1 m2)))) Extensions to the system 2

Expanding to handle arbitrary numbers of arguments: (define (augend s) (if (null? (cdddr s)) (caddr s) (append (+) (cddr s)))) (define (multiplicand p) (if (null? (cdddr p)) (caddr p) (append (*) (cddr p)))) Expanding to handle exponentiation: To the deriv procedure, add the following clause, and the subsequent procedures: ((exponential? exp) (make-product (make-product (exponent exp) (make-exponential (base exp) (- (exponent exp) 1))) (deriv (base exp) var))) (define (exponential? exp) (if (not (atom? exp)) (eq? (car exp) **))) (define (base exp) (cadr exp)) (define (exponent exp) (caddr exp)) (define (make-exponential b e) (cond ((= e 0) (make-constant 1)) ((= e 1) b) (else (list ** b e)))) Pattern Matching and Simplification The code on the following pages summarizes the pattern matcher that we will build in this lecture. The basic idea behind this simplification system is to build a set of rules, consisting of a pattern and an evaluation skeleton. Given an expression, we try to match the pattern to the expression, keeping track of the assignment of pattern variables to segments of the expression in a dictionary. If we can perform such a pattern match, then we use the skeleton part of the rule to indicate the procedures that should be evaluated to perform the simplification. 3

An example of the sort of rules we will wish to specify is the following set for algebraic simplification. (define algebra-rules ( ( ((? op) (?c e1) (?c e2)) (: (op e1 e2)) ) ( ((? op) (? e1) (?c e2)) ((: op) (: e2) (: e1)) ) ( (+ 0 (? e)) (: e) ) ( (* 1 (? e)) (: e) ) ( (* 0 (? e)) 0 ) ( (* (?c e1) (* (?c e2) (? e3))) (* (: (* e1 e2)) (: e3)) ) ( (* (? e1) (* (?c e2) (? e3))) (* (: e2) (* (: e1) (: e3))) ) ( (* (* (? e1) (? e2)) (? e3)) (* (: e1) (* (: e2) (: e3))) ) ( (+ (?c e1) (+ (?c e2) (? e3))) (+ (: (+ e1 e2)) (: e3)) ) ( (+ (? e1) (+ (?c e2) (? e3))) (+ (: e2) (+ (: e1) (: e3))) ) ( (+ (+ (? e1) (? e2)) (? e3)) (+ (: e1) (+ (: e2) (: e3))) ) ( (+ (* (?c c) (? a)) (* (?c d) (? a))) (* (: (+ c d)) (: a)) ) ( (* (? c) (+ (? d) (? e))) (+ (* (: c) (: d)) (* (: c) (: e))) ) )) A simple matcher is given below, built on the appropriate data abstractions. This will be used to match the left side of rules against data expressions. (define (match pattern expression dictionary) (cond ((eq? dictionary failed) failed) ((atom? pattern) (if (atom? expression) (if (eq? pattern expression) dictionary failed) failed)) ((arbitrary-constant? pattern) (if (constant? expression) (extend-dictionary pattern expression dictionary) failed)) ((arbitrary-variable? pattern) (if (variable? expression) (extend-dictionary pattern expression dictionary) failed)) ((arbitrary-expression? pattern) (extend-dictionary pattern expression dictionary)) ((atom? expression) failed) (else (match (cdr pattern) (cdr expression) (match (car pattern) (car expression) dictionary))))) 4

Once we have a consistent match, we instantiate the skeleton part of the rule, evaluating when appropriate. (define (instantiate skeleton dictionary) (cond ((atom? skeleton) skeleton) ((skeleton-evaluation? skeleton) (evaluate (evaluation-expression skeleton) dictionary)) (else (cons (instantiate (car skeleton) dictionary) (instantiate (cdr skeleton) dictionary))))) The control of the rule base matcher consists of a series of tightly interwoven recursive loops. The basic idea is that given an expression, we apply the simplification rules in order until we either succeed or run out of rules. Moreover, if the expression to be simplified is compound, this control pattern is applied first to the elementary components of the expression, and then to the resulting simplified whole expression. The procedure simplifier on the next page returns a procedure, based on a set of rules, that can be applied to any expression. (define (simplifier the-rules) (define (simplify-exp exp) (try-rules (if (compound? exp) (simplify-parts exp) exp))) (define (simplify-parts exp) (if (null? exp) () (cons (simplify-exp (car exp)) (simplify-parts (cdr exp))))) (define (try-rules exp) (define (scan rules) (if (null? rules) exp (let ((dictionary (match (pattern (car rules)) exp (make-empty-dictionary)))) (if (eq? dictionary failed) (scan (cdr rules)) (simplify-exp (instantiate (skeleton (car rules)) dictionary)))))) (scan the-rules)) simplify-exp) 5

Having built our simplification system, we now must build the data abstractions on which it rests. The dictionary is represented as a list of pairs, each pair consisting of the variable name and its associated value from the expression. Note that assq is a primitive Scheme procedure which has the behaviour of scanning a list of pairs, testing a key against the first element of each pair. If it finds a pair whose first element is equal to the key, then that pair is returned. (define (make-empty-dictionary) ()) (define (extend-dictionary pat dat dictionary) (let ((vname (variable-name pat))) (let ((v (assq vname dictionary))) (cond ((null? v) (cons (list vname dat) dictionary)) ((equal? (cadr v) dat) dictionary) (else failed))))) (define (lookup var dictionary) (let ((v (assq var dictionary))) (if (null? v) var (cadr v)))) Predicates for types of expressions are straightforward. (define (compound? exp) (pair? exp)) (define (constant? exp) (number? exp)) (define (variable? exp) (atom? exp)) A rule is represented by a list of two parts, a pattern and a skeleton. (define (pattern rule) (car rule)) (define (skeleton rule) (cadr rule)) Within each pattern, explicit objects are represented by themselves, while generic objects are represented by a list, the first element of which identifies the type of generic object, and the second of which identifies the variable name of that object within the pattern. We distinguish three types of generic objects. (define (arbitrary-constant? pat) (if (pair? pat) (eq? (car pat)?c) false)) (define (arbitrary-expression? pat) (if (pair? pat) (eq? (car pat)?) false)) (define (arbitrary-variable? pat) (if (pair? pat) (eq? (car pat)?v) false)) (define (variable-name pat) (cadr pat)) On the skeleton side of the rule, we have two procedures (define (skeleton-evaluation? pat) (if (pair? pat) (eq? (car pat) :) false)) (define (evaluation-expression evaluation) (cadr evaluation)) The following procedure is included for completeness, but you need not worry about understanding exactly what it does until later in the term. For the purposes of this lecture, you can treat it as an abstraction that evaluates a given form, relative to the assignment of values to variables indicated in the dictionary. 6

(define (evaluate form dictionary) (if (atom? form) (lookup form dictionary) (apply (eval (lookup (car form) dictionary) user-initial-environment) (map (lambda (v) (lookup v dictionary)) (cdr form))))) Using the rules we called algebra-rules earlier we can define an algebraic simplification function as: (define algsimp (simplifier algebra-rules)) Exactly the same system can be used to build other symbolic simplifiers. The following rules create a simple symbolic differentiator. (define deriv-rules (( (dd (?c c) (? v)) 0 ) ( (dd (?v v) (? v)) 1 ) ( (dd (?v u) (? v)) 0 ) ( (dd (+ (? x1) (? x2)) (? v)) (+ (dd (: x1) (: v)) (dd (: x2) (: v))) ) ( (dd (* (? x1) (? x2)) (? v)) (+ (* (: x1) (dd (: x2) (: v))) (* (dd (: x1) (: v)) (: x2))) ) ( (dd (** (? x) (?c n)) (? v)) (* (* (: n) (** (: x) (: (- n 1)))) (dd (: x) (: v))) ) )) (define dsimp (simplifier deriv-rules)) In closing, it is worth considering that important aspects of the kind of evaluation characterizing Scheme itself can be captured by such rules. This should not be entirely surprising, since these tables of rules define certain fixed kinds of substitutions, and it is the substitution model that is our current model of Scheme. For example: (define scheme-rules (( (square (?c n)) (: (* n n)) ) ( (fact 0) 1 ) ( (fact (?c n)) (* (: n) (fact (: (- n 1)))) ) ( (fib 0) 0 ) ( (fib 1) 1 ) ( (fib (?c n)) (+ (fib (: (- n 1))) (fib (: (- n 2)))) ) ( ((? op) (?c e1) (?c e2)) (: (op e1 e2)) ) )) (define scheme-evaluator (simplifier scheme-rules)) A good exercise (though by no means trivial) is to work out the substitution model itself via such a set of rules. 7