====== Estimação de pi por simulação ======
==== Simulação em quadrado/circulo ====
==== Agulha de Buffon ====
Diferentes abordagens para a estimativa de π através do experimento da agulha de Buffon, realizadas pelos participantes do curso:
=== Éder ===
buffon.eder <- function(n,l=1,a=1){
if(a l\n')}
if(a>=l){
theta <- runif(n,0,pi)
dist <- runif(n,0,a/2)
inter <- sum(dist <= l/2*sin(theta))
phi_est <- round((n/inter)*(2*l/a),12)
cat('Número Simulação',n,'phi_estimado', phi_est,'Erro',
round(pi-phi_est,12), '\n')
return(c(n,phi_est))
}
}
## Teste de funcionamento
buffon.eder(1000)
## Abordagem final
n <- seq(10000,1000000,by=20000)
res <- matrix(NA,ncol=2,nrow=length(n))
con <- 1
system.time(
for (i in n){
res[con,] <- buffon.eder(i)
con <- con+1
}
)
## Plot
plot(res,type='l',ylab=expression(pi),xlab='Simulações')
abline(h=pi,col='red')
=== Walmes ===
buffon.walmes <- function(simul, d=1, l=1, n=10){
## argumentos da função
## simul é o escalar inteiro número de agulhas lançadas
## d é o escalar espaçamento entre as linhas da grade
## l é o escalar comprimento da agulha
## n é o escalar inteiro número de linhas na grade
malha <- seq(0, 10, by=d)
linhas <- malha[-c(1,length(malha))]
range <- range(malha)+c(1,-1)*d
x <- matrix(runif(2*simul, range[1], range[2]), ncol=2)
a <- runif(simul, 0, 2*pi)
y <- x+matrix(c(l*sin(a), l*cos(a)), ncol=2)
R <- sapply(seq_len(simul),
function(i){
sum(linhas>=x[i,1] & linhas<=y[i,1])>0
})
rho <- l/d
## função retorna um a lista com
## R vetor de TRUE/FALSE se a linha toca ou não a grade
## o valor de rho
## a matrix X com as coordenadas onde a agulha toca
return(list(R=R, rho=rho, X=cbind(cabeca=x,ponta=y)))
}
## Teste de funcionamento
buffon.walmes(1000)
## Abordagem final
bf <- buffon.walmes(1000)
pi0 <- bf$rho/(sum(bf$R)/length(bf$R)); pi0
## Plot
plot(bf$rho/(cumsum(bf$R)/c(1:length(bf$R))), type="l")
abline(h=pi)
=== Fernando ===
buffon.fernando <- function(n, a = 1, l = 1){
buffon.calc <- function(n, ...){
D.random <- runif(n, 0, a/2)
theta.random <- runif(n, 0, pi)
d <- (l/2) * sin(theta.random)
H <- numeric(n)
H[D.random <= d] <- 1
h <- sum(H)
pi.est <- (2*l*n)/(a*h)
return(pi.est)
}
pi.res <- sapply(n, buffon.calc)
saida <- data.frame(n = n,
pi.est = pi.res,
abs.error = abs(pi.res - pi))
class(saida) <- c("buffon", "data.frame")
return(saida)
}
## Teste
system.time(
testef <- buffon.fernando(1:1000)
)
## Abordagem final
# ja finalizada
source("plot.buffon.R")
## Plot
plot(buffon.fernando(1:1e4))
A função ''plot.buffon()'' está aqui:
plot.buffon <- function(x, xlab = "Numero de jogadas da agulha",
ylab = expression(paste("Estimativa de ", pi)),
...){
plot(x$n, x$pi.est, type = "l", xlab = xlab, ylab = ylab,
main = "Experimento de Buffon", ...)
abline(h = pi, col = "lightgrey")
}
=== Stuart ===
Para comparação, o código feito pelos autores da apostila (e também disponível no pacote CIM) está abaixo:
require(CIM)
buf(100)
## edita a funcao para tirar o plot
buffon.stuart <- function(n){
ttt <- NULL
ttt[1] <- 0
x <- runif(n)
th <- runif(n, 0, pi)
st <- sin(th)
for (i in 1:n) {
if (st[i] > x[i])
ttt[i + 1] <- ttt[i] + 1
else ttt[i + 1] <- ttt[i]
}
#ttt
if (ttt[n + 1] > 0)
2 * (0:n)[ttt > 0]/ttt[ttt > 0]
else print("no successes")
}
## Teste
buffon.stuart(1000)
## Plot
plot(buffon.stuart(1000), type = "l")
abline(h = pi)
==== Comparação dos algorítmos ====
=== Executando e armazenando tempos e resultados ===
## Define um n comum
n1 <- 1:1e+4
n2 <- seq(0, 1e+6, 1000)[-1]
##----------------------------------------------------------------------
## Tempo Eder com n1
res.eder.n1 <- matrix(NA, ncol=2, nrow=length(n1))
con <- 1
eder.n1 <- system.time(
for (i in n1){
res.eder.n1[con,] <- buffon.eder(i)
con <- con+1
}
)
## Tempo Walmes com n1
walmes.n1 <- system.time(
bf <- buffon.walmes(max(n1))
)
res.walmes.n1 <- bf$rho/(cumsum(bf$R)/c(1:length(bf$R)))
## Tempo Fernando com n1
fernando.n1 <- system.time(
res.fernando.n1 <- buffon.fernando(n1)
)
## Tempo Stuart com n1
stuart.n1 <- system.time(
res.stuart.n1 <- buffon.stuart(max(n1))
)
##----------------------------------------------------------------------
## Tempo Eder com n2
res.eder.n2 <- matrix(NA, ncol=2, nrow=length(n2))
con <- 1
eder.n2 <- system.time(
for (i in n2){
res.eder.n2[con,] <- buffon.eder(i)
con <- con+1
}
)
## Tempo Walmes com n2
walmes.n2 <- system.time(
bf <- buffon.walmes(max(n2))
)
res.walmes.n2 <- bf$rho/(cumsum(bf$R)/c(1:length(bf$R)))
## Tempo Fernando com n2
fernando.n2 <- system.time(
res.fernando.n2 <- buffon.fernando(n2)
)
## Tempo Stuart com n2
stuart.n2 <- system.time(
res.stuart.n2 <- buffon.stuart(max(n2))
)
#### Parei em 3261 seg. ~ 55 min.
=== Comparando performances ===
## Usando n1 = 1:1e4
##----------------------------------------------------------------------
## Comparacao de tempos de execucao
tempo.n1 <- c(eder.n1[3], walmes.n1[3], fernando.n1[3], stuart.n1[3])
names(tempo.n1) <- c("eder", "walmes", "fernando", "stuart")
tempo.n1 <- sort(tempo.n1)
## barchart
require(lattice)
barchart(tempo.n1, xlab = "Tempo (s)",
panel = function(...){
panel.barchart(...)
panel.text(x = tempo.n1, y = 1:4,
labels = do.call(as.character,
list(round(tempo.n1, 2))), pos = 2)
})
## Cria um data.frame com todos os resultados
res.n1 <- data.frame(n = n1,
eder = res.eder.n1[,2],
walmes = res.walmes.n1,
fernando = res.fernando.n1$pi.est,
stuart = res.stuart.n1)
## modifica o data.frame para o lattice
require(reshape)
res.n1 <- melt(res.n1, id = 1)
## Comparacao grafica
xyplot(value ~ n | variable, data = res.n1, type = "l", as.table = TRUE,
xlab = "Número de jogadas da agulha",
ylab = expression(paste("Estimativa de ", pi)),
panel = function(...){
panel.xyplot(...)
panel.abline(h = pi, lty = 2)
}, scales = list(relation = "free"))
## Usando n2 = seq(0, 1e+6, 1000)[-1]
##----------------------------------------------------------------------
## Comparacao de tempos de execucao
tempo.n2 <- c(eder.n2[3], walmes.n2[3], fernando.n2[3])
names(tempo.n2) <- c("eder", "walmes", "fernando")
tempo.n2 <- sort(tempo.n2)
## barchart
barchart(tempo.n2, xlab = "Tempo (s)",
panel = function(...){
panel.barchart(...)
panel.text(x = tempo.n2, y = 1:4,
labels = do.call(as.character,
list(round(tempo.n2, 2))), pos = 2)
})
## Cria um data.frame com todos os resultados
## Stuart nao entra pq nao terminou a execução
## Walmes fica de fora pq vai ate 1e6
res.n2 <- data.frame(n = n2,
eder = res.eder.n2[,2],
fernando = res.fernando.n2$pi.est)
## modifica o data.frame para o lattice
res.n2 <- melt(res.n2, id = 1)
## Comparacao grafica
xyplot(value ~ n | variable, data = res.n2, type = "l", as.table = TRUE,
xlab = "Número de jogadas da agulha",
ylab = expression(paste("Estimativa de ", pi)),
panel = function(...){
panel.xyplot(...)
panel.abline(h = pi, lty = 2)
})#, scales = list(relation = "free"))
## Plot separado do Walmes
xyplot(res.walmes.n2 ~ 1:max(n2), type = "l",
xlab = "Número de jogadas da agulha",
ylab = expression(paste("Estimativa de ", pi)),
panel = function(...){
panel.xyplot(...)
panel.abline(h = pi, lty = 2)
})