Difference of (sqrt-iter-cond 1 x) and (sqrt-iter-cond 1.0 x) - elisp

I read the answer https://stackoverflow.com/a/58899297/7301792 which find the sqrt with iteration
#+begin_src emacs-lisp :session sicp :lexical t
(defun sqrt-iter-cond(guess x)
(cond ((good-enough-p guess x) guess)
(t (sqrt-iter-cond (improve guess x) x))
)
)
(defun good-enough-p(guess x)
(< (abs (- (square guess) x)) 0.001))
(defun improve(guess x)
(average guess (/ x guess)))
(defun average(x y)
(/ (+ x y) 2))
(sqrt-iter-cond 1.0 13))
#+end_src
#+RESULTS:
: 3.6055513629176015
However, if change 1.0 to 1, it report error
#+begin_src emacs-lisp :session sicp :lexical t
(sqrt-iter-cond 1 13)
#+end_src
Lisp nesting exceeds ‘max-lisp-eval-depth’
What's the problem here?

Consider the difference between calling your average function with two integers and calling it with two numbers where one or more is a floating-point number:
(average 3 4)
3
vs.
(average 3.0 4)
3.5
With integers, you get stuck in an infinite loop because improve calls average, which eventually keeps returning the same integer value due to integer arithmetic. But with floating-point numbers, improve actually moves the guess closer to the result on each call because average isn't limited to returning only integers.
An easy fix for the problem is to change the average function to divide by 2.0 instead of 2:
(defun average(x y)
(/ (+ x y) 2.0))
If you set debug-on-error to t, the backtrace with the original code gives you an idea of where the problem is:
Debugger entered--Lisp error: (error "Lisp nesting exceeds ‘max-lisp-eval-depth’")
(abs (- (* guess guess) x))
(< (abs (- (* guess guess) x)) 0.001)
good-enough-p(3 13)
(cond ((good-enough-p guess x) guess) (t (sqrt-iter-cond (improve guess x) x)))
sqrt-iter-cond(3 13)
(cond ((good-enough-p guess x) guess) (t (sqrt-iter-cond (improve guess x) x)))
sqrt-iter-cond(3 13)
(cond ((good-enough-p guess x) guess) (t (sqrt-iter-cond (improve guess x) x)))
sqrt-iter-cond(3 13)
...
The ... is there to indicate that the backtrace just keeps repeating.
Alternatively, just adding a message call into the improve function can help:
(defun improve(guess x)
(message (format "guess: %f, x: %f" guess x))
(average guess (/ x guess)))
With the original average function using integer arithmetic, the *Message* buffer shows:
guess: 4.000000, x: 13.000000
guess: 3.000000, x: 13.000000 [391 times]
With floating-point numbers, the messages show the guess converging to the answer:
guess: 1.000000, x: 13.000000
guess: 7.000000, x: 13.000000
guess: 4.428571, x: 13.000000
guess: 3.682028, x: 13.000000
guess: 3.606345, x: 13.000000

Related

How to step through this evaluation?

I would like to see how the value of a square root is iteratively improved. For example on the following:
#lang sicp
(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(define (improve guess x) (average guess (/ x guess)))
(define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001 ))
(define (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x)))
(define (sqrt x) (sqrt-iter 1.0 x))
(sqrt 2)
It gets values such as the following:
1 1
2 1.5
3 1.4166666666666665
4 1.4142156862745097
As an example of what I want to show, in Javascript I would do something like:
const sqrt_iter = (guess, x) => {
console.log(count++, guess);
return good_enough(guess, x) ? guess : sqrt_iter(improve(guess, x), x);
}
const sqrt = x => sqrt_iter(1.0, x);
How could I print or trace these intermediate values in DrRacket/SICP? I tried doing (trace sqrt) but it said not found.
I am sure Racket has some fancy trace facility. But there's a famous quote (due I think to John Foderaro):
Lisp [for which read Racket] is the programmable programming language.
What this means is: if there's no tracing facility, or you are too lazy to make one, you can just write one.
Here is a rudimentary one I wrote in five minutes:
#lang racket
(provide define/traced)
(define trace-depths (make-parameter 0))
(define (spaces n)
(make-string n #\ ))
(define-syntax define/traced
(syntax-rules ()
[(_ (name arg ...) form ...)
(define/traced name (λ (arg ...) form ...))]
[(_ (name . args) form ...)
(define/traced name (λ args form ...))]
[(_ name function)
(define name
(λ args
(let* ([depth (trace-depths)]
[prefix (spaces depth)])
(parameterize ([trace-depths (+ depth 1)])
(printf "~A~S ...~%" prefix `(,'name ,#args))
(call-with-values
(thunk (apply function args))
(λ results
(printf "~A-> ~S~%" prefix results)
(apply values results)))))))]))
Stash this in a file called define-traced.rkt and then require it, and tell it to trace the procedures you care about:
#lang racket
(require "define-traced.rkt")
(define (square x) (* x x))
(define (average x y) (/ (+ x y) 2))
(define/traced (improve guess x) (average guess (/ x guess)))
(define (good-enough? guess x) (< (abs (- (square guess) x)) 0.001 ))
(define/traced (sqrt-iter guess x) (if (good-enough? guess x) guess (sqrt-iter (improve guess x) x)))
(define (sqrt x) (sqrt-iter 1.0 x))
(sqrt 2)
Which will duly print this:
(sqrt-iter 1.0 2) ...
(improve 1.0 2) ...
-> (1.5)
(sqrt-iter 1.5 2) ...
(improve 1.5 2) ...
-> (1.4166666666666665)
(sqrt-iter 1.4166666666666665 2) ...
(improve 1.4166666666666665 2) ...
-> (1.4142156862745097)
(sqrt-iter 1.4142156862745097 2) ...
-> (1.4142156862745097)
-> (1.4142156862745097)
-> (1.4142156862745097)
-> (1.4142156862745097)
1.4142156862745097
Note that when I said it was a rudimentary facility I meant it: in particular it will probably turn tail calls into non-tail calls, and there are many other things wrong with it. But it took less long to write than it would take to read the manual on some hairy facility. If I was going to use this thing just once (and this is probably the only time I will ever use it: it only made it into a file so I could require it in another file) it's worth it. This is one of the glories of Lisp-family languages.
Try begin with printf (and also add one variable as counter):
#lang racket
(define (square x)
(* x x))
(define (average x y)
(/ (+ x y) 2))
(define (improve guess x)
(average guess (/ x guess)))
(define (good-enough? guess x)
(< (abs (- (square guess) x)) 0.001 ))
(define (sqrt-iter guess x count)
(begin
(printf "~a ~a \n" count guess)
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x)
x
(+ 1 count)))))
(define (sqrt x) (sqrt-iter 1.0 x 1))
(sqrt 2)
1 1.0
2 1.5
3 1.4166666666666665
4 1.4142156862745097
1.4142156862745097
Note that I used #lang racket- it seems that sicp don't have print or printf, but you can try write or display to achieve similar result.
#ignis provides the proper technique for this. However, before you dive into the deep ocean of define-syntax, maybe you want the quick-and-dirty approach -
#lang sicp
(define (sqrt-iter guess x)
(for-each display (list "sqrt-iter" " " guess " " x "\n"))
(if (good-enough? guess x)
guess
(sqrt-iter (improve guess x) x)))
(sqrt 2)
sqrt-iter 1.0 2
sqrt-iter 1.5 2
sqrt-iter 1.4166666666666665 2
sqrt-iter 1.4142156862745097 2
1.4142156862745097

Contract Violation; expected: real?; given #f

I'm sorry if this question has been answered before, but I've looked around and I can't really understand the explanation as to why I'm getting this error.
From what I understand I'm asking if a statement is true and then if it is I'm asking it to return an expression. And apparently I'm not allowed to get #t/#f answers and expressions? I'm not sure. Could someone help me understand.
This is my code.
(define (piecewise x)
(define pi 3.142)
(cond
((> x (* pi 2)) (- x (* 2 pi)))
((or ( > x (* pi -1) (= x ( * -1 pi)))) (sin x))
((or ( < x (* 2 pi)) (= x (* 2 pi))) (sin x))
(else (- (- 1 x) pi))))
If I may, if we take all of the suggestions and use them to simplify the code a bit, we might get the following:
(define (piecewise x)
(let* ((pi 3.142)
(tau (* 2 pi)))
(cond
((> x tau)
(- x tau))
((or (>= x (- pi))
(<= x tau))
(sin x))
(else (+ x pi)))))
This runs without errors under both Racket and Guile. Whether it computes the function correctly, only the OP can say for certain.

Scheme: Not a procedure (Dr. Racket)

I'm running this program in Dr. Racket using R5RS scheme and am getting this error on the line (+ 1 IntDivide((- x y) y)):
"application: not a procedure; expected a procedure that can be
applied to arguments given: 5 arguments...:"
The procedure is supposed to return the quotient of the division between two integers using subtraction. Since this is a homework problem, I'm not going to ask whether my solution is correct (I can debug that later), but rather what is causing this error. It seems to be commonly caused by excess brackets, but I can't seem to find them. Any help would be appreciated.
(define IntDivide (lambda (x y)
(if (eqv? (integer? x) (integer? y))
(begin
(if (= y 0)
(begin
(write "Can't divide by zero") (newline)
-1
)
)
(if (= (- x y) 0)
1
)
(if (< x y)
0
)
(if (> x y)
(+ 1 IntDivide((- x y) y))
)
)
)
(write "Please only input integers")
))
Thanks in advance!
In addition to moving the operator inside the parens, you also need to replace the if with a cond:
(define IntDivide
(lambda (x y)
(if (eqv? (integer? x) (integer? y))
(cond ((= y 0) (write "Can't divide by zero")
(newline)
-1)
((= x y) 1)
((< x y) 0)
((> x y) (+ 1 (IntDivide (- x y) y))))
(write "Please only input integers"))))
The way you have it now, with the interior if expressions, won't work because they don't automatically return. They just evaluate and then the result gets thrown away.
Call IntDivide the same way you would any other function.
(+ 1 (IntDivide (- x y) y))

Can this function be simplified (made more "fast")?

I was wondering if this is the fastest possible version of this function.
(defun foo (x y)
(cond
;if x = 0, return y+1
((zp x) (+ 1 y))
;if y = 0, return foo on decrement x and 1
((zp y) (foo (- x 1) 1))
;else run foo on decrement x and y = (foo x (- y 1))
(t (foo (- x 1) (foo x (- y 1))))))
When I run this, I usually get stack overflow error, so I am trying to figure out a way to compute something like (foo 3 1000000) without using the computer.
From analyzing the function I think it is embedded foo in the recursive case that causes the overflow in (foo 3 1000000). But since you are decrementing y would the number of steps just equal y?
edit: removed lie from comments
12 years ago I wrote this:
(defun ackermann (m n)
(declare (fixnum m n) (optimize (speed 3) (safety 0)))
(let ((memo (make-hash-table :test #'equal))
(ncal 0) (nhit 0))
(labels ((ack (aa bb)
(incf ncal)
(cond ((zerop aa) (1+ bb))
((= 1 aa) (+ 2 bb))
((= 2 aa) (+ 3 (* 2 bb)))
((= 3 aa) (- (ash 1 (+ 3 bb)) 3))
((let* ((key (cons aa bb))
(val (gethash key memo)))
(cond (val (incf nhit) val)
(t (setq val (if (zerop bb)
(ack (1- aa) 1)
(ack (1- aa) (ack aa (1- bb)))))
(setf (gethash key memo) val)
val)))))))
(let ((ret (ack m n)))
(format t "A(~d,~d)=~:d (~:d calls, ~:d cache hits)~%"
m n ret ncal nhit)
(values ret memo)))))
As you can see, I am using an explicit formula for small a and memoization for larger a.
Note, however, that this function grows so fast that it makes little sense to try to compute the actual values; you will run out of atoms in the universe faster - memoization or not.
Conceptually speaking, stack overflows don't have anything to do with speed, but they concern space usage. For instance, consider the following implementations of length. The first will run into a stack overflow for long lists. The second will too, unless your Lisp implements tail call optimization. The third will not. All have the same time complexity (speed), though; they're linear in the length of the list.
(defun length1 (list)
(if (endp list)
0
(+ 1 (length1 (rest list)))))
(defun length2 (list)
(labels ((l2 (list len)
(if (endp list)
len
(l2 (rest list) (1+ len)))))
(l2 list 0)))
(defun length3 (list)
(do ((list list (rest list))
(len 0 (1+ len)))
((endp list) len)))
You can do something similar for your code, though you'll still have one recursive call that will contribute to stack space. Since this does appear to be the Ackermann function, I'm going to use zerop instead of zp and ack instead of foo. Thus, you could do:
(defun foo2 (x y)
(do () ((zp x) (+ 1 y))
(if (zp y)
(setf x (1- x)
y 1)
(psetf x (1- x)
y (foo x (1- y))))))
Since x is decreasing by 1 on each iteration, and the only conditional change is on y, you could simplify this as:
(defun ack2 (x y)
(do () ((zerop x) (1+ y))
(if (zerop y)
(setf x (1- x)
y 1)
(psetf x (1- x)
y (ack2 x (1- y))))))
Since y is the only thing that conditionally changes during iterations, you could further simplify this to:
(defun ack3 (x y)
(do ((x x (1- x))
(y y (if (zerop y) 1 (ack3 x (1- y)))))
((zerop x) (1+ y))))
This is an expensive function to compute, and this will get you a little bit farther, but you're still not going to get, e.g., to (ackN 3 1000000). All these definitions are available for easy copying and pasting from http://pastebin.com/mNA9TNTm.
Generally, memoization is your friend in this type of computation. Might not apply as it depends on the specific arguments in the recursion; but it is a useful approach to explore.

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