If $x_i\sim\text{Laplace(0, b)}$ and
$$y=\sum_{i=1}^nx_i$$
then $y$ is a mixture of double (two-sided) gamma distributions:
$$f(y)=\sum_{i=1}^nw_i\frac{b^i|y|^{i-1}}{2\Gamma(i)}e^{-b|y|}$$
with
$$w_{i\in2...n}(n)=\binom{2n-i-1}{n-i}2^{i-2n+1}$$
and $w_1=w_2$.
I'm not up for showing the derivation, but it could be done by partial fraction expansion of the characteristic function of the sum of $n$ iid Laplace random variates.
A quick check in R:
set.seed(1044174532)
fcoeff <- function(n) {
# function to get coefficients of a gamma mixture with the same distribution
# as the sum of n Laplace(0, 1) random variates
C <- numeric(n)
k <- (2*n - 3):(n - 1)
# C[2:n] <- choose(k, (n - 2):0)/2^k
C[2:n] <- exp(lgamma(k + 1) - lgamma((n - 1):1) - lgamma(n) - k*log(2))
C[1] <- C[2]
C
}
n <- 5L # number of Laplace r.v. to sum
s <- 1e5L # number of samples
# sum of iid Laplace(0, 1) r.v. as a gamma mixture
x <- rgamma(s, sample(n, s, 1, fcoeff(n)))*sample(c(-1, 1), s, 1)
# sum of iid Laplace(0, 1) r.v. directly
y <- rowSums(matrix(rexp(s*n)*sample(c(-1, 1), s*n, 1), s, n))
ks.test(x, y)
#>
#> Asymptotic two-sample Kolmogorov-Smirnov test
#>
#> data: x and y
#> D = 0.00194, p-value = 0.9918
#> alternative hypothesis: two-sided
plot(ecdf(x), col = "blue")
plot(ecdf(y), col = "orange", add = TRUE)
From this, get the CDF and quantile functions for the distribution of $y$:
pnlaplace <- function(q, b, n) {
0.5 + sign(q)*sum(pgamma(abs(q), 1:n, b)*fcoeff(n))/2
}
qnlaplace <- function(p, b, n) {
if (p < 0.5) {
uniroot(\(a) pnlaplace(a, b, n) - p, c(n*log((1 - p)/2), 0))$root
} else {
uniroot(\(a) pnlaplace(a, b, n) - p, c(0, -n*log((1 - p)/2)))$root
}
}
To determine the minimum value of $a$ for $n=2$ (two reports), first specify $b$ and the desired confidence and power for the hypothesis test:
b <- 1
n <- 2L
alpha <- 0.05 # type I error
beta <- 0.1 # type II error
Next, find $x_0$ (the value of $s_0$ that will give the desired confidence level) and $x_1$ (the value of $s_1 - x_0$ that will give the desired power). $a$ is the average of $x_0$ and $x_1$:
# value of s0 to reject null hypothesis with 1 - alpha confidence
(x0 <- qnlaplace(1 - alpha, b, n))
#> [1] 3.27181
# value of s1 - x0 needed for a test with 1 - beta power
(x1 <- qnlaplace(1 - beta, b, n))
#> [1] 2.397277
(a <- (x0 + x1)/n)
#> [1] 2.834543
Check the type I and type II errors with a simulation:
mean(rowSums(matrix(rexp(1e6*n)*sample(c(-1, 1), 1e6*n, 1), 1e6, n)) > x0)
#> [1] 0.050136
mean(rowSums(matrix(rexp(1e6*n)*sample(c(-1, 1), 1e6*n, 1), 1e6, n)) + n*a < x0)
#> [1] 0.100319
Similarly determine the minimum value of $n$ to achieve the desired confidence and power given $a$:
a <- 1
# find the lowest value of n that satisfies the specified errors (alpha, beta)
# first find the lower and upper bound on n to pass to the solver
n <- 2L
while (1 - pnlaplace(qnlaplace(1 - alpha, b, n) - a*n, b, n) < 1 - beta) n <- n*2L
(n <- ssanv::uniroot.integer(\(n) pnlaplace(qnlaplace(1 - alpha, b, n) - a*n, b, n) - beta, c(n/2L, n), step.power = log2(n) - 2)$root)
#> [1] 17
Again, check the errors with a quick simulation:
# value of s0 to reject null hypothesis with 1 - alpha confidence
(x0 <- qnlaplace(1 - alpha, b, n))
#> [1] 9.574182
mean(rowSums(matrix(rexp(1e6*n)*sample(c(-1, 1), 1e6*n, 1), 1e6, n)) > x0)
#> [1] 0.050118
mean(rowSums(matrix(rexp(1e6*n)*sample(c(-1, 1), 1e6*n, 1), 1e6, n)) + n*a < x0)
#> [1] 0.099337
These functions are capable of working with large $n$, but because of the use of nested solvers, the process of finding the minimum $n$ becomes noticeably slower as $n$ gets large:
a <- 0.01
system.time({
n <- 2L
while (1 - pnlaplace(qnlaplace(1 - alpha, b, n) - a*n, b, n) < 1 - beta) n <- n*2L
n <- ssanv::uniroot.integer(\(n) pnlaplace(qnlaplace(1 - alpha, b, n) - a*n, b, n) - beta, c(n/2L, n), step.power = log2(n) - 2)$root
})
#> user system elapsed
#> 32.29 0.47 32.80
n
#> [1] 171277