Can't integrate the subtraction of two Gaussian CDFs [Wolfram Mathematica] - plot

I have a function which is a product composed by three (k) factors . Each factor is a subtraction of two Gaussian CDF with random variables R and L. These random variables are defined according to 4 parameters.
The code below shows how I plot the main function (according to two independent variables d and e) and how the random variables are calculated
sigma = 1;
k = 3;
priors = {};
AppendTo[priors, 1/k + e];
Do[AppendTo[priors, 1/k - e/(k - 1)], {c, 2, k}];
L[priors_, sigma_, d_, i_] := Do[
maxVal = -Infinity;
Do[
val = (2*sigma^2*Log[priors[[i]]/priors[[j]]] + d^2 (j^2 - i^2 + 2 (i - j)))/(2 (j - i) d);
If[val > maxVal, maxVal = val, Null];
, {j, 1, i - 1}];
Return[maxVal];
, {1}];
R[priors_, sigma_, d_, i_] := Do[
minVal = Infinity;
Do[
val = (2*sigma^2*Log[priors[[j]]/priors[[i]]] + d^2 (i^2 - j^2 + 2 (j - i)))/(2 (i - j) d);
If[val < minVal, minVal = val, Null];
, {j, i + 1, k}];
Return[minVal];
, {1}];
Print[
Plot3D[
Product[
If[R[priors, sigma, d, c] < L[priors, sigma, d, c], 0,
(CDF[NormalDistribution[(c - 1) d, sigma], R[priors, sigma, d, c]] -
CDF[NormalDistribution[(c - 1) d, sigma], L[priors, sigma, d, c]])]
, {c, 1, k}]
, {d, 0.01, 5}
, {e, -1/k, 1 - 1/k}, PlotRange -> {All, All, All}, AxesLabel -> Automatic]];
Now, I want to integrate the function over d (in the same region as the Plot3D, d=0.01-5) and to plot the results according to just the independent variable e.
Below is the code I've used.
Print[
Plot[
Integrate[
Product[
If[R[priors, sigma, d, c] < L[priors, sigma, d, c], 0,
(CDF[NormalDistribution[(c - 1) d, sigma], R[priors, sigma, d, c]] -
CDF[NormalDistribution[(c - 1) d, sigma], L[priors, sigma, d, c]])]
, {c, 1, k}]
, {d, 0.01, 5}]
, {e, -1/k, 1 - 1/k}, PlotRange -> {All, All}, AxesLabel -> Automatic]];
However, the resulting plot is not what I expect. It's constant and in the 3D plot it can be seen that this cannot happen. Does anyone know what is happening and what to do to obtain the real integration of the function? Thanks in advance.

When you compute val inside the functions L and R the result is symbolic (because e is not defined ). The logical val < minVal is thus indeterminate, and as a result minVal is never set (so that L and R return infinity every time )
(cleaned up a couple of other things as well.. )
sigma = 1;
k = 3;
priors = Join[ {1/k + e} , Table[1/k - e/(k - 1) , {c, 2, k} ] ];
L[priors0_, sigma_, d_, i_, e0_] := Module[{priors, maxVal, val, e},
Do[maxVal = -Infinity;
priors = priors0 /. e -> e0 ;
Do[val = (2*sigma^2*Log[priors[[i]]/priors[[j]]] +
d^2 (j^2 - i^2 + 2 (i - j)))/(2 (j - i) d);
If[val > maxVal, maxVal = val];, {j, 1, i - 1}];, {1}]; maxVal];
R[priors0_, sigma_, d_, i_, e0_] := Module[{priors, maxVal, val, e},
priors = priors0 /. e -> e0;
Min[Table[(2*sigma^2*Log[priors[[j]]/priors[[i]]] +
d^2 (i^2 - j^2 + 2 (j - i)))/(2 (i - j) d), {j, i + 1, k}]]];
g[d_?NumericQ, c_, e_] :=
Product[If[R[priors, sigma, d, c, e] < L[priors, sigma, d, c, e],
0,
(CDF[NormalDistribution[(c - 1) d, sigma], R[priors, sigma, d, c, e]] -
CDF[NormalDistribution[(c - 1) d, sigma], L[priors, sigma, d, c, e]])],
{c, 1, k}];
Plot[NIntegrate[g[d, c, e], {d, 0.01, 5}], {e, -1/k, 1 - 1/k},
PlotRange -> {All, All}, AxesLabel -> Automatic]

Related

Runge Kutta 4 doesn't give the desired result

I am solving a system of differential equations with the RK4 method but the outcome performs bad towards the end iteration. The problem seems to be with the eq11 of my function l(lna,x,y,m,xi,yi) since the term (np.float64(1)-np.power(x,2)-np.power(y,2))->0 and np.exp(3*(lna-lnai))->\infty towards the end state.
The code I wrote is,
import numpy as np
import matplotlib.pyplot as plt
q = 1
def l(lna,x,y,m,xi,yi):
eq11 = (np.float64(1)-np.power(x,2)-np.power(y,2))*np.exp(3*(lna-lnai))
denom= (yi**2)*eq11
num = (y**2)*(1-xi**2-yi**2)
eq1 = np.divide(num,denom)
eq2 = (eq1)**(1/n)
return n * (m**(-1)) * eq2
def f1 (x,y,l):
return -3*x + l*np.sqrt(3/2)* y**2+ 3/2 *x*(2*(x**2)+q*(1-x**2-y**2))
def f2 (x,y,l):
return -l*np.sqrt(3/2) *y*x + 3/2 *y*(2*x**2+q*(1-x**2-y**2))
def R_K_4(xi,yi,m):
N = int(round((lnaf-lnai)/dlna))
lna = np.linspace(lnai, lnaf, N+1)
x = np.empty(N+1)
y = np.empty(N+1)
x[0],y[0] = xi,yi
for i in range(0,N):
kx1 = dlna * f1( x[i], y[i], l( lna[i], x[i], y[i], m, xi, yi) )
ky1 = dlna * f2( x[i], y[i], l( lna[i], x[i], y[i], m, xi, yi) )
kx2 = dlna * f1( x[i]+kx1/2, y[i]+ky1/2, l( lna[i]+dlna/2, x[i]+kx1/2, y[i]+ky1/2, m, xi, yi) )
ky2 = dlna * f2( x[i]+kx1/2, y[i]+ky1/2, l( lna[i]+dlna/2, x[i]+kx1/2, y[i]+ky1/2, m, xi, yi) )
kx3 = dlna * f1( x[i]+kx2/2, y[i]+ky2/2, l( lna[i]+dlna/2, x[i]+kx2/2, y[i]+ky2/2, m, xi, yi) )
ky3 = dlna * f2( x[i]+kx2/2, y[i]+ky2/2, l( lna[i]+dlna/2, x[i]+kx2/2, y[i]+ky2/2, m, xi, yi) )
kx4 = dlna * f1( x[i]+kx3, y[i]+ky3, l( lna[i]+dlna, x[i]+kx3, y[i]+ky3, m, xi, yi) )
ky4 = dlna * f2( x[i]+kx3, y[i]+ky3, l( lna[i]+dlna, x[i]+kx3, y[i]+ky3, m, xi, yi) )
x[i+1] = x[i] +1/6*(kx1 + 2*kx2 + 2*kx3 + kx4)
y[i+1] = y[i] +1/6*(ky1 + 2*ky2 + 2*ky3 + ky4)
return x,y,lna
#Parameters and step size:
n = 0.1
dlna = 1e-3
# Initial and final times:
lnai, lnaf = -2, 17
# Calling the funtion RK4:
x1, y1, lna = R_K_4(np.sqrt(n/(n+4))*10**(-5), 10**(-5), 0.1)
w1 = np.divide((x1**2-y1**2),(x1**2+y1**2))
plt.plot(lna, w1, label='w1')
plt.xlabel('x')
plt.ylabel('y')
plt.grid()
plt.legend()
plt.show()
If I run it, I will get the following result and there is a bump towards y =-1 :

Probability density function with triangular distribution of parameters

How do you compute this probability density function, with a triangular distribution of parameters (a,b,c)?
f(x)= 0 , x<a
2(x-a)/((b-a)(c-a)) , a <= x <= c
2(b-x)/((b-a)(b-c)) , c < x <=b
0 , x> b
Expanding on #StéphaneLaurent‘s comments, you can define a piecewise function using a series of ifelse() calls (or dplyr::case_when()).
f <- function(x, A, B, C) {
out <- ifelse(
x < A | B < x,
0,
ifelse(
A <= x & x <= C,
(2*(x-A))/((B-A)*(C-A)),
ifelse(
C < x & x <= B,
(2*(B-x))/((B-A)*(B-C)),
NA_real_
)))
if (any((is.na(out) | is.nan(out)) & (!is.na(x) & !is.nan(x)))) {
warning("f(x) undefined for some input values")
}
out
}
Taking it for a spin:
library(ggplot2)
dat <- expand.grid(
x = seq(-1.5, 1.5, by = 0.1),
A = -1:1,
B = -1:1,
C = -1:1
)
dat$y <- with(dat, f(x, A, B, C))
# Warning message:
# In f(x, A, B, C) : f(x) undefined for some input values
ggplot(dat, aes(x, y)) +
geom_line(aes(color = factor(C))) +
facet_grid(B ~ A, labeller = label_both)
Here is an option for a density function and a random function.
dtri <- function(x, A, B, C) {
n <- length(x)
i <- 1:n
if (length(A) == 1) A <- rep(A, n)
if (length(B) == 1) B <- rep(B, n)
if (length(C) == 1) C <- rep(C, n)
abc <- Rfast::rowSort(matrix(c(A, B, C), n, 3))
bln <- x < abc[,2]
p <- 2*abs(x - abc[i + 2*n*!bln])/(abc[,3] - abc[,1])/(abc[i + n*(2 - bln)] - abc[i + n*(1 - bln)])
p[x < abc[,1] | x > abc[,3]] <- 0
p
}
rtri <- function(n, a, b, c) {
if (a > b) {a <- (b - a) + (b <- a)}
if (b > c) {c <- (b - c) + (b <- c)}
fb <- (b - a)/(c - a)
U <- runif(n)
blna <- U < fb
r <-numeric(n)
r[blna] <- a + sqrt(U[blna]*(c - a)*(b - a))
r[!blna] <- c - sqrt((1 - U[!blna])*(c - a)*(c - b))
r
}
Using R's vectorized cabilities:
my_fun <- function(x, a, b, c) {
i1 <- x >= a & x <= c
i2 <- x > c & x <= b
f <- rep(NA, length(x))
f[x < a | x > b] <- 0
f[i1] <- 2 * (x[i1] - a) / ((b - a) * (c - a))
f[i2] <- 2 * (b - x[i2]) / ((b - a) * (b - c))
return(f)
}
Test:
set.seed(123)
x <- sort(rnorm(1000, 0, 5))
a <- runif(1, -10, -2)
c <- runif(1, -2, 2)
b <- runif(1, 2, 10)
f <- my_fun(x, a, b, c)
plot(x, f, type="l")

MethodError: MethodError: objects of type Vector{Float64} are not callable

mutable struct ConjugateGradientDescent <: DescentMethod
d
g
end
function bracket_minimum(f, x=0; s=1e-2, k=2.0)
a, ya = x, f(x)
b, yb = a + s, f(a + s)
if yb > ya
a, b = b, a
ya, yb = yb, ya
s = -s
end
while true
c, yc = b + s, f(b + s)
if yc > yb
return a < c ? (a, c) : (c, a)
end
a, ya, b, yb = b, yb, c, yc
s *= k
end
end
function line_search(f, x, d)
objective = α -> f(x + α*d)
a, b = bracket_minimum(objective)
α = minimize(objective, a, b)
return x + α*d
end
function init!(M::ConjugateGradientDescent, f, ∇f, x)
M.g = ∇f(x)
M.d = -M.g
return M
end
function step!(M::ConjugateGradientDescent, f, ∇f, x)
d, g = M.d, M.g
g′ = ∇f(x)
β = max(0, dot(g′, g′-g)/(g⋅g))
d′ = -g′ + β*d
x′ = line_search(f, x, d′)
M.d, M.g = d′, g′
return x′
end
function conjugate_gradients(f, g, x0)
xʼ = x0
d = 0.01
n = 10000
CGD = ConjugateGradientDescent(d, g)
init!(CGD, f, g, xʼ)
i = 0
prev = 0
while i <= n
i += 1
xʼ = step!(CGD, f, g, xʼ)
if prev == xʼ
break
else
prev = xʼ
end
end
return xʼ, rosenbrock(xʼ), i
end
x = rand(10)
g(x) = derivative(rosenbrock, x)
x_final, f_final, iter = conjugate_gradients(rosenbrock(x), g, -5.0)
There are multiple lines for this particular Error:
MethodError: MethodError: objects of type Vector{Float64} are not callable
Use square brackets [] for indexing an Array.
In the function line_search, objective = α -> f(x + α*d) shows the error and in the bracket_minimum function, a, ya = x, f(x) b, yb = a + s, f(a + s) shows the error.
Why am I getting this error? I'm confused. Is it because function inside another function i.e. f is a function inside line_search function.

How do I make this simple for loop faster in R?

I have a for loop like this:
len = 10000
alpha_0 = seq(0, 10, length = len)
for (a in 1:len) {
alpha0 = alpha_0[a]
llike[a] <- llikelihood(alpha0, beta, q, d, n)
}
Basically I am just changing values of alpha0 and then inputting that value into a function called llikelihood. The llikelihoodfunction looks like so:
llikelihood = function(alpha0, beta, q, d, n) {
llike = n*(lgamma(alpha0) - sum_a(alpha0, beta, d) + sum_b (alpha0, beta, q, d, n))
return(llike)
}
sum_a = function(alpha0, beta, d) {
sum_a = 0
for (i in 1:d) {
sum_a = sum_a + lgamma(alpha0*beta[i])
}
return(sum_a)
}
# returns the output to summation from 1 to k of (alpha0*beta[i] - 1)*log(x_i)
sum_b = function(alpha0, beta, q, d, n) {
# replace zero values
sum_b = 0
# find the log q
logq = log(q)
qlog = apply(logq, 1, sum)
# for each column, sum up the draws
for (i in 1:d) {
sum_b = sum_b + (alpha0*beta[i] - 1)*1/n*qlog[i]
}
return(sum_b)
}
Is there any way I can make the whole process more efficient? Any help is appreciated!

summation issue in mathematica

I'm puzzled by this behavior of mathematica. The two following expressions should return the same result:
Simplify[(1 - w)^2 Sum[w^(k+kp) Sum[If[l == lp, 1, 0], {l, 0, k}, {lp, 0, kp}],
{k,0, \[Infinity]}, {kp, 0, \[Infinity]}]]
returns:
(-1 - w + w^3)/(-1 + w^2)
whereas the strictly equivalent:
Simplify[(1 - w)^2 Sum[w^(k+kp) Min[k, kp],{k,0,\[Infinity]},{kp,0,\[Infinity]}]
+ (1 - w)^2 Sum[w^(k+kp) ,{k,0,\[Infinity]},{kp,0,\[Infinity]}]]
returns:
1/(1 - w^2)
Not an answer, but if you use
$$\sum_{k=0}^{\infty} \sum_{l=0}^{k} = \sum_{l=0}^{\infty} \sum_{k=l}^{\infty}$$
then :
sum1 = Simplify[(1 - w)^2
Sum[w^(k + kp) Sum[KroneckerDelta[l, lp] , {l, 0, k}, {lp, 0, kp}],
{k, 0, Infinity}, {kp, 0, Infinity}]]
(* (-2 + w + w^2 - w^3)/(-1 + w^2) *)
but
sum2 = Simplify[(1 - w)^2
Sum[KroneckerDelta[l, lp]
Sum[w^(k + kp), {k, l, Infinity}, {kp, lp, Infinity}] ,
{l, 0, Infinity}, {lp, 0, Infinity}]]
(* 1/(1 - w^2) *)

Resources