Find Anti-derivative in R - r

I want to be able to find the anti-derivative of an arbitrary function in R.
Suppose I´ve got f = 1/(2*x^2) and want to find F, which by the way is easy to calculate by hand.
I´ve tried the following:
f<- function (x) {1/(sqrt(x))}
F = antiD(f)
This gives me:
Error: no applicable method for 'rhs' applied to an object of class "function"
Can someone give me a push in the right direction here?

Are you using the mosaicCalc package?
I don't think you can use a function as argument to the antiD(). It expects a formula:
F <- antiD( 1/sqrt(x) ~ x)
This will give you a function F that takes two parameters x and C (constant). In this instance, it can't do a symbolic integration as it doesn't know what to do with the sqrt() function. If you alternatively did:
F <- antiD(x^-0.5 ~ x)
Then you'll see that symbolic integration has been done:
F
function (x, C = 0) {2 * x^(1/2) + C}

With Ryacas:
library(Ryacas)
yac_str("Integrate(x) 1/Sqrt(x)")
# [1] "2*Sqrt(x)"

Related

nls2 with nested functions

I am trying to find parameters using the nls2 package. As the formula I am trying to optimize parameters for is quite complex, I try to use functions that I call within the formula I optimize with the nls2 command:
library(nls2)
set.seed(20160227)
x <- seq(0,50,1)
y <- ((runif(1,10,20)*x)/(runif(1,0,10)+x))+rnorm(51,0,1)
a <- function(){
d+1
}
f1 <- function(){
y <- a()*x/(b+x)
}
st <- data.frame(d = c(-100,100),
b = c(-100,100))
nls2(f1,start = st, algorithm = "brute-force")
Currently, this throws the error
Error: object of type 'closure' is not subsettable
I found this error here, however when I assign values to b and d this works:
a()*x/(b+x)
I assume the problem is that I try to find b and d using functions that already have them inside?
What is the best way to do this? Is it even possible or do I need to define the entire complex formula within nls2?
Neither f1 nor a here have any parameters, so it's not really surprising that it's having some difficulty understanding how you want to optimize f1.
nls2::nls2 (like stats::nls) expects a formula as the first parameter. That formula can be built from any function you want, and does not have to be written down entirely in the call. You could do the following:
a <- function(d){
d+1
}
f1 <- function(b,d,x){
y <- a(d)*x/(b+x)
}
And then fit the model like this:
nls2(y~f1(b,d,x), start = st, algorithm = "brute-force")
Because no start value is provided for x, and because its actual value can be found in the environment, it won't optimize over x, just b and d.

function return as another function parameter with eval() in R

I have a difficulty in learning how to use eval() to evaluate a function,
suppose i have a function:
sq <- function(y){ y**2 }
u can evaluate this function like this:
call <- match.call(expand.dots = FALSE)
call[[1]] <- as.name('sq')
call$y <- 0.2
call <- call[c(1,3)]
eval(call)
and it will give u 0.2^2 = 0.04
But if i want to calculate sth like sq(y), where y = sin(x), i may write:
call <- match.call(expand.dots = FALSE)
call[[1]] <- as.name('sq')
call$y <- as.name('sin')
call$x <- 0.2
call <- call[c(1,3:4)]
eval(call)
it will give me this error:
Error in sq(y = sin, x = 0.2) : unused argument (x = 0.2)
Seems that R cannot recognize x as an argument of sin, but an argument of sq instead. how can we tell R that x is an argument of sin?
Also, it seems that R is the only language i have learned that uses eval() to evaluate a function (i know C++ and Python, but havent seen that syntax before), what is the different (or advantage) to evaluate a function in this way instead of calling sq(y=sin(x=0.2))?
Is there a good book or tutorial talking about its usage, and when to use between the two ways? Thanks!
PS: the example above is actually a simplified version of the code in mlogit package im studying, in which the log likelihood is returned by calling 'lnl.slogit' and is passed to 'mlogit.optim' and get optimized (Line 407 of https://github.com/cran/mlogit/blob/master/R/mlogit.R). I used the same method as the code in the package to call two functions, but i got the error above.
The code is trying to pass:
an argument x to sq but sq has no x argument
the function sin in argument y but a number is required, not a function.
Try this:
x <- 0.2
cl <- call("sq", y = quote(sin(x)))
cl
## sq(y = sin(x))
eval(cl)
## [1] 0.0394695
or maybe what you want is:
x <- 0.2
cl <- call("sq", y = sin(x))
cl
## sq(y = 0.198669330795061)
eval(cl)
## [1] 0.0394695
or
match.fun("sq")(sin(x))
## [1] 0.0394695
or just:
sq(sin(x))
## [1] 0.0394695
Note that ordinarily you do not have to use eval. Just listing the function with its arguments is enough to evaluate it as the in last line of code.
The regression functions in R internally use non-standard code due to considerations related to environments but ordinarily that would not be needed in other contexts.

Solve a Non-linear Equation of one variable but written in a summation form, in "R"

This is the Non-Linear Equation in "mu" which I want to solve numerically using R. All of the paired (x, y) are known. So the only variable is "mu"
Now, I have written the function in R. Then, I am trying to get the root by using "rootSolve" package. But it is giving an error.
This is my code of the function:
f = function(k){
sum(((2*exp(-x) - 1)*(2*exp(-y)- 1))/
(1 + k*(2*exp(-x) - 1)*(2*exp(-y)- 1)))
}
This is the error after running "uniroot.all" from the "rootSolve" package:
> library(rootSolve)
> uniroot.all(f, interval = c(-1, 1))
numeric(0)
Warning message:
In k * (2 * exp(-x) - 1) :
longer object length is not a multiple of shorter object length
Also, I am searching my root in the interval (-1, 1).
Can someone please help? I think, my way of defining the function is wrong. Hence this error is coming.
Can anyone confirm that my way of defining the function in the picture is correct or not?
Thank you in advance!
Let me add something more:
The way I have defined my function (chances are high that the way is wrong) and given my data (x, y), I have f(-1) < f(1) and also f(-1) * f(1) < 0. These conditions are satisfied.
Additional Problem that makes me question my way of writing the function:
I cannot run curve function in R. e.g., curve(f, from = -1, to = 1)
But, if I plot Vectorize(f), then the curve function works.
Can anyone please help me in correcting the way of defining the function?
Thank you very much!
It seems that uniroot.all wants a vectorized function. I have tried to use it and get the same error as you do. I can't find anything in the documentation of uniroot.all about this.
I have tried package nleqslv and can get a solution.
I have rewritten your function as follows (I think you made some errors in setting up the equation):
f <- function(k){
A <- 2*exp(-x)-1
B <- 2*exp(-y)-1
sum((A*B)/(1+k*A*B))
}
and run the function with these data
set.seed(13)
x <- runif(10)*10
y <- runif(10)*5
and the solved your function as follows:
library(nleqslv)
nleqslv(0,f)
with the following output:
$x
[1] 1.42992
$fvec
[1] 2.300633e-09
$termcd
[1] 1
$message
[1] "Function criterion near zero"
$scalex
[1] 1
$nfcnt
[1] 7
$njcnt
[1] 1
$iter
[1] 7
This solves with a Secant method. If you want to try other methods you can use testnslv to explore.
** Addition **
Function uniroot.all will work in my example as long as you do:
fvec <- Vectorize(f)
and change the interval to c(-1,1.7).

R - Picard Method for General Polynomial

I am currently writing a program in R to find solutions of a general polynomial difference equation using Picard's method.
For an insight in the mathematics behind it (as math mode isn't available here):
https://math.stackexchange.com/questions/2064669/picard-iterations-for-general-polynomials/2064732
Now since then I've been trying to work with the Ryacas package for integration. However I ran into trouble trying to work with the combination of expression and integration function.
library(Ryacas)
degrees = 3
a = c(3,5,4,6)
x0 = -1
maxIterations(10)
iteration = vector('expression', length = maxIterations)
iteration[1] = x0
for(i in 2:maxIterations){
for(i in 1:degrees){
exp1 = expression( a[i] * iteration[i-1] ^ i)
}
iteration[i] = x0 + Integrate(exp1, t)
}
but this results in
"Error in paste("(", ..., ")") :
cannot coerce type 'closure' to vector of type 'character'"
and exp1 = expression(a[j] * iteration[i-1]^j) instead of an actual expression as I tried to achieve. Is there anyway I can make sure R reads this as a real expression (i.e. for example 3 * ( x0 ) ^ j for i = 2)?
Thanks in advance!
Edit:
I also found the Subst() function, and currently trying to see if anything is fixable using it. Now I am mainly struggling to actually set up an expression for m coefficients of a, as I can't find a way to create e.g. a for loop in the expression() command.

R: how to pass functions as arguments to another function

Suppose I want to integrate some function that involves sums and products of a few other user defined functions. Lets take an extremely simple example, it gives the same error.
integrate(f = sin + cos, lower=0, upper=1)
This yields "Error in sin + cos : non-numeric argument to binary operator" which I think is saying it doesn't make sense to just add functions together without passing them some sort of argument. So I am a bit stuck here. This thread poses what I think is a solution to a more complicated question, that can be applied here, but it seems long for such a simple task in this case. I'm actually kind of surprised that I am unable to find passing function arguments to functions in the help manual so I think I am not using the right terminology.
Just write your own function:
> integrate(f = function(x) sin(x) + cos(x), lower=0, upper=1)
1.301169 with absolute error < 1.4e-14
In this example I've used an anonymous function, but that's not necessary. The key is to write a function that represents whatever function you want to integrate over. In this case, the function should take a vector input and add the sin and cos of each element.
Equivalently, we could have done:
foo <- function(x){
sin(x) + cos(x)
}
integrate(f = foo, lower=0, upper=1)
This is an old question, but I recently struggled with it, so here is a simple example in case it helps others in the future. #joran's answer is still the best.
Define your first function: f1 <- function(x){return(x*2)}
Test it: f1(8) (expect 8*2=16); returns [1] 16
Define your second function: f2 <-function(f, y){return(f+y)}
Test it: f2(f=f1(8), y=1) (expect 8*2 = 16 +1 = 17); returns [1] 17

Resources