Search code examples
rnonlinear-functions

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".

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!


Solution

  • 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).