I am quite new to r, so I turned to the internet for some help.
My question is:
for the equation ln(n/n0) = kln(1+x/k),
I would like to write a function that estimates k (based of trial and error) if all other variables are known.
In other words: function that would solve the equation like
0.85 = k * ln(1+0.56/k).
In my work I have to estimate k over and over again so the automation of the process would save me alot of time.
Thanks
Too long for a comment...
The equation x*ln(1+a/x) = b (for suitable values of a and b) has a solution expressed with the Lambert W function, available in the gsl package under the name lambert_W0. This solution is -a*b/(a*W(-b/(a*exp(b/a)))+b) where W is the Lambert W function.
> library(gsl)
> a=0.56; b=0.85
> x <- -a*b/(a*lambert_W0(-b/(a*exp(b/a)))+b) # solution of the equation
> x*log(1+a/x)
[1] 0.85
I don't know exactly for which values of a and b this solution works. It seems to work whenever a<b.
For some cases of a>b, there is a solution in terms of the Lambert W_{-1} function, lambert_Wm1 in gsl:
> library(gsl)
> a=0.6; b=0.4
> x <- -a*b/(a*lambert_Wm1(-b/(a*exp(b/a)))+b)
> x*log(1+a/x)
[1] 0.4
The domains of definition of W and W_{-1} can be found in the documentation of the lamW package (section "Details" page 3).
Related
I'm trying to write an equation in R, and then solve it. I'm fairly new to R, so it's probably a basic question, but I haven't been able to make much sense of the CRAN notes on several packages that come up with a google.
My equation:
F- b ln(|1+ (F/b)|) - 0.05t = 0
I'm trying to solve for F, and have other equations/variables in R that define b and t already.
I guess what I'm asking is, how do I translate this formula into something in R, and go about solving it for F?
Assuming b and t are scalars with known values (here we assume 1 for both) we can minimize the the square of the left hand side assuming the answer lies in the indicated interval and if it achieves zero (which it does below) we have solved it. Note that F means FALSE in R so we used FF for clarity.
fun <- function(FF, b, t) (FF - b * log(abs(1+ (FF/b))) - 0.05*t)^2
optimize(fun, c(-10, 10), b = 1, t = 1)
giving:
$minimum
[1] 0.3503927
$objective
[1] 7.525844e-12
I am having the hardest time trying to implement this equation into a nonlinear solver in R. I am trying both the nleqslv and BB packages but so far getting nothing but errors. I have searched and read documentation until my eyes have bled, but I cannot wrap my brain around it. The equation itself works like this:
The Equation
s2 * sum(price^(2*x+2)) - s2.bar * sum(price^(2*x)) = 0
Where s2, s2.bar and price are known vectors of equal length.
The last attempt I tried in BB was this:
gamma = function(x){
n = len(x)
f = numeric(n)
f[n] = s2*sum(price^(2*x[n]+2)) - s2.bar*sum(price^(2*x[n]))
f
}
g0 = rnorm(length(price))
results = BBsolve(par=g0, fn=gamma)
From you description of the various parts used in the function you seem to have muddled up the formula.
Your function gamma should most probably be written as
gamma <- function(x){
f <- s2*sum(price^(2*x+2)) - s2.bar*sum(price^(2*x))
f
}
s2, price and s2.bar are vectors from your description so the formula you gave will return a vector.
Since you have not given any data we cannot test. I have tried testing with randomly generated values for s2, price, s2.bar. Sometimes one gets a solution with both nleqslv and BB but not always.
In the case of package nleqslv the default method will not always work.
Since the package has different methods you should use the function testnslv from the package to see if any of the provided methods does find a solution.
I am getting an equation with this form
exp(az) = 1 + cz
which I wanna solve for z,
where c is a complex number, so expectedly z is complex also.
I cannot figure out how to solve an equation involving complex number in R.
I hope anybody can help me
Wolfram Alpha can get a solution in terms of the Lambert W function (which it calls the ProductLog function):
The emdbook package (among others) has an implementation of the Lambert W function. (In order to make this work I had to fix a bug, so you can't use the CRAN implementation. Instead, install the latest version from Github: library(devtools); install_github("bbolker/emdbook") ...
library(emdbook)
sfun <- function(a,c) {
w <- lambertW(-a/c*exp(-a/c))
-(c*w+a)/(a*c)
}
Example
a <- 2+1i; c <- 1+1i
(z <- sfun(a,c))
## [1] -0.1686391-0.2337278i
Check answer:
(exp(a*z)-(1+c*z))
## [1] 0+5.551115e-17i
This is zero to within expected numeric tolerance ...
The intermediate step in Ben Bolker's solution:
I have a question concerning the possibility to solve functions in R, and doing the same using excel.
However I want to do it with R to show that R is better for my colleagues :)
Here is the equation:
f0<-1e-9
t_pw<-30e-9
a<-30.7397582453682
c<-6.60935546184612
P<-1-exp((-t_pw)*f0*exp(-a*(1-b/c)^2))
I want to find the b value for P<-0.5. In Excel we can do it by selecting P value column and setting it to 0.5 and then by using the solver parameters function.
I don't know which method is the best? Or any other way to do it?
Thankx.
I have a strong suspicion that your equation was supposed to include -t_pw/f0, not -t_pw*f0, and that t_pw was supposed to be 3.0e-9, not 30e-9.
Pfun <- function(b,f0=1e-9,t_pw=3.0e-9,
a=30.7397582453682,
c=6.60935546184612) {
1-exp((-t_pw)/f0*exp(-a*(1-b/c)^2))
}
Then #Lyzander's uniroot() suggestion works fine:
u1 <- uniroot(function(x) Pfun(x)-0.5,c(6,10))
The estimated value here is 8.05.
par(las=1,bty="l")
curve(Pfun,from=0,to=10,xname="b")
abline(h=0.5,lty=2)
abline(v=u1$root,lty=3)
If you want to solve an equation the simplest thing is to do is to use uniroot which is in base-R.
f0<-1e-9
t_pw<-30e-9
a<-30.7397582453682
c<-6.60935546184612
func <- function(b) {
1-exp((-t_pw)*f0*exp(-a*(1-b/c)^2)) - 0.5
}
#interval is the range of values of b to look for a solution
#it can be -Inf, Inf
> uniroot(func, interval=c(-1000, 1000), extendInt='yes')
Error in uniroot(func, interval = c(-1000, 1000), extendInt = "yes") :
no sign change found in 1000 iterations
As you see above my unitroot function fails. This is because there is no single solution to your equation which is easy to see as well. exp(-0.0000000000030 * <positive number between 0-1>) is practically (very close to) 1 so your equation becomes 1 - 1 - 0.5 = 0 which doesn't hold. You can see the same with a plot as well:
curve(func) #same result for curve(func, from=-1000, to=1000)
In this function the result will be -0.5 for any b.
So one way to do it fast, is uniroot but probably for a different equation.
And a working example:
myfunc2 <- function(x) x - 2
> uniroot(myfunc2, interval=c(0,10))
$root
[1] 2
$f.root
[1] 0
$iter
[1] 1
$init.it
[1] NA
$estim.prec
[1] 8
Let's say I have a function that is nlogn in space requirements, I want to work out the maximum size of input for that function for a given available space. i.e. I want to find n where nlogn=c.
I followed an approach to calculate n, that looks like this in R:
step = function(R, z) { log(log(R)-z)}
guess = function(R) log(log(R))
inverse_nlogn = function(R, accuracy=1e-10) {
zi_1 = 0
z = guess(R)
while(abs(z - zi_1)>accuracy) {
zi_1 = z
z = step(R, z)
}
exp(exp(z))
}
But I can't get understand why it must be solved iteratively. For the range we are interested (n>1), the function is non singular.
There's nothing special about n log n — nearly all elementary functions fail to have elementary inverses, and so have to be solved by some other means: bisection, Newton's method, Lagrange inversion theorem, series reversion, Lambert W function...
As Gareth hinted the Lambert W function (eg here) gets you almost there, indeed n = c/W(c)
A wee google found this, which might be helpful.
Following up (being completely explicit):
library(emdbook)
n <- 2.5
c <- 2.5*log(2.5)
exp(lambertW(c)) ## 2.5
library(gsl)
exp(lambert_W0(c)) ## 2.5
There are probably minor differences in speed, accuracy, etc. of the two implementations. I haven't tested/benchmarked them extensively. (Now that I tried
library(sos)
findFn("lambert W")
I discover that it's implemented all over the place: the games package, and a whole package that's called LambertW ...