I have the following optimization function, similar as this one:
R. Run optimization function in data frame:
main <- function(p1, p2, n1, n2, pE) {
# FIND MINIMUM a
func <- function(a) {
Mopt <- (p1-a*pE)/(1-a)
f_n <- (Mopt-p2)^2-Mopt*(1-Mopt)/(n1-1) - p2*(1-p2)/(n2-1)
f_d <- Mopt*(1-p2)+p2*(1-Mopt)
f_v <- f_n/f_d
}
opt <- optimize(func, seq(0, 1,by=0.01), maximum=FALSE)$minimum
}
Here, the arguments of "main" are columns from a data frame. The function returns the minimum value of "a" required to get the minimum f_v value. I would like to add some conditions to the function, or in other words, to force a certain objects to acquire values within a certain range, in order to get the minimum f_v. For instance, Mopt must follow:
0 < Mopt < 1
and (1 - a) must follow:
(1 - a) > 0.
I am not sure how to do this in the context of an optimization.
I think simply add the condition would work. Code might be like this.
func <- function(a) {
a = min(a, 1-1e-7);
Mopt <- max(min((p1-a*pE)/(1-a), 1-1e-7), 1e-7);
#here means a<1 and 0<Mopt<1. 1e-7 ensures the inequality. It can be 1e-6 or 1e-8 depends on the precision you need
f_n <- (Mopt-p2)^2-Mopt*(1-Mopt)/(n1-1) - p2*(1-p2)/(n2-1)
f_d <- Mopt*(1-p2)+p2*(1-Mopt)
f_v <- f_n/f_d
}
opt <- seq(0, 1, 1e-7)[which.min(sapply(seq(0, 1, 1e-7), func))]
Addition:
Code above would return the right $objective but may fail in searching minimum. To search minimum, the function should be.
func <- function(a) {
if ((1-a)<1e-7) return(Inf);
#Ensure the optimization is reached in the range of condition
Mopt <-(p1-a*pE)/(1-a);
if (Mopt<1e-7 || Mopt>(1-1e-7)) return(Inf);
#Ensure the optimization is reached in the range of condition
f_n <- (Mopt-p2)^2-Mopt*(1-Mopt)/(n1-1) - p2*(1-p2)/(n2-1)
f_d <- Mopt*(1-p2)+p2*(1-Mopt)
f_v <- f_n/f_d
}
opt <- seq(0, 1, 1e-7)[which.min(sapply(seq(0, 1, 1e-7), func))]
It is very time consuming but available when you do not need to repeat the computation for many times.
Related
I'm trying to set a function in R to compute the Greatest Common RATIONAL Divisor of a vector. So I'm not working with a vector of integers, but of numerics. And from this vector I would like to automatically determine the highest numeric that can divide all the values in the vector and result in a integer. Which is very difficult with floating-point arithmetic used in R.
To give an example, lets say that I would like to find the highest common rational divisor of 5, 0.37 and 0.02. It's 0.01, but how can I automate this, taking into account that with floating-point arithmetic 0.37 will for instance be considered like 0.3700000000000000000000000005271 in R (something like that) ? With that problem I can't easily compute the lowest order of decimal (10^-2 in my example), or if you prefer the lowest one that has significance for me as user.
The fact that the result in itself will have floating-point-like error (e.g. 0.0100000000000000000000008465 in place of 0.01) is not a problem. However ideally the solution should be the most general possible (capable of working with vectors having extremely different values (10^20 and 10^-20 for instance).
I got a solution. So the basic idea is to divide everything by the smallest value, to multiply by integers, until every value is made of integers. This is controlled via the floor() function, which allows to have explicit control over the level of tolerance. I added some control to the amount of possibilities it tests, to make it kind of efficient, but I'm not sure this is the best method. Anyway I'll put this in the StratigrapheR package
divisor <- function(x, tolerance = 8, relative = T, tries = 4, speak = T)
{
if(!(isFALSE(relative) | isTRUE(relative))) {
stop("The 'relative' parameter should be TRUE or FALSE'")
}
if(!(isFALSE(speak) | isTRUE(speak))) {
stop("The 'speak' parameter should be TRUE or FALSE'")
}
x <- unique(x)
x <- x[x != 0]
# Divide by smallest
mx <- min(x)
d <- x/mx
if(!relative){
# Test if tolerance is of lower order than the smallest
if(-log10(mx) > tolerance) {
stop(paste("If 'relative' is FALSE, the smallest value (zero excepted)",
"should of higher order than the order",
"defined by the 'tolerance' parameter"))
}
}
# Test the dispersion of values
general_tolerance <- 15 # Order of digits affected by floating-point
if(log10(max(x)) >= (general_tolerance - tolerance)){
stop(paste("The range of 'x' values is too large to find a meaningful",
"greatest common rational divisor.",
"To solve this problem you can change the values in x or",
" lower the 'tolerance' parameter (i.e. the",
"tolerance for floating-point aritmetics):in the later case be",
"critical of the result."))
}
# Test and remove values that are multiples of the smallest value
remain1 <- (d - floor(d + 10^-(tolerance - 1)))
if(!relative) remain1 <- remain1 * mx
rzero1 <- abs(remain1) < 10^-tolerance
d <- d[!rzero1]
if(length(d) == 0) {
if(!relative){
res <- round(mx, tolerance)
} else {
res <- signif(mx, tolerance)
}
} else {
# Multiply d [x/min(x)] by integers, and test if
# this returns only integers within tolerance
ld <- length(d)
try_order_OLD <- 0
try_order_i <- 6 - ceiling(log10(ld))
for(i in seq_len(as.integer(tries))){
if(speak) {
print(paste("Try ",i,": 10^",try_order_i,
" possibilities tested", sep = ""))
}
t <- 1:(10^try_order_i)
t <- t[-(1:(10^try_order_OLD))]
lt <- length(t)
tmat <- matrix(rep(t,ld), ncol = ld)
dmat <- matrix(rep(d, lt), ncol = ld, byrow = T)
test <- dmat * tmat
remain2 <- (test - floor(test + 10^-(tolerance - 1)))
remain2 <- remain2/tmat
if(!relative) remain2 <- remain2 * mx
rzero2 <- abs(remain2) < 10^-tolerance
rzero2 <- matrix(as.integer(rzero2), ncol = ld)
test[which(rowSums(rzero2) == ld),]
res <- mx/t[which(rowSums(rzero2) == ld)[1]]
if(!is.na(res)) break
try_order_OLD <- try_order_i
try_order_i <- try_order_i + 1
}
}
return(res)
}
The problem is to simulate an equation with variables that change. All the variables are fixed, expect for lower case s and treat_date. Here is the error message:
Error in checkFunc(Func2, times, y, rho) : The number of derivatives
returned by func() (202) must equal the length of the initial
conditions vector (2)
I have tried moving things around but I honestly have no idea what I am doing
seasonal_SI <- function (t, y, parameters) {
S <- y[1]
I <- y[2]
with(as.list(parameters), {
julian_date <- t %% 365
v <- ifelse(julian_date >= treat_date &
julian_date < (treat_date + 10) &
treatment, 0.9, v)
beta <- beta0 + s*beta0*sin(2*pi*(julian_date)/365)
dSdt <- b*(1-c*(S+I))*(S+rho*I)-d*S-beta*S*I
dIdt <- beta*S*I-(d+v)*I
res <- c(dSdt, dIdt)
list(res)
})
}
initials <- c(S=99, I=1)
params <- c(b=.5, c=.01, beta0=5e-3, v=.05, rho=.3, treatment=TRUE,
s=as.numeric(seq(from=0, to=1, by=.01)),
treat_date=as.numeric(seq(from=0, to=355, length.out=101)))
t <- 0:1
library("deSolve")
lsoda(y=initials, times=t, parms=params, func=seasonal_SI)
I would like for it to run and return a graph.
I agree with the former comment, that you may consider to use a parameter list. However, you may also consider to use a forcing function or the event mechanism.
You find help pages in deSolve:
?forcings
?events
and a short tutorial here: https://tpetzoldt.github.io/deSolve-forcing/deSolve-forcing.html
I'm trying to write the following function:
f <- function(q, r) {
for(i in seq(from = (1 - r), to = (r - 1), by = 1)){
s <- r + i;
if (q %% s == 0) {
here(s)
}
}
}
However, where I have "here," I'd like those values of s that meet the criterion specified by the "if" statement above it, so that I may perform operations on it (take max and min values, and whatnot), i.e. a vector of the form:
v <- c(those values of s that meet the criterion stipulated by if statement)
I'm sure this is relatively simple, but this is the first function I've tried to write in R, so bear with me, if you could. Thanks.
From what I understand in your code, you want to create a vector from (1-r+r) to (r-1+r) and then if the values of that vector are divisible by q, then you want to apply a function to them.
I created a vector of only the numbers that meet the condition (by sub-setting with the TRUE/FALSE vector) and then applied the function only to those that met the condition.
I hope this code correctly interprets your function.
f <- function(q, r) {
s <- seq(1, 2*r-1, by=1)
ind <- ifelse(q %% s == 0, TRUE, FALSE)
result <- here(s[ind])
return(result)
}
I don't have background in programming (except from wrestling with R to get things done), and I'm trying to verbalize what the formula for the greater common divisor in the R {numbers} package is trying to do at each step. I need help with understanding the flow of steps within the function:
function (n, m)
{
stopifnot(is.numeric(n), is.numeric(m))
if (length(n) != 1 || floor(n) != ceiling(n) || length(m) !=
1 || floor(m) != ceiling(m))
stop("Arguments 'n', 'm' must be integer scalars.")
if (n == 0 && m == 0)
return(0)
n <- abs(n)
m <- abs(m)
if (m > n) {
t <- n
n <- m
m <- t
}
while (m > 0) {
t <- n
n <- m
m <- t%%m
}
return(n)
}
<environment: namespace:numbers>
For instance, in the if (m > n) {} part the n becomes t and ultimately it becomes m? I'm afraid to ask, because it may be painfully obvious, but I don't know what is going on. The same apply to, I guess, he else part of the equation with %% being perhaps modulo.
What it says is:
Stop if either m or n are not numeric, more than one number, or have decimals, and return the message, "Arguments 'n', 'm' must be integer scalars."
If they both are zero, return zero.
Using absolute values from now on.
Make sure that n > m because of the algorithm we'll end up applying in the next step. If this is not the case flip them: initially place n in a temporary variable "t", and assign m to n, so that now the larger number is at the beginning of the (n, m) expression. At this point both the initial (n, m) values contain m. Finish it up by retrieving the value in the temporary variable and assigning it to m.
Now they apply the modified Euclidean algorithm to find the GCD - a more efficient version of the algorithm that shortcuts the multiple subtractions, instead replacing the larger of the two numbers by its remainder when divided by the smaller of the two.
The smaller number at the beginning of the algorithm will end up being the larger after the first iteration, therefore we'll assign it to n to get ready for the second iteration. To do so, though, we need to get the current n out of the way by assigning it to the temporary variable t. After that we get the modulo resulting from dividing the original larger number (n), which now is stored in t, by the smaller number m. The result will replace the number stored in m.
As long as there is a remainder (modulo) the process will go on, this time with the initial smaller number, m playing the role of the big guy. When there is no remainder, the smaller of the numbers in that particular iteration is returned.
ADDENDUM:
Now that I know how to read this function, I see that it is limited to two numbers in the input to the function. So I entertained myself putting together a function that can work with three integers in the input:
require(numbers)
GCF <- function(x,y,z){
tab.x <- tabulate(primeFactors(x))
tab.y <- tabulate(primeFactors(y))
tab.z <- tabulate(primeFactors(z))
max.len <- max(length(tab.x), length(tab.y), length(tab.z))
tab_x = c(tab.x, rep(0, max.len - length(tab.x)))
tab_y = c(tab.y, rep(0, max.len - length(tab.y)))
tab_z = c(tab.z, rep(0, max.len - length(tab.z)))
GCD_elem <- numeric()
for(i in 1:max.len){
GCD_elem[i] <- min(tab_x[i], tab_y[i], tab_z[i]) * i
}
GCD_elem <- GCD_elem[!GCD_elem==0]
GrCD <- prod(GCD_elem)
print(GrCD)
}
Also for the LCM:
LCM <- function(x,y,z){
tab.x <- tabulate(primeFactors(x))
tab.y <- tabulate(primeFactors(y))
tab.z <- tabulate(primeFactors(z))
max.len <- max(length(tab.x), length(tab.y), length(tab.z))
tab_x = c(tab.x, rep(0, max.len - length(tab.x)))
tab_y = c(tab.y, rep(0, max.len - length(tab.y)))
tab_z = c(tab.z, rep(0, max.len - length(tab.z)))
LCM_elem <- numeric()
for(i in 1:max.len){
LCM_elem[i] <- i^(max(tab_x[i], tab_y[i], tab_z[i]))
}
LCM_elem <- LCM_elem[!LCM_elem==0]
LCM <- prod(LCM_elem)
print(LCM)
}
I am trying to use a two dimension matrix to produce a two dimension matrix result where
the number of rows and number of columns are determined in a new way everytime I change the values in the function which determines the number of rows and number of columns accordingly.
The function that I would like to ask and resolve the "subscript out of bounds" problem is the following:
HRC <- function(n,b,c)
{
R=matrix( ,nrow = n*b, ncol = c)
R[0,]=133
for (j in 1:c)
{
r=rnorm(n*b)
for (i in 1:n*b){
R[i+1,j]=R[i,j]+3*b/r[i]
}
}
return(R)
}
HRC(10,1,3)
The error message that I get is the following:
Error in R[i + 1, j] = R[i, j] + 3 * b/r[i] : subscript out of bounds
I wonder how I can resolve this problem. Thank you so much in advance.
R's indexing starts at 1, not 0.
You also have to be careful with the operators precedence rules: the : operator has higher precedence than *. See ?Syntax.
This should work:
HRC <- function(n, b, c) {
R <- matrix(NA, nrow = n*b, ncol = c)
R[1,]=133
for (j in 1:c) {
r = rnorm(n*b)
for (i in 1:(n*b-1)){
R[i+1,j] = R[i,j] + 3*b/r[i]
}
}
return(R)
}
HRC(10,1,3)
The problem is that you loop from row b to row n*b (with stride b, due to the precedence of * and :) and then index to one greater, so you attempt to index row n*b + 1 of R, which is out of bounds.
R[0,]<- will cause incorrect results but not elicit an error from R.
I find the code easier to read if you loop from 2 to n*b, the number of rows, and write the formula in terms of creating row i from row i-1 (rather than creating row i+1 from row i).
In addition, you can drop one loop dimension by vectorizing the operations over the rows:
HRC <- function(n, b, c) {
R <- matrix(NA, nrow = n*b, ncol = c)
R[1,] <- 133
r <- matrix(rnorm(n*b*c), ncol=c)
for (i in 2:(n*b)){
R[i,] <- R[i-1,] + 3*b/r[i-1,]
}
return(R)
}
HRC(10,1,3)
Here, the same number of random samples are taken with rnorm but they are formed as a matrix, and used in the same order as used in the question. Note that not all of the random values are actually used in the computation.
If you set a random seed and then run this function, and the function in #flodel's answer, you will get identical results. His answer is also correct.
I think you are making three mistakes:
First: You are messing up the row count on the index. It should be 1:(n*b) and not 1:n*b.
Second: In R, indexing starts at 1. So R[0,] should be replaced by R[1,].
Third: You are running the loops in the right bounds 1:c and 1:(n:b), but you are probably not keeping track of the indices.
Try this:
set.seed(100)
HRC <- function(n, b, c) {
R <- matrix(0, nrow = n*b, ncol = c)
R[1,] <- 133
for (j in 1:c) {
r <- rnorm(n*b)
for (i in 2:(n*b)){
R[i,j] <- R[i-1,j] + 3*b/r[i-1]
}
}
return(R)
}
HRC(10,1,3)
Lastly, I would like to warn you about interchangeable use of the assignment operators. See here.