Using Scheme to calculate Newton-Raphson's - scheme

According to Newton-Raphson's:
Xn+1 = Xn - f(Xn) / f'(Xn)
(newtonRhap x f fx)
(newtonRhap 0.1 sin cos) => 0
(newtonRhap 2.0
(lambda (x) (- (* x x) x 6)) ; f
(lambda (x) (- (* 2 x) 1 )) ) => 3 ; f'
How can I implement this function?
The routine will stop iteration when the change in solution is less than pre-set tolerance.
I use a global variable for it, (define TOL 1e-6):
#lang racket
(define TOL 1e-6)
(define (func f x) (f x))
(define (f x) (- (* x x) x 6))
(define (fx x) (- (* 2 x) 1))
(define x 2.0)
(define (newtonRhap x ff ffx)
( (> (- x (/ ff ffx)) TOL)
(newtonRhap (- x (/ ff ffx)) ff ffx)
(list x) ) )
(display (newtonRhap x (f x) (fx x)) )

Good attempt, you need to modify newtonRaph function to use IF though, like this
(define (newtonRhap x ff ffx)
(if (> (- x (/ ff ffx)) TOL)
(newtonRhap (- x (/ ff ffx)) ff ffx))
(list x)))

First, you're missing an if there:
(define (newtonRhap x ff ffx)
( if (> (- x (/ ff ffx)) TOL)
(newtonRhap (- x (/ ff ffx)) ff ffx)
(list x) ) )
Without it you would be calling the result of the Boolean test as a function with the following two forms values as arguments (it could work in a lazy functional language with Church-encoded conditionals, but that's besides the point, and Scheme / Racket is not lazy).
Second, and even more crucially, the last two arguments to newtonRhap are functions, but you're treating them as if they were numeric values. Correcting this gives us
(define (nl x) ; for debugging insight;
(newline) ; for production redefine it as
(display x) ; (define (nl x) x)
x)
(define (newtonRhap x ff ffx)
(let ((new-x (nl (- x (/ (ff x) (ffx x)))))) ; Follow The Formula
( if (> (abs (- x new-x)) TOL) ; use abs
(newtonRhap new-x ff ffx) ; make next step
(list new-x) ) ) ) ; return the new x, it's closer to the true result
Now we can run
(display (newtonRhap x f fx))
3.333333333333333
3.019607843137255
3.0000762951094835
3.000000001164153
3.0(3.0)
>

Related

Printing decimal numbers get rounded up in chicken-scheme

I have a scheme procedure that returns 0.24999999999999992 as a result. However, when I tried to print this result with chicken-scheme on my machine, it gets rounded to 0.25. How can I prevent rounding?
I tried running the same procedure on repl.it, and the print command here outputs the result without rounding.
If it helps, the code below:
(define (sum term a next b)
(if
(> a b)
0
(+ (term a) (sum term (next a) next b))
)
)
(define (integral-simpson f a b n)
(define h (/ (- b a) n))
(define (inc x) (+ x 1))
(define (term x)
(cond
((or (= x 0) (= x n)) (f (+ a (* x h))))
((even? x) (* 2 (f (+ a (* x h)))))
((odd? x) (* 4 (f (+ a (* x h)))))
)
)
(* (/ h 3)
(sum
term
a
inc
n
)
)
)
(define (cube x)
(* x x x)
)
(print (integral-simpson cube 0 1 100))
Try changing the print precision: (flonum-print-precision 17)

Riemann integral formula to compute high-order function

SICP introduced Riemann integral formula in Chapter 1.3.1
(define (integral f a b dx)
(define (add-dx x) (+ x dx))
(* (sum f (+ a (/ dx 2.0)) add-dx b)
dx))
Apply it to a particular case
#+name: case-1.3.1-integral.scm
#+BEGIN_SRC scheme :session sicp
(define pi 3.141592653589793)
(define (integral2 f a b dx)
(define (add-dx x) (+ x dx))
(* (sum (f b)
(+ a (/ dx 2.0))
(lambda (x) (+ x dx))
b)
dx))
(define (f b)
(lambda (x) (/ 1 (sqrt
(- (sin x)
(sin b))))))
(* (integral2 f 0 (/ pi 6) 0.00001)
(sqrt (/ 40
(* 3 9.8))))
#+END_SRC
#+RESULTS: case-1.3.1-integral.scm
: 0.0-1.777598336021436i
Got a perfect answer 1.777598336021436
Then translate it to elisp
Start from small:
#+name: case-1.3.1-integral.el
#+begin_src emacs-lisp :session sicp :lexical t
(defun integral (f a b dx)
(* (sum f
(+ a (/ dx 2.0))
(lambda (x) (+ x dx))
b)
dx))
(defun sum(term a next b)
(if (> a b)
0
(+ (funcall term a)
(sum term (funcall next a) next b))))
(integral #'cube 0 1 0.01)
#+end_src
#+RESULTS: case-1.3.1-integral.el
: 0.24998750000000042
It works and thus use it to solve the previous problem
#+begin_src emacs-lisp :session sicp :lexical t
(defvar pi 3.141592653589793)
(defun integral (f a b dx)
(* (sum f
(+ a (/ dx 2.0))
(lambda (x) (+ x dx))
b)
dx))
(defun f (b)
(lambda (x) (/ 1 (sqrt
(- (sin x)
(sin b))))))
(defun integral2 (f a b dx)
(* (sum (funcall f b)
(+ a (/ dx 2.0))
(lambda (x) (+ x dx))
b)
dx))
(integral2 #'f 0 (/ pi 6) 0.01)
#+end_src
But it return a meaningless result
ELISP> (integral2 #'f 0 (/ pi 6) 0.01)
-0.0e+NaN
What's the problem?
The answer you obtained when using Scheme is a complex number, the result of calling sqrt (are you sure the Scheme code was correct in the first place? you should double-check it):
0.0-1.777598336021436i
Unfortunately, Elisp doesn't support complex numbers, that's why we get a NaN in there. But that's not the real problem; you should investigate why are you getting complex results in the Scheme code, an integral should not return complex values!

How to produce a stream of guesses for the root of f?

I would like to produce a stream of guesses for the root of f with 3 arguments f fx and x with f = sin(x) and x = 3. I tried some code but i don't get it. I would appreciate it if you could provide me some help.
(define (stream f fx x)
(let ((x (3))
((f x) (sin x))
((fx x) (cos x)))
(cons-stream (x (stream f fx (x (- x (/ (f x) (fx x)))))))))
(stream f fx 3)
Your code is this (I've applied indentation to make the bracketing clearer):
(define (stream f fx x)
(let ((x (3))
((f x) (sin x))
((fx x) (cos x)))
(cons-stream (x (stream f fx (x (- x (/ (f x) (fx x))))
))
)))
(stream f fx 3)
You have a few mistakes in this:
(3) treats 3 as a procedure and tries to call it. You should have 3 instead.
You have put specific arguments 3, sin, cos inside the general function. It should be outside instead.
You have done (x (stream ...)) and (x (- x ..)) both treat x like a function, but it's a number.
So clearing up these mistakes the code will be more like this:
(define (stream f fx x)
(cons-stream x (stream f fx (- x (/ (f x) (fx x))))))
(let ((x 3)
(f (lambda (x) (sin x)))
(fx (lambda (x) (cos x))))
(stream f fx x))
lambda was used to define a local function. Hope that helps, Feel free to ask follow up questions if anything was unclear.

Recursive function not working as planned

I am writing a function in Scheme that is supposed to take two integers, X and Y, and then recursively add X/Y + (X-1)/(Y-1) + ...until one of the numbers reaches 0.
For example, take 4 and 3:
4/3 + 3/2 + 2/1 = 29/6
Here is my function which is not working correctly:
(define changingFractions (lambda (X Y)
(cond
( ((> X 0) and (> Y 0)) (+ (/ X Y) (changingFunctions((- X 1) (- Y 1)))))
( ((= X 0) or (= Y 0)) 0)
)
))
EDIT: I have altered my code to fix the problem listed in the comments, as well as changing the location of or and and.
(define changingFractions (lambda (X Y)
(cond
( (and (> X 0) (> Y 0)) (+ (/ X Y) (changingFunctions (- X 1) (- Y 1) )))
( (or (= X 0) (= Y 0)) 0)
)
))
Unfortunately, I am still getting an error.
A couple of problems there:
You should define a function with the syntax (define (func-name arg1 arg2 ...) func-body), rather than assigning a lambda function to a variable.
The and and or are used like functions, by having them as the first element in a form ((and x y) rather than (x and y)). Not by having them between the arguments.
You have an extra set of parens around the function parameters for the recursive call, and you wrote changingFunctions when the name is changingFractions.
Not an error, but don't put closing parens on their own line.
The naming convention in Lisps is to use dashes, not camelcase (changing-fractions rather than changingFractions).
With those fixed:
(define (changing-fractions x y)
(cond
((and (> x 0) (> y 0)) (+ (/ x y) (changing-fractions (- x 1) (- y 1))))
((or (= x 0) (= y 0)) 0)))
But you could change the cond to an if to make it clearer:
(define (changing-fractions x y)
(if (and (> x 0) (> y 0))
(+ (/ x y) (changing-fractions (- x 1) (- y 1)))
0))
I personally like this implementation. It has a proper tail call unlike the other answers provided here.
(define (changing-fractions x y (z 0))
(cond ((zero? x) z)
((zero? y) z)
(else (changing-fractions (sub1 x) (sub1 y) (+ z (/ x y))))))
(changing-fractions 4 3) ; => 4 5/6
The trick is the optional z parameter that defaults to 0. Using this accumulator, we can iteratively build up the fractional sum each time changing-fractions recurses. Compare this to the additional stack frames that are added for each recursion in #jkliski's answer
; changing-fractions not in tail position...
(+ (/ x y) (changing-fractions (- x 1) (- y 1)))

Gaussian functions and currying in Scheme

I am currently trying to learn Scheme to run FDTD simulations and I am having trouble building a Gaussian function in 2 dimensions.
In a forum I found this possibility for 1D:
(define ( (gaussx sigma) x)
(exp (- (/ (vector3-dot x x) (* 2 sigma sigma)))))
which if I understood currying correctly is equivalent to:
(define (gauss sigma)
(lambda(x)
(exp (- (/ (vector3-dot x x) (* 2 sigma sigma))))))
Now I would like the function to be gaussian along both x and y directions but I don't understand why this doesn't work:
(define (gauss sigma)
(lambda(x)
(lambda(y)
(exp (- (/ (+ (vector3-dot y y) (vector3-dot x x)) (* 2 sigma sigma))))
When I call
(gauss 1)
I get the following message:
ERROR: Wrong type (expecting real number): # <procedure> #f (y)
Does someone see what I am doing wrong? I also tried other solutions but I don't seem to get the logics here...
Thanks a lot for your help!
Best regards
Mei
I don't think there's need for a double currying here, try this:
(define (gauss sigma)
(lambda (x y)
(exp (- (/ (+ (vector3-dot y y) (vector3-dot x x)) (* 2 sigma sigma))))))
Call it like this:
(define gauss-1 (gauss 1))
(gauss-1 some-x some-y)
But if you definitely need the double currying, this should work:
(define (gauss sigma)
(lambda (x)
(lambda (y)
(exp (- (/ (+ (vector3-dot y y) (vector3-dot x x)) (* 2 sigma sigma)))))))
Using it like this:
(define gauss-1 (gauss 1))
((gauss-1 some-x) some-y)

Resources