solving a simple (?) system of nonlinear equations - r

I'm trying to solve a simple system of non-linear equations described in this post.
The system is two equations with two unknowns p and q and a free parameter lambda:
When lambda = 1 the system looks like this:
There is a unique solution and it's in the vicinity of p = 0.3, q = 0.1.
I'm trying to solve it with nleqslv. My objective function is:
library(nleqslv)
fn = function(x, lambda = 1){
# p = x[1]
# q = x[2]
pstar = exp(lambda * (1*x[2])) / (exp(lambda * (1*x[2])) + exp(lambda * (1 - x[2])))
qstar = exp(lambda * (1 - x[1])) / (exp(lambda * ((1 - x[1]))) + exp(lambda * (9*x[1])))
return(c(pstar,qstar))
}
but the results don't match what the plot:
> xstart = c(0.1, 0.3)
> nleqslv(xstart, fn)$x
[1] 1.994155 -8.921285
My first question is: am I using nleqslv correctly? I thought so after looking at other examples. But now I'm not sure.
My second question: is this a good problem nleqslv? Or am I barking up the wrong tree?

Your function does not reflect properly what you want.
You can see this by evaluating fn(c(0.3,0.1)) as follows.
fn(c(0.3,0.1))
[1] 0.3100255 0.1192029
So the output is very close to the input. You wanted (almost) zero as output.
So you want to solve the system for p and q.
What you need to do is to make your function return the difference between the input p and the expression for pstar and the difference between the input q and the expression for qstar.
So rewrite your function as follows
fn <- function(x, lambda = 1){
p <- x[1]
q <- x[2]
pstar <- exp(lambda * (1*x[2])) / (exp(lambda * (1*x[2])) + exp(lambda * (1 - x[2])))
qstar <- exp(lambda * (1 - x[1])) / (exp(lambda * ((1 - x[1]))) + exp(lambda * (9*x[1])))
return(c(pstar-p,qstar-q))
}
and then call nleqslv as follows (PLEASE always show all the code you are using. You left out the library(nleqslv)).
library(nleqslv)
xstart <- c(0.1, 0.3)
nleqslv(xstart, fn)
This will display the full output of the function. Always a good idea to check for succes. Always check $termcd for succes.
$x
[1] 0.3127804 0.1064237
$fvec
[1] 5.070055e-11 6.547240e-09
$termcd
[1] 1
$message
[1] "Function criterion near zero"
$scalex
[1] 1 1
$nfcnt
[1] 7
$njcnt
[1] 1
$iter
[1] 7
The result for $x is more what you expect.
Finally please use <- for assignment. If you don't there will come the day that you will be bitten by R and its magic.
This is nothing wrong in using nleqslv for this problem. You only made a small mistake.

Related

Sum function in the R programming

In R , I have a vector like x= 3:100
I want to write function like:
sum ( (x/a)^2t) - 5
and get the answer if I choose any value for t .
Example:
Func= function ( t ) {
x=c(1:100)
a= min(x)
Sum ( x / a )^2t - 5
}
I don't know if this correct or not.
what about if I want to get the root of the function by secant method. I use library(NLRoot) in R. but the codes that I write it is not correct.
library(NLRoot)
curve(func, xlim=c(0,3), col='blue', lwd=1.5, lty=2,xlab="x",ylab="f(x)")
output is written Error in code.
Here is just a syntax correction
Func <- function(t) {
x <- c(1:100)
a <- min(x)
sum((x / a)^(2 * t)) - 5
}
and a more compact version might be something like below
Func <- function(t, x = 1:100) sum((x / min(x))^(2 * t)) - 5
To find the root, thanks for comments from #Rui Barradas, we can use uniroot, i.e.,
> uniroot(Func, interval = c(-5, 5))
$root
[1] -0.5091492
$f.root
[1] -0.0003913713
$iter
[1] 13
$init.it
[1] NA
$estim.prec
[1] 6.103516e-05

Package nleqslv Error: Length of fn result <> length of x

I am solving a nonlinear equation using the package nleqslv, but I keep getting the error: Length of fn result <> length of x!
I can't spot the place where vector length can be a problem. Anyone knows what mistakes did I made in my code?
library(nleqslv)
d_plus <- function(x) (log(55.75/x[1])+(0.026 + x[2]^2 / 2) * 0.25) / (x[2]*0.5) + 0 * x[3]
d_minus <- function(x) (log(55.75/x[1])+(0.026 - x[2]^2 / 2) * 0.25) / (x[2]*0.5) + 0 * x[3]
F_C0 <- function(x) 55.75 * pnorm(d_plus(x)) - x[1] * exp(-0.026 * 0.25) * pnorm(d_minus(x)) + 0 * x[3]
eqn <- function(x) F_C0(x) - x[3]
nleqslv( c(40, 1, 17.35), eqn)
I am trying to solve for x[2] and I have the input of x[1] and x[3]. It looks like I should get the numeric solution of x[2].
Your example is not reproducible since you have not shown all your code: library(nleqslv) is missing. Please show all your code.
As the first comment on your question stated you are providing a vector to eqn but functions d_plus, d_minus and thus F_C0 return a scalar.
That implies that the length of the function result is not the same as the length of the input.
From your explanation you want to solve for x[2]. So the function presented to nleqslv must take a scalar as input and return a scalar.
This can be achieved as follows:
library(nleqslv)
d_plus <- function(x) (log(55.75/x[1])+(0.026 + x[2]^2 / 2) * 0.25) / (x[2]*0.5) + 0 * x[3]
d_minus <- function(x) (log(55.75/x[1])+(0.026 - x[2]^2 / 2) * 0.25) / (x[2]*0.5) + 0 * x[3]
F_C0 <- function(x) 55.75 * pnorm(d_plus(x)) - x[1] * exp(-0.026 * 0.25) * pnorm(d_minus(x)) + 0 * x[3]
eqn <- function(xpar) { x <- c(40,xpar,17.35);F_C0(x) - x[3] }
Insert the scalar argument of eqn, which is your x[2], into a vector x where the first and third entries are what you provided as starting values in your code .
Then running this
xstart <- 1
nleqslv( xstart, eqn)
results in this
$x
[1] 0.6815036
$fvec
[1] 6.18563e-11
$termcd
[1] 1
$message
[1] "Function criterion near zero"
$scalex
[1] 1
$nfcnt
[1] 5
$njcnt
[1] 1
$iter
[1] 5
Read the documentation of nleqslv to see what these items mean.
As you can see nleqslv found a solution to your problem.

R loop to approximate square root of a positive real number with Newton's method

I am new to R and I'm working on a homework question which asks me to use a repeat loop using Newton's method for square root approximation. Here is what I have so far:
x = 2
a = 10
tol = 1e-04
repeat {
(abs(x^2 - a) > tol)
(x = 0.5 * (a/x + x))
if (all.equal(x^2, a)) {
break
}
}
But I am getting some error message plus a wrong answer. In the end, a should nearly equal x ^ 2 but it doesn't yet. I know there is something wrong with the all.equal portion, but I'm trying to figure out how to break the loop once they are close enough.
Thank you for any suggestions.
Don't use all.equal at all.
## trying to find `sqrt(10)`
x <- 2
a <- 10
tol <- 1e-10
repeat{
x <- 0.5 * (a / x + x)
if (abs(x * x - a) < tol) break
}
x
#[1] 3.162278

Solving a system of nonlinear equations in R

Suppose I have the following system of equations:
a * b = 5
sqrt(a * b^2) = 10
How can I solve these equations for a and b in R ?
I guess this problem can be stated as an optimisation problem, with the following function... ?
fn <- function(a, b) {
rate <- a * b
shape <- sqrt(a * b^2)
return(c(rate, shape) )
}
In a comment the poster specifically asks about using solve and optim so we show how to solve this (1) by hand, (2) using solve, (3) using optim and (4) a fixed point iteration.
1) by hand First note that if we write a = 5/b based on the first equation and substitute that into the second equation we get sqrt(5/b * b^2) = sqrt(5 * b) = 10 so b = 20 and a = 0.25.
2) solve Regarding the use of solve these equations can be transformed into linear form by taking the log of both sides giving:
log(a) + log(b) = log(5)
0.5 * (loga + 2 * log(b)) = log(10)
which can be expressed as:
m <- matrix(c(1, .5, 1, 1), 2)
exp(solve(m, log(c(5, 10))))
## [1] 0.25 20.00
3) optim Using optim we can write this where fn is from the question. fn2 is formed by subtracting off the RHS of the equations and using crossprod to form the sum of squares.
fn2 <- function(x) crossprod( fn(x[1], x[2]) - c(5, 10))
optim(c(1, 1), fn2)
giving:
$par
[1] 0.2500805 19.9958117
$value
[1] 5.51508e-07
$counts
function gradient
97 NA
$convergence
[1] 0
$message
NULL
4) fixed point For this one rewrite the equations in a fixed point form, i.e. in the form c(a, b) = f(c(a, b)) and then iterate. In general, there will be several ways to do this and not all of them will converge but in this case this seems to work. We use starting values of 1 for both a and b and divide both side of the first equation by b to get the first equation in fixed point form and we divide both sides of the second equation by sqrt(a) to get the second equation in fixed point form:
a <- b <- 1 # starting values
for(i in 1:100) {
a = 5 / b
b = 10 / sqrt(a)
}
data.frame(a, b)
## a b
## 1 0.25 20
Use this library.
library("nleqslv")
You need to define the multivariate function you want to solve for.
fn <- function(x) {
rate <- x[1] * x[2] - 5
shape <- sqrt(x[1] * x[2]^2) - 10
return(c(rate, shape))
}
Then you're good to go.
nleqslv(c(1,5), fn)
Always look at the detailed results. Numerical calculations can be tricky. In this case I got this:
Warning message:
In sqrt(x[1] * x[2]^2) : NaNs produced
That just means the procedure searched a region that included x[1] < 0 and then presumably noped the heck back to the right hand side of the plane.

Computing geometric series in R

I would like to compute:
$\sum_{j=1}^n r^j$ for $n=10, 20, 30, 40$, where $r=1.08$
http://quicklatex.com/cache3/76/ql_b64b957d43a0d6a93418cb18eb752576_l3.png
and to see the answers as a vector. I'm working with R; could anyone is able to explain to me how to do this?
So you are playing with power series. You may do:
r <- 1.08 ## this will be a divergent series, toward `Inf`
rr <- r^(1:40)
cumsum(rr)[1:4 * 10]
# [1] 15.64549 49.42292 122.34587 279.78104
The theoretical value is
## define a function
f <- function (n, r) r * (1 - r ^ n) / (1 - r)
## call this function
f(1:4 * 10, 1.08)
# [1] 15.64549 49.42292 122.34587 279.78104
Note, the theoretical result is not (1 - r ^ (n + 1)) / (1 - r), as you start summation from j = 1 instead of j = 0.
The value of r is unstated and I guessing that the formula being requested is not really the correct solution to a compound interest problem, but here is one answer to the question as currently posed:
r = 5.3; for (n in c(10,20,30,40) ) print( sum( r^(1:n) ) )
[1] 21555896
[1] 3.769856e+14
[1] 6.593006e+21
[1] 1.153034e+29
Perhaps (if I interpreted the latex right):
library(purrr)
r <- 1.08
map_dbl(seq(10, 40, 10), function(n) {
sum(r^(1:n))
})
Using only for loop and getting output as a vector:
out=c();
for(i in c(10,20,30,40))
{sum=0;
for(j in 1:i)
{sum=sum+1.08^j};
out=c(out,sum)};
out
Output:
[1] 15.64549 49.42292 122.34587 279.78104
Or:
> out=c();
> for(i in c(10,20,30,40))
+ out=c(out,sum(1.08^(1:i)))
> out
[1] 15.64549 49.42292 122.34587 279.78104
or, in R way:
> sapply(seq(10,40,10), function(x) sum(1.08^(1:x)))
[1] 15.64549 49.42292 122.34587 279.78104

Resources