I am working in the R programming language.
I am trying to make a plot from n=0 to n = 1000 for the following function (link: https://www.youtube.com/watch?v=iH2kATv49rc&t=7s):

First, I tried to define the P_00(2n) part:
combinatorial_square <- function(n) {
(choose(2*n, n)^2) * ((1/4)^(2*n))
}
Then, I tried to write another function that performs the cumulative sum of the above function:
cumulative_sum <- function(N) {
s <- 0
for (n in 1:N) {
s <- s + (choose(2*n, n)^2) * ((1/4)^(2*n))
}
return(s)
}
Then, I tried to plot it over a range of N's:
N <- 1:250
y <- sapply(N, cumulative_sum)
plot(N, y, type = "l", main = "Plot of cumulative_sum function", xlab = "N", ylab = "cumulative_sum(N)")

My Problem: I can not seem to plot this function for larger values of N (I think this might be because the computer is not able to calculate large combinatorial terms?):
N <- 1:1000
y <- sapply(N, cumulative_sum)
> tail(y)
[1] NaN NaN NaN NaN NaN NaN
Is there something I can do in R to approximate these larger factorials?
Currently, I was thinking of using some mathematical method to approximate the larger factorial terms involved in combinatorial expressions (e.g. https://en.wikipedia.org/wiki/Stirling%27s_approximation) - that is, re-write the cumulative_sum function so that it uses Stirling Approximation for each factorial term.
But is there an easier way to do this?
Thanks!
The trick is to use logarithms. Base R has logarithm versions of the beta, gamma, choose and factorial functions. These versions are prefixed with an l, are numerically stable and can be invaluable when the numbers become very large. The relevant function is lchoose.
First test the functions' results.
combinatorial_square <- function(n) {
(choose(2*n, n)^2) * ((1/4)^(2*n))
}
cumulative_sum <- function(N) {
s <- 0
for (n in 1:N) {
s <- s + (choose(2*n, n)^2) * ((1/4)^(2*n))
}
return(s)
}
lcombinatorial_square <- function(n) {
2*lchoose(2*n, n) + 2*n * log(1/4)
}
N <- 1:250
y1 <- sapply(N, combinatorial_square)
y2 <- sapply(N, lcombinatorial_square)
# all values are equal to floating-point accuracy
mapply(all.equal, log(y1), y2) |> all()
#> [1] TRUE
mapply(all.equal, y1, exp(y2)) |> all()
#> [1] TRUE
# but only 1% are exactly equal
# (note that the vectors log(y1) and y2 have the same attributes
# therefore the two instructions that follow are equivalent)
mapply(identical, y1, exp(y2)) |> mean()
#> [1] 0.012
mapply(`==`, y1, exp(y2)) |> mean()
#> [1] 0.012
# (note also that if the test is on log(y1) 3% are exactly equal)
mapply(identical, log(y1), y2) |> mean()
#> [1] 0.028
mapply(`==`, log(y1), y2) |> mean()
#> [1] 0.028
# now test with larger numbers
N <- 1:1000
y2 <- sapply(N, lcombinatorial_square)
y2 |> exp() |> is.finite() |> all()
#> [1] TRUE
y2 |> exp() |> max()
#> [1] 0.25
y2 |> exp() |> sum()
#> [1] 2.265321
Created on 2023-11-20 with reprex v2.0.2
Finally, compute the sums with bigger N and plot the summation.
lcombinatorial_square <- function(n) 2*lchoose(2*n, n) + 2*n * log(1/4)
# cumulative_sum_2a <- function(N) {
# s <- 0
# for (n in seq.int(N)) {
# e <- exp(lcombinatorial_square(n))
# s <- s + e
# }
# s
# }
cumulative_sum_2 <- function(N) {
N |>
seq.int() |>
sapply(lcombinatorial_square) |>
exp() |>
sum()
}
N <- 1:1000
y <- sapply(N, cumulative_sum_2)
plot(N, y, type = "l", main = "Plot of cumulative_sum function",
xlab = "N", ylab = "cumulative_sum(N)")

Created on 2023-11-20 with reprex v2.0.2
You got NAN since choose(2*n, n)^2 explodes for large n, but you should have way to circumvent that issue for big numbers.
You can rearrange the terms in the math expression and make sure that each item is less than 1 and decay in the power law (in your case, it is power of 2), and then you will make it "converge" (not the same concept of "convergence" in series sum of the math domain), for example
f <- Vectorize(function(n) {
v <- seq_len(n)
prod((n + v) / (4 * v))^2
})
and then run (up to 10000 for exmaple)
N <- 1:10000
P <- cumsum(f(N))
plot(N, P, type = "l", main = "Plot of cumulative_sum function", xlab = "N", ylab = "cumulative_sum(N)")
and you will obtain

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With