Project 1: Part 1. x = b± b 2 4ac., x 2 = b b 2 4ac.

Similar documents
Project 1: Part 1. Project 1 will be to calculate orthogonal polynomials. It will have several parts. x = b± b 2 4ac., x 2 = b b 2 4ac.

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

Intro. Scheme Basics. scm> 5 5. scm>

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream?

Building a system for symbolic differentiation

STREAMS 10. Basics of Streams. Practice with Streams COMPUTER SCIENCE 61AS. 1. What is a stream? 2. How does memoization work?

Is the statement sufficient? If both x and y are odd, is xy odd? 1) xy 2 < 0. Odds & Evens. Positives & Negatives. Answer: Yes, xy is odd

Project 2: Scheme Interpreter

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

CS 360 Programming Languages Interpreters

Putting the fun in functional programming

Building a system for symbolic differentiation

Programming Project #2: Solving Quadratic Equations Date Due: Monday 25 September 2017

Table of Laplace Transforms

More Ways to Solve & Graph Quadratics The Square Root Property If x 2 = a and a R, then x = ± a

Intermediate Algebra. Gregg Waterman Oregon Institute of Technology

CSSE 304 Assignment #13 (interpreter milestone #1) Updated for Fall, 2018

2.2 Hierarchical Data and the Closure Property

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

An Explicit Continuation Evaluator for Scheme

CS61A Discussion Notes: Week 11: The Metacircular Evaluator By Greg Krimer, with slight modifications by Phoebus Chen (using notes from Todd Segal)

Repetition Through Recursion

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

Scheme: Strings Scheme: I/O

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))

An introduction to Scheme

MA 1128: Lecture 02 1/22/2018

4.2 Variations on a Scheme -- Lazy Evaluation

CS450: Structure of Higher Level Languages Spring 2018 Assignment 7 Due: Wednesday, April 18, 2018

Section 1.5 Transformation of Functions

Discussion 4. Data Abstraction and Sequences

Discussion 11. Streams

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

CS450 - Structure of Higher Level Languages

Section 1.5 Transformation of Functions

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

Programming Languages. Thunks, Laziness, Streams, Memoization. Adapted from Dan Grossman s PL class, U. of Washington

6.001: Structure and Interpretation of Computer Programs

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

Piecewise Defined Functions

CS 315 Software Design Homework 3 Preconditions, Postconditions, Invariants Due: Sept. 29, 11:30 PM

University of Massachusetts Lowell

Lists in Lisp and Scheme

Catalan Numbers. Table 1: Balanced Parentheses

A Brief Introduction to Scheme (II)

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

Simplifying Logical Formulas

Scheme Quick Reference

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

6.001 Notes: Section 8.1

Programming Languages. Function-Closure Idioms. Adapted from Dan Grossman's PL class, U. of Washington

Scheme in Scheme: The Metacircular Evaluator Eval and Apply

C+X. Complex Arithmetic Toolkit. Introduction

SCHEME AND CALCULATOR 5b

Math 2 Final Exam Study Guide. Translate down 2 units (x, y-2)

Administrivia. Simple data types

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

How to Design Programs Languages

An Explicit-Continuation Metacircular Evaluator

CS 275 Name Final Exam Solutions December 16, 2016

CSE413: Programming Languages and Implementation Racket structs Implementing languages with interpreters Implementing closures

A Quick Introduction to Common Lisp

CSc 520 Principles of Programming Languages

PreCalculus 300. Algebra 2 Review

The Typed Racket Guide

Solution Guide for Chapter 12

Typed Racket: Racket with Static Types

COP4020 Programming Assignment 1 - Spring 2011

a b c d a b c d e 5 e 7

CS61A Notes Disc 11: Streams Streaming Along

Lecture Numbers. Richard E Sarkis CSC 161: The Art of Programming

Documentation for LISP in BASIC

Lab copy. Do not remove! Mathematics 152 Spring 1999 Notes on the course calculator. 1. The calculator VC. The web page

Math 182. Assignment #4: Least Squares

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

Sample: Do Not Reproduce QUAD4 STUDENT PAGES. QUADRATIC FUNCTIONS AND EQUATIONS Student Pages for Packet 4: Quadratic Functions and Applications

Streams. CS21b: Structure and Interpretation of Computer Programs Spring Term, 2004

Functional Languages. Hwansoo Han

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

Project 5 - The Meta-Circular Evaluator

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

COUNTING AND CONVERTING

Here are a couple of warnings to my students who may be here to get a copy of what happened on a day that you missed.

Unit 1 and Unit 2 Concept Overview

Dr Richard Greenaway

Section 1.1 Definitions and Properties

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

Quadratic Functions Dr. Laura J. Pyzdrowski

Scheme Quick Reference

Generating Functions

/633 Introduction to Algorithms Lecturer: Michael Dinitz Topic: Priority Queues / Heaps Date: 9/27/17

Algorithms and Data Structures

Math 2 Coordinate Geometry Part 2 Lines & Systems of Equations

CSE 413 Languages & Implementation. Hal Perkins Winter 2019 Structs, Implementing Languages (credits: Dan Grossman, CSE 341)

MAT 003 Brian Killough s Instructor Notes Saint Leo University

CS 314 Principles of Programming Languages. Lecture 16

2.1 Basics of Functions and Their Graphs

Quicksort. Alternative Strategies for Dividing Lists. Fundamentals of Computer Science I (CS F)

Introduction to Scheme

Describe the Squirt Studio Open Office Version

Transcription:

Project 1: Part 1 Project 1 will be to calculate orthogonal polynomials. It will have several parts. Note: The scheme code in this writeup is available in the file project1.scm, available from the course web page. Warmup: Solving quadratic equations The quadratic formula says that the solutions of ax 2 +bx+c = 0 are given by x = b± b 2 4ac. 2a If b 2 4ac < 0 then b 2 4ac is imaginary, so there is no problem with round-off error. If b 2 4ac > 0 then cancellation can occur in b+ b 2 4ac if b > 0 and in b b 2 4ac if b < 0. Thus, if b > 0 one would want to use the computations x 1 = b b 2 4ac, x 2 = 2a 2c b b 2 4ac. Similarly if b < 0. Write a function (quadratic-solver a b c) that returns a list of the two roots of ax 2 +bx+c = 0 as accurately as possible. Test your code on the following problems: euler-126% gsi Gambit v4.1.2 > (sqrt -1) +i > (sqrt +i).7071067811865476+.7071067811865475i > (load "quadratic-solver") "/export/users/lucier/programs/615project/2007/project-1/quadratic-solver.scm" > (quadratic-solver 1 2 5) (-1+2i -1-2i) > (quadratic-solver 1-1 1) (1/2+.8660254037844386i 1/2-.8660254037844386i) > (quadratic-solver 1 2-1) (-2.414213562373095.4142135623730951) > (quadratic-solver 4 1 1) (-1/8+.4841229182759271i -1/8-.4841229182759271i) > (quadratic-solver 4 4 1) (-1/2-1/2) > (quadratic-solver 4 0 1) (+1/2i -1/2i) > (quadratic-solver 0 0 1) *** ERROR IN (console)@11.1 -- not a quadratic: 0 0 1 1> > (quadratic-solver 4 0-1) (-1/2 1/2) > (quadratic-solver 1 3138428376721 1) (-3.138428376721e12-3.186308177103568e-13) > *** EOF again to exit 1

2 Meroon Standard Scheme (so-called R5RS Scheme, which Gambit implements) does not have an object system. We use an object system provided by the software package Meroon. To use Gambit, you need to have /pkgs/gambit-c/current/bin/ in your path. The Gambit interpreter is called gsi and the Gambit compiler is called gsc. To have Gambit load Meroon automatically, just call gsi++ or gsc++. Our system has two differences with standard Meroon: (1) In standard Meroon, keywords begin with a colon; in our Meroon keywords end with a colon: (define-class Polynomial Object ((= variable immutable:) (= terms immutable:))) (2) In standard Meroon, so-called setters begin with set- and end with!. In our Meroon, setters end with -set!: euler-130% gsi++ [ Meroon V3 Paques2001+1 $Revision: 1.5 $ ] Gambit v4.1.2 > (define-class Point Object (x y)) Point > (define p (make-point 0 1)) > (unveil p) (a Point <------------- [Id: 1] x: 0 y: 1 end Point) #t > (Point-x-set! p 1) #<meroon #2> > (unveil p) (a Point <------------- [Id: 1] x: 1 y: 1 end Point) #t > Numerical Integration This first part will be about numerical integration (quadrature rules). The Gauss-Lobatto quadrature rules with n points have the form 1 1 n 1 f(x)dx γ nν f(x nν ). Here x n0 = 1, x n,n 1 = 1, and x n,ν, ν = 1,...,n 2, are the zeros of the degree n 2 orthogonal polynomial over [ 1, 1] with the weight w(x) = 1 x 2. If we define then l nκ has degree n 1 and satisfies l nκ (x) = n 1 ν=0 ν κ ν=0 x x nν x nκ x nν { 1, ν = κ, l nκ (x nν ) = 0, ν κ.

The weights γ nν satisfy γ nν = 1 1 l n,ν (x)dx. So, the first part of the project is to write code to manipulate polynomials. We ll keep the code at http://mitpress.mit.edu/sicp/full-text/sicp/book/node49.html in the back of our heads as a model, while writing new code that uses Meroon s framework of classes/objects and generics/methods. We ll refer to this web page as the SICP web page. A good thing to keep in the back of your mind is that, generally speaking, code should not depend on the implementation technique of terms or termlists. The code in SICP uses lists for both terms and termlists of polynomials, but that can be confusing, especially for debugging. So we ll define a polynomial class: (define-class Polynomial Object ((= variable immutable:) ; a symbol (= terms immutable:))) ; a list of terms and a way to check whether two Polynomial variables are the same: (define (Polynomial-variable= var1 var2) (eq? var1 var2)) The terms of a polynomial is just a list of nonzero terms, in decreasing order by degree (unfortunately called order at the SICP web page), so we need some code to manipulate terms and lists of terms: ;;; a term is a pair (order coeff) (order should really be degree, but...) ;;; We re going to use a Meroon class for terms to aid debugging. (define-class term Object ((= order) (= coeff))) The generic function initialize! is called on all Meroon objects after their construction, and for polynomials we use initialize! to check that the invariants we assume about polynomials are satisfied whenever we create one: (define-method (initialize! (p Polynomial)) (let ((terms (Polynomial-terms p))) ;; check that ;; (a) termlists are in decreasing order (let loop ((terms terms)) (cond ((or (empty-termlist? terms) (empty-termlist? (rest-terms terms))) ;; We re done checking the orders of terms ) ((> (term-order (first-term terms)) (term-order (first-term (rest-terms terms)))) (loop (rest-terms terms))) (error "initialize! for Polynomials: terms are not in decreasing order" p)))) ;; (b) check that coeffs are not zero (let loop ((terms terms)) (cond ((empty-termlist? terms) ;; We re done checking that terms are nonzero ) ((not (=zero? (term-coeff (first-term terms)))) (loop (rest-terms terms))) (error "initialize! for Polynomials: some terms have zero coefficients" p)))) (call-next-method))) You are asked to define the generic function =zero? in Problem 1. 3

4 It is not good form to use initialize! to enforce the invariants by, e.g., sorting the terms in decreasing order or removing all terms with zero coefficients. Having initialize! check these invariants, and ensuring all code that manipulates Polynomials preserves these invariants helps in debugging. We will need some operations on lists. The functions map and for-each are built into Scheme (learn them!) but we will need some more: ;;; See the Haskell Wiki page ;;; http://www.haskell.org/haskellwiki/fold ;;; for a good explanation, together with pictures, for how ;;; fold-left and fold-right work. (define (fold-left operator initial-value list) (if (null? list) initial-value (fold-left operator (operator initial-value (car list)) (cdr list)))) (define (fold-right operator initial-value list) (if (null? list) initial-value (operator (car list) (fold-right operator initial-value (cdr list))))) ;;; map is a builtin function that works on lists, but it could ;;; be defined as follows: (define (my-map f list) (fold-right (lambda (v l) (cons (f v) l)) () list)) And one can use the usual functions car, cdr, cadr, null? and the usual empty list (), but we need a better way to add a term to a list of terms, since we don t want any zero terms in our termlists: (define (adjoin-term term term-list) (if (=zero? (term-coeff term)) term-list (cons term term-list))) (define (map-termlist f list) (fold-right (lambda (v l) (adjoin-term (f v) l)) () list) In map-termlist, the function f must return a term and we let the initialize! method for Polynomials check that the order of the terms is decreasing. The SICP web page has code for adding two polynomials. Putting it into our terms we define a generic function add that should work for everything, and we start with it working with numbers: (define-generic (add (x) y) (if (number? x) (if (number? y) ;; We know how to add two numbers. (+ x y) ;; We don t know how to add a number to an arbitrary object, ;; but perhaps there is a method to add the object y to ;; a number, so we swap arguments and try again. (add y x)) ;; If x isn t a number, we don t have a method for it.

(error "add: This generic is not defined on these objects: " x y))) and then we define a method for adding Polynomials: (define-method (add (p_1 Polynomial) p_2) (cond ((number? p_2) (add p_1 (number->polynomial p_2 (Polynomial-variable p_1)))) ((and (Polynomial? p_2) (Polynomial-variable= (Polynomial-variable p_1) (Polynomial-variable p_2))) (instantiate Polynomial variable: (Polynomial-variable p_1) terms: (add-terms (Polynomial-terms p_1) (Polynomial-terms p_2)))) (error "add: p_2 is neither a number nor a polynomial with the same variable as p_1 " p_1 p_2)))) This method is called only when p_1 is a polynomial; if p_2 is a number, it converts p_2 to a Polynomial with the same variable as p_1 and calls add again with both arguments now a Polynomial. So you need to define number->polynomial, which takes two arguments. The SICP web page has code for add-terms: (define (add-terms l1 l2) (cond ((null? l1) l2) ((null? l2) l1) (let ((t1 (car l1)) (t2 (car l2))) (cond ((> (term-order t1) (term-order t2)) (adjoin-term t1 (add-terms (cdr l1) l2))) ((< (term-order t1) (term-order t2)) (adjoin-term t2 (add-terms l1 (cdr l2)))) (adjoin-term (make-term (term-order t1) (add (term-coeff t1) (term-coeff t2))) (add-terms (cdr l1) (cdr l2))))))))) You need to define a multiply generic that works with numbers by default, and a method for multiply that works on Polynomials; follow ths same pattern as for add. The SICP web page has the guts of the code: (define (multiply-terms l1 l2) (if (null? l1) l1 (add-terms (multiply-term-by-all-terms (car l1) l2) (multiply-terms (cdr l1) l2)))) (define (multiply-term-by-all-terms t1 L) (if (null? L) L (let ((t2 (car L))) (adjoin-term 5

6 (make-term (+ (term-order t1) (term-order t2)) (multiply (term-coeff t1) (term-coeff t2))) (multiply-term-by-all-terms t1 (cdr L)))))) So that s pretty much the code that comes on the web page. Meroon defines a generic function show that we can specialize for Polynomials as such: (define-method (show (p Polynomial). stream) (let ((port (if (null? stream) (current-output-port) (car stream)))) (if (=zero? p) (display 0) (show-terms (Polynomial-variable p) (Polynomial-terms p) port)) (newline port))) (define (show-terms variable terms port) (show-first-term variable (car terms) port) (for-each (lambda (term) (show-term variable term port)) (cdr terms))) (define (show-first-term variable term port) (let ((coeff (term-coeff term)) (order (term-order term))) (print port: port (list (if (and (= coeff 1) (positive? order)) () coeff) (cond ((zero? order) ()) ((= order 1) variable) (list variable "^" order))))))) (define (show-term variable term port) (let ((coeff (term-coeff term)) (order (term-order term))) (print port: port (list (if (negative? coeff) "-" "+") (let ((abs-coeff (abs coeff))) (if (and (eq? coeff 1) (< 0 order)) () (abs coeff))) (cond ((zero? order) ()) ((= order 1) variable) (list variable "^" order))))))) It will probably help your debugging.

So, here are some problems. (1) The above code uses a function =zero?. Define a generic function =zero? that handles numbers. Define a method that works with Polynomials. Why does the initialize! method for polynomials use =zero? to check whether coefficients are zero rather than the built-in Scheme function zero?. (2) Define a generic function (negate (x)) that handles numbers by default. Define a method for negate that works with Polynomials. Use the generic negate to define a regular function (subtract x y). (Remember that a polynomial in x may have coefficients that are polynomials in y, so write negate so it works with these types of polynomials.) (3) Define a function (exponentiate x n) that uses multiply to exponentiate anything that multiply can multiply. Use the discussion of exponentiation on page http://mitpress.mit.edu/sicp/full-text/book/book-z-h-11.html#%_sec_1.2 as your model. You should be able to exponentiate a polynomial. (4) Define a function (variable->polynomial x) that takes a symbol x and returns a Polynomial that represents the polynomial x, i.e., a single term with coefficient 1 and order 1. Define a function (number->polynomial n x) where n is a number and x is a symbol. (Hint: Use make-term, adjointerm, and the-empty-termlist to calculate the termlist in number->polynomial.) (5) Define a generic function (evaluate f x) that evaluates the function f at x. If f is a number, assume that it means a function that constantly returns f (so the generic is supposed to work with both numbers v and Scheme functions f). Define a method for Polynomials. If p is a polynomial, then you should be able to say (evaluate p p), i.e., evaluate a polynomial with another polynomial as an argument. If you ve done the exercises until now, something like the following should work. ;;; evaluation (define-generic (evaluate (f) x) (cond ((number? f) f) ((procedure? f) (f x)) (error "evaluate: unknown argument types " f x)))) (define-method (evaluate (p Polynomial) x) (evaluate-terms (Polynomial-terms p) x)) (define (evaluate-terms terms x) (if (null? terms) 0 (add (evaluate-term (car terms) x) (evaluate-terms (cdr terms) x)))) (define (evaluate-term term x) (multiply (exponentiate x (term-order term)) (term-coeff term))) Can you write a method that uses Horner s rule for evaluating Polynomials in our representation? Changes make 2014/02/14 (1) Add a hint about how to write number->polynomial. Changes made 2012/02/27 (1) The project will just be about orthogonal polynomials. (2) Corrected the formula for γ nν. (3) Changed the definition of add so it can add polynomials to numbers in either order. I added some comments to the problems: (1) Added map-termlist as an exercise. (2) Made more explicit my expectations for negate, exponentiate, and evaluate. (3) Redid the definition of the evaluate generic to match its specification. Changes made 2012/03/07 (1) Make a term a Meroon object for easier debugging. 7

8 (2) (Polynomial-terms p) was a regular list, so I m just going to use the regular list operations, except for adjoin-term and map-termlist, which check that the term is nonzero before adding it to the list. Got rid of first-term, rest-terms, empty-termlist?, etc., and changed their uses to regular list operations. (3) Since map-termlist is already defined, don t have it as an exercise. (4) Defined fold-left and fold-right earlier, so I could use them in map-termlist. Changes made 2012/05/17 (1) Change the definition of the interpolation points to handle 1 and 1 in the same way as the other interpolation points. Fix the upper limit of the product defining l nκ. (2) Move the definition of initialize! for polynomials from the web page to here. Explain its use. (3) Generally clean up the discussion.