Skip to content

Commit cf3a939

Browse files
committed
second example ... and then I found it on Wikipedia ... ugh
1 parent 61219e3 commit cf3a939

File tree

1 file changed

+145
-0
lines changed

1 file changed

+145
-0
lines changed

part-advanced-topics/01-simulation.qmd

Lines changed: 145 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -708,6 +708,148 @@ mean(riemann$y)
708708
:::
709709
:::
710710

711+
712+
::: callout-caution
713+
### Example: Integration in 2d
714+
715+
::: panel-tabset
716+
#### Problem
717+
718+
Let's say that you want to find an estimate for $\pi$, and you know that a circle with radius 1 has an area of exactly that. You also know, that all of the points on this circle can be written as $x^2 + y^2 \le 1$.
719+
720+
```{r, echo = F}
721+
#| fig-width: 4
722+
#| fig-height: 4
723+
#| out-width: 50%
724+
#| fig-cap: "The unit circle."
725+
#| fig-alt: "A circle centered in (0,0) with radius 1."
726+
fn <- function(x) sqrt(1-x^2)
727+
ggplot(data.frame(x = seq(-1, 1, length.out = 1000)), aes(x)) +
728+
geom_polygon(aes(y = fn(x)), fill = "grey70", alpha = 0.8) +
729+
geom_polygon(aes(y = -fn(x)), fill = "grey70", alpha = 0.8) +
730+
geom_path(aes(x = sin(theta), y = cos(theta)),
731+
data = data.frame(theta=seq(0,2*pi, by = 0.0001))) + ylab("y")
732+
733+
```
734+
735+
Evaluating the area of the circle mathematically, would need us to either change to polar-coordinates or separate the graph into suitable functions (half-circles), and evaluate the integral between the top and the bottom:
736+
$$
737+
\int_{-1}^1 2 \sqrt{1-x^2} dx
738+
$$
739+
Instead, we note that the circle is encapsulated in a square with side length 2. We can reach all points in that square by using two independent uniform random random variables over the interval $[-1,1]$, i.e. when we generate two random values from U[-1,1], and use one as the $x$ coordinate and one as the $y$ coordinate, we get a point in the square.
740+
If the sum of the squares of the coordinates are less than 1, the point will also fall inside the circle. If not, the point falls in one of the four corners of the square that are outside the circle.
741+
742+
```{r, echo = F}
743+
#| fig-width: 4
744+
#| fig-height: 4
745+
#| out-width: 50%
746+
#| fig-cap: "The unit circle is encapsulated by a square and overlaid with uniform points from U[-1,1] x U[-1,1]. "
747+
#| fig-alt: "A circle centered in (0,0) with radius 1 overlaid with randomly generated points. The points inside the circle are drawn in a different color from the ones outside the circle."
748+
749+
R <- 1000
750+
751+
random <- data.frame(
752+
x = runif(R, min=-1, max=1),
753+
y = runif(R, min=-1, max=1)) %>%
754+
mutate(
755+
in_circle = x^2+y^2<1
756+
)
757+
758+
fn <- function(x) sqrt(1-x^2)
759+
ggplot(data.frame(x = seq(-1, 1, length.out = 1000)), aes(x)) +
760+
geom_path(aes(x = x, y = y), data = data.frame(x = c(-1, 1, 1, -1, -1), y = c( 1, 1, -1, -1, 1))) +
761+
geom_polygon(aes(y = fn(x)), fill = "grey70", alpha = 0.8) +
762+
geom_polygon(aes(y = -fn(x)), fill = "grey70", alpha = 0.8) +
763+
geom_path(aes(x = sin(theta), y = cos(theta)),
764+
data = data.frame(theta=seq(0,2*pi, by = 0.0001))) + ylab("y") +
765+
geom_point(aes(x = x, y = y, colour = in_circle), data = random) +
766+
coord_equal()
767+
768+
```
769+
770+
How do we get to an estimate of $\pi$ from there? We know that the area of the square is simply $2^2 = 4$. The area of the circle is then directly proportional to the rate at which points fall into the circle, ie.
771+
772+
$$
773+
\hat{\pi} = 4 \times \frac{\text{Number of points with } x^2+y^2 \le 1}{\text{Number of points generated}}.
774+
$$
775+
The more points we generate, the closer our estimate will be to the real value.
776+
777+
778+
779+
This problem is an example for Monte-Carlo Integration using an Acceptance-Rejection approach: we can slightly re-write the simulation and think of the generation of a new point in the circle as a two step process, where we first generate a value for $x$ from U[-1,1], and in second step generate a candidate $c$ for $y$ from U[-1, 1], which we will only accept as $y$, if $|c| \le \sqrt{1-x^2}$. Acceptance-Rejection sampling is the basis of a lot of [Markov-Chain Monte-Carlo](https://en.wikipedia.org/wiki/Markov_chain_Monte_Carlo) (MCMC) methods, such as e.g. the [Metropolis-Hastings algorithm](https://en.wikipedia.org/wiki/Metropolis%E2%80%93Hastings_algorithm).
780+
781+
#### R Code
782+
783+
```{r}
784+
set.seed(20491720)
785+
786+
calculate_pi <- function(R) {
787+
x = runif(R, min=-1, max=1)
788+
y = runif(R, min=-1, max=1)
789+
in_circle = x^2+y^2<1
790+
791+
4 * sum(in_circle) / R
792+
}
793+
794+
# Quite a bit of variability with just 100 values
795+
calculate_pi(100)
796+
calculate_pi(100)
797+
calculate_pi(100)
798+
799+
# Better with 10,000
800+
calculate_pi(10000)
801+
calculate_pi(10000)
802+
803+
# Better, but still only good for about 2-3 digits
804+
calculate_pi(1000000)
805+
806+
pi
807+
808+
```
809+
810+
#### Python Code
811+
812+
```{python}
813+
random.seed(20491720)
814+
815+
def calculate_pi(R):
816+
x = np.random.uniform(size = R)
817+
y = np.random.uniform(size = R)
818+
in_circle = x**2+y**2<1
819+
820+
return 4 * sum(in_circle) / R
821+
822+
823+
# Quite a bit of variability with just 100 values
824+
calculate_pi(100)
825+
calculate_pi(100)
826+
calculate_pi(100)
827+
828+
# Better with 10,000
829+
calculate_pi(10000)
830+
calculate_pi(10000)
831+
832+
# Better, but still only good for about 2-3 digits
833+
calculate_pi(1000000)
834+
835+
np.pi
836+
```
837+
838+
#### Numeric integration
839+
840+
```{r}
841+
set.seed(20491720)
842+
fn <- function(x) 2*sqrt(1-x^2)
843+
844+
integrate(fn, lower=-1, upper=1)
845+
846+
pi
847+
```
848+
849+
:::
850+
:::
851+
852+
711853
::: callout-tip
712854
### Try it out
713855

@@ -792,6 +934,9 @@ plt.show()
792934
:::
793935
:::
794936

937+
938+
939+
795940
## Other Resources
796941

797942
- [Simulation](https://bookdown.org/rdpeng/rprogdatascience/simulation.html) (R programming for Data Science chapter)

0 commit comments

Comments
 (0)