Last active
January 13, 2016 08:40
-
-
Save chainsawriot/7a8eff5f03ddccaa9051 to your computer and use it in GitHub Desktop.
how to use the R debugger
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
## prereq: | |
## 1) How to define a function | |
## Security level | |
## Warning: Does not stop execution | |
## Error: Stop execution | |
## example of warning | |
log(-1) | |
## example of error | |
log("ABC") | |
## example of non-warning and non-error, but potentially problematic | |
log(NA) | |
mean(c(1,2,43,5,6,7,NA)) | |
10/0 | |
### Real life bugs are not only about error / warning. | |
## how to throw an error / warning | |
stop(2 > 3) | |
stopifnot(3==4) | |
warning("You should go to the Hong Kong Python usergroup!") | |
suppressWarnings(log(-1)) | |
## let's define a simple function | |
simpleFx <- function(x) { | |
if (x > 0) { | |
return("Positive") | |
} else { | |
return("Negative") | |
} | |
} | |
# let's try | |
simpleFx(10) | |
simpleFx(-10) | |
simpleFx(50/10) | |
simpleFx(pi) | |
simpleFx(10/0) | |
# let's try some corner cases | |
simpleFx(0) | |
simpleFx(NA) | |
simpleFx(log(-1)) | |
simpleFx(NaN) | |
NaN > 0 | |
# let try something even crazy | |
# press C-c C-c to stop | |
# finding square root using bisection method | |
mySqrt <- function(x, epsilon = 0.001) { | |
lowest <- 0 | |
highest <- x | |
guess <- mean(c(lowest, highest)) | |
while(abs((guess * guess) - x) > epsilon) { | |
if ((guess * guess) > x) { | |
highest <- guess | |
} else { | |
lowest <- guess | |
} | |
} | |
return(guess) | |
} | |
### infinite loop! Why? | |
### oldskool way: adding print statement | |
mySqrtdebug <- function(x, epsilon = 0.001) { | |
lowest <- 0 | |
highest <- x | |
guess <- mean(c(lowest, highest)) | |
while(abs((guess * guess) - x) > epsilon) { | |
cat(paste0("guess: ", str(guess))) | |
cat(paste0("Highest: ", str(highest))) | |
cat(paste0("Lowest: ", str(lowest))) | |
cat((paste0("Diff: ", str(abs((guess*guess) - x))))) | |
if ((guess * guess) > x) { | |
highest <- guess | |
} else { | |
lowest <- guess | |
} | |
} | |
return(guess) | |
} | |
### guess is not updated! | |
mySqrtdebug <- function(x, epsilon = 0.001) { | |
lowest <- 0 | |
highest <- x | |
guess <- mean(c(lowest, highest)) | |
while(abs((guess * guess) - x) > epsilon) { | |
print(guess) | |
# cat(paste0("Highest: ", str(highest))) | |
# cat(paste0("Lowest: ", str(lowest))) | |
# cat((paste0("Diff: ", str(abs((guess*guess) - x))))) | |
if ((guess * guess) > x) { | |
highest <- guess | |
} else { | |
lowest <- guess | |
} | |
guess <- mean(c(lowest, highest)) | |
} | |
return(guess) | |
} | |
# how to detect the problem without inserting print / cat statement | |
debug(mySqrt) | |
mySqrt(5) # c (or just enter), Q, help | print out the value of guess after each iteration | ls() | |
undebug(mySqrt) | |
mySqrt(5) | |
mySqrt <- function(x, epsilon = 0.001) { | |
lowest <- 0 | |
highest <- x | |
guess <- mean(c(lowest, highest)) | |
while(abs((guess * guess) - x) > epsilon) { | |
if ((guess * guess) > x) { | |
highest <- guess | |
} else { | |
lowest <- guess | |
} | |
guess <- mean(c(lowest, highest)) | |
} | |
return(guess) | |
} | |
debug(mySqrt) | |
mySqrt(5) | |
undebug(mySqrt) | |
mySqrt(6) | |
mySqrt(100) | |
mySqrt(25.8) * mySqrt(25.8) | |
### corner cases | |
mySqrt(0.000001) # Accuracy problem | |
mySqrt(-1) # also, it should return a complex number | |
mySqrt(99999999) | |
mySqrt(Inf) #die | |
mySqrt(NaN) #die too | |
mySqrt(NA) #die three | |
debug(mySqrt) | |
mySqrt(-1) | |
mySqrt(0.000001) # Accuracy problem | |
# defensive programming | |
mySqrt <- function(x, epsilon = 0.001) { | |
if (!(is.numeric(x) & !is.infinite(x) & x > 0)) stop("Invalid input") | |
if (x < epsilon) stop("x is smaller than tolerance.") | |
lowest <- 0 | |
highest <- x | |
guess <- mean(c(lowest, highest)) | |
while(abs((guess * guess) - x) > epsilon) { | |
if ((guess * guess) > x) { | |
highest <- guess | |
} else { | |
lowest <- guess | |
} | |
guess <- mean(c(lowest, highest)) | |
} | |
return(guess) | |
} | |
debug(mySqrt) | |
mySqrt(Inf) | |
mySqrt(NaN) | |
mySqrt(NA) | |
mySqrt(-1) | |
mySqrt(0.000001) | |
## Example from the SICP | |
## Newton-Rhapson method | |
sqrtNewt <- function(x, epsilon=0.0001) { | |
if (!(is.numeric(x) & !is.infinite(x) & x > 0)) stop("Invalid input") | |
if (x < epsilon) stop("x is smaller than tolerance.") | |
guess <- max(c(x,1)) / 2 | |
delta <- abs(guess^2 - x) | |
while (delta > epsilon) { | |
guess <- mean(c(guess, (x/guess))) | |
delta <- abs(guess^2 - x) | |
} | |
return(guess) | |
} | |
sqrtNewt(Inf) | |
sqrtNewt(NaN) | |
sqrtNewt(NA) | |
sqrtNewt(-1) | |
sqrtNewt(0.000001) | |
sqrtNewt(100) | |
sqrtNewt(500) | |
newton <- function(x, f, epsilon=0.0001) { | |
if (!(is.numeric(x) & !is.infinite(x) & x > 0)) stop("Invalid input") | |
if (x < epsilon) stop("x is smaller than tolerance.") | |
guess <- max(c(x,1)) / 2 | |
delta <- abs(f(guess) - x) | |
while (delta > epsilon) { | |
guess <- mean(c(guess, (x/guess))) | |
delta <- abs(f(guess) - x) | |
} | |
return(guess) | |
} | |
sq <- function(x) { | |
return(x^2) | |
} | |
newton(100, sq) | |
# or even, aka lambda function | |
newton(100, function(x) x^2) | |
newton(100, function(x) x^3) | |
debug(newton) | |
newton(100, function(x) x^3) | |
# the theory is wrong, because the improvement function depends on f(x) | |
# i.e. Universial guess <- mean(c(guess, (x/guess))) as guess improvement is wrong | |
newton <- function(x, f, imp, epsilon=0.0001) { | |
if (!(is.numeric(x) & !is.infinite(x) & x > 0)) stop("Invalid input") | |
if (x < epsilon) stop("x is smaller than tolerance.") | |
guess <- max(c(x,1)) / 2 | |
delta <- abs(f(guess) - x) | |
while (delta > epsilon) { | |
guess <- imp(x, guess) | |
delta <- abs(f(guess) - x) | |
} | |
return(guess) | |
} | |
newton(100, function(x) x^2, function(x, y) { mean(c(y, (x/y))) }) | |
newton(90, function(x) x^3, function(x, y) { ((x/(y^2)) + (2 * y)) / 3 }) | |
bisec <- function(x, f, epsilon = 0.001) { | |
if (!(is.numeric(x) & !is.infinite(x) & x > 0)) stop("Invalid input") | |
if (x < epsilon) stop("x is smaller than tolerance.") | |
lowest <- 0 | |
highest <- x | |
guess <- mean(c(lowest, highest)) | |
while(abs(f(guess) - x) > epsilon) { | |
if (f(guess) > x) { | |
highest <- guess | |
} else { | |
lowest <- guess | |
} | |
guess <- mean(c(lowest, highest)) | |
} | |
return(guess) | |
} | |
bisec(100, function(x) x^2) | |
bisec(1000, function(x) x^3) | |
bisec(10000, function(x) x^4) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment