I would like to integrate the following function with respect to t, for lower bound = 0 and upper bound = t. I can do that with the following code, but my ultimate goal is to have a value of the integral for each t. Even if I make t a sequence instead of a value, or if I try and use sapply, I still cannot get a value for the integral at each step of t.
#initialize constants
kap=-0.1527778
alph0<-6
b<-0
po<-0.01
t<-100
gp_st<-integrate(function(t) (1-alph0/(alph0+b*t)*(1-po^kap))^(1/kap),lower=0,upper=t)$value
#try alternate where t is now a sequence
t<-seq(1:100)
gp_st2<-function(h) sapply(h,gp_st) #still gives length of 1
Thanks!
Try making gp_st a function of your upper bound, like so:
gp_st <- function(h) {
integrate(function(t) (1-alph0/(alph0+b*t)*(1-po^kap))^(1/kap),lower=0,upper=h)$value
}
Then you can use sapply much as you intended:
t<-seq(1:100)
gp_st2 <- sapply(t, gp_st)
and now gp_st2 is a numeric vector of length 100.
The problem is that you are evaluating the integral in gp_st, and you don't want to do that. You want the following:
ff = function(t) {
(1-alph0/(alph0+b*t)*(1-po^kap))^(1/kap)
}
sapply(1:100, function(ul) {
integrate(ff, lower = 0, upper = ul)$value
})
There are naturally more efficient ways to do this.
Related
I was commanded with the following question. Write a function, named pdice, to simulate a weighted die that has probability of landing on 1:6 of (p1,p2,p3,p4,p5,p6) respectively. You can simulate this by using the parameter prob = p in the sample function, where p is a vector of non-negative numbers of length 6 (at least one needs to be >0). It will use p/sum(p) as the probabilities. This function has arguments p, n. Check ?sample to find out what conditions you need to check for p. Your function should generate an error message if these conditions are not met. Below is my code thus far, which runs, though giving back a warning about a coercing error of double to logical.
pdice <- function(n, p){
weightofDies <- c(1/40, rep(4/40,4), 23/40)
roll <- sample(1:6, size = n, replace = TRUE, prob = weightofDies)
if(n>0 && all(p=1)) {
return(roll)
}
else {
print("Error, Conditions Not Met")
}
}
I'm confused when the question says use parameter prob = p, then defines p as a vector of non-negative numbers of length 6. How can a probability be defined as a vector? Thus when it came to the conditions my brief understanding made sure the number of rolls (n) was greater than zero. And with p I just went on ahead to make sure the probabilities of this "Vector" added up to one. However not sure if my process thus far is correct. I created my biased probabilities via weightofDies.
f1 = function(t){exp(-t^2)}
phi1 = function(theta){
0.5-1/sqrt(pi)*integrate(f1, lower = 0, upper = (10-theta)/(2*sqrt(2)))}
mu1 = (450*barx)/(454)
sigs1 = 36/454
pi_thetapost = function(theta){
(1/sqrt(2*pi*sigs1))*exp(-((theta-mu1)^2)/(2*sigs1))}
E_phipost = integrate(phi1*pi_thetapost, lower = -Inf, upper =Inf)
I was trying to do a integration, and I got the error says:
non-numeric argument to binary operator
I think that * is a binary operator, but I am not sure how to figure this out.
Thanks~
A few problems here. First barx isn't defined. But the main problem is that you can't just multiple functions in R. You can multiple the values returns by function, but not the functions themselves. You need to pass in a proper function to integrate.
But then after that problem, you need to make sure all the functions you pass in to integrate() are vectorized and your phi function is not. you need to be able to pass in a vector and get a vector out. The easiest way to fix this is with Vectorize(). And finally, integrate() returns an object, not just a number. So if you want to return the calculated value, you need to extract it from the object before you can multiply it by another object. Try
f1 <- function(t){
exp(-t^2)
}
phi1 <- function(theta) {
0.5-1/sqrt(pi)*integrate(f1, lower = 0, upper = (10-theta)/(2*sqrt(2)))$value
}
barx <- 2 # or whatever
mu1 <- (450*barx)/(454)
sigs1 <- 36/454
pi_thetapost <- function(theta){
(1/sqrt(2*pi*sigs1))*exp(-((theta-mu1)^2)/(2*sigs1))
}
myfun <- function(x) {
Vectorize(phi1)(x)*pi_thetapost(x)
}
E_phipost <- integrate(myfun, lower = -Inf, upper =Inf)
E_phipost
# 3.690467e-05 with absolute error < 5.6e-05
E_phipost$value
# [1] 3.690467e-05
in R I try to
1) get a general form of an inverse of a matrix (I mean a matrix with parameters instead of specific numbers),
2) then use this to compute an integral.
I mean, I've got a P matrix with a parameter theta, I need to add and subtract something, then take an inverse of this and multiply it by a vector so that I am given a vector pil. From the vector pil I take term by term and multiply it by a function with again the parameter theta and the result must be integrated from 0 to infinity.
I tried this, but it didn't work because I know the result should be pst=
(0.3021034 0.0645126 0.6333840)
c<-0.1
g<-0.15
integrand1 <- function(theta) {
pil1 <- function(theta) {
P<-matrix(c(
1-exp(-theta), 1-exp(-theta),1-exp(-theta),exp(-theta),0,0,0,exp(-theta),exp(-theta)
),3,3);
pil<-(rep(1,3))%*%solve(diag(1,3)-P+matrix(1,3,3));
return(pil[[1]])
}
q<-pil1(theta)*(c^g/gamma(g)*theta^(g-1)*exp(-c*theta))
return(q)}
(pst1<-integrate(integrand1, lower = 0, upper = Inf)$value)
#0.4144018
This was just for the first term of the vector pst, because when I didn't know how to a for cycle for this.
Please, do you have any idea why it won't work and how to make it work?
Functions used in integrate should be vectorized as stated in the help.
At the end of your code add this
integrand2 <- Vectorize(integrand1)
integrate(integrand2, lower = 0, upper = Inf)$value
#[1] 0.3021034
The result is the first element of your expected result.
You will have to present more information about the input to get your expected vector.
In DEoptim how to fix parameters as integers in lower and upper bounds
opt <- DEoptim(function,lower = c(0.03,17,5,0.002), upper = c(0.12,30,15,-0.5))
In the below example the 2nd, 3rd parameters should be integers but the optimizer takes it as float with upto 6 decimals.
How to fix them as integers?
Here we need to create a Mapping function to map each parameter type. In the above example we have to create the following function,
Mapfun <- function(x){
x[1] <- round(x[1],2) #you can decide to what decimal the optimization to be done by explicit defining the digits here, i need 2 digits
x[2:3] <- round(x[2:3]) #implies that they are integer
x[4] <- round(x[4],3) #here i need 3 digits
}
Now for using in DeOptim:
opt <- Deoptim(function,lower = c(0.03,17,5,0.002), upper = c(0.12,30,15,-0.5),fnMap = Mapfun)
I would like to create two functions that would calculate the probability mass function (pmf) and cumulative distribution function (cdf) for a dice of 20 sides.
In the function I would use one argument, y for the side(from number 1 to 20). I should be able to put a vector and it would return the value for each of the variable.
If the value entered is non-discrete, it should then return zero in the result and a warning message.
This is what have solved so far for PMF:
PMF= function(side) {
a = NULL
for (i in side)
{
a= dbinom(1, size=1, prob=1/20)
print(a)
}
}
And this is what I got for CDF:
CDF= function(side) {
a = NULL
for (i in side)
{
a= pnorm(side)
print(a)
}
}
I am currently stuck with the warning message and the zero in result. How can I assing in the function the command line for that?
Next,how can I plot these two functions on the same plot on a specific interval (for example 1,12)?
Did I use the right function for calculating cdf and pmf?
I would propose the following simplifications:
PMF <- function(side) {
x <- rep(0.05, length(side))
bad_sides <- ! side %in% 1:20 # sides that aren't in 1:20 are bad
x[bad_sides] <- 0 # set bad sides to 0
# warnings use the warning() function. See ?warning for details
if (any(bad_sides)) warning("Sides not integers between 1 and 20 have 0 probability!")
# print results is probably not what you want, we'll return them instead.
return(x)
}
For the CDF, I assume you mean the probability of rolling a number less than or equal to the side given, which is side / 20. (pnorm is the wrong function... it gives the CDF of the normal distribution.)
CDF <- function(side) {
return(pmin(1, pmax(0, floor(side) / 20)))
}
Technically, the CDF is defined for non-integer values. The CDF of 1.2 is just the same as the CDF of 1, so I use floor here. If you want to make it more robust, you could make it min(1, floor(side) / 20) to make sure it doesn't exceed 1, and similarly a max() with 0 to make sure it's not negative. Or you could just try not to give it negative values or values over 20.
Plotting:
my_interval <- 1:12
plot(range(my_interval), c(0, 1), type = "n")
points(my_interval, PMF(my_interval))
lines(my_interval, CDF(my_interval), type = "s")