Computing geometric series in R - 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

Related

solving a simple (?) system of nonlinear equations

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.

Solving an algebraic equation

I'm trying to solve this equation: ((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) =1
Is there a way to do this with R?
ATTEMPT with incorrect solution:
library(Ryacas)
eq <- "((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 "
# simplify the equation:
library(glue)
yac_str(glue("Simplify({eq})"))
library(evaluate)
evaluate(eq,list(x=c(0,1,10,100,-100)))
evaluate() just returns the equation:
"((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 "
The answer for the equation is −2004200
It sounds like you want to Solve() for x rather than merely simplifying ... ? The following code solves the equation, strips off the x== from the solution, and evaluates the expression:
eq2 <- gsub("x==","",yac_str(glue("Solve({eq},x)")))
[1] "{(-0.80168e6)/0.4}"
eval(parse(text=eq2))
[1] -2004200
1) Ryacas Use the Ryacas package solve as shown below. (Thanks to #mikldk for improvement to last line.)
library(Ryacas)
eq <- "((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 " # from question
res <- solve(ysym(eq), "x")
as_r(y_rmvars(res)) # extract and convert to R
## [1] -2004200
if eq has R variables in it, here h is referenced in eq2, then use eval to evaluate the result.
h <- 2300
eq2 <- "((h+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 " # from question
res2 <- solve(ysym(eq2), "x")
eval(as_r(y_rmvars(res2)))
## [1] -2004200
2) Ryacas0 or using eq from above with the Ryacas0 package:
library(Ryacas0)
res <- Solve(eq, "x")
eval(Expr(res)[[1:3]]) # convert to R
## [1] -2004200
3a) Base R In light of the fact that this is a linear equation and the solution to the following where A is the slope and B is the intercept:
A * x + B = 0
is
x = - B / A
if we replace x with the imaginary 1i and then move the rhs to the lhs we have that B and A are the real and imaginary parts of that expression. No packages are used.
r <- eval(parse(text = sub("==", "-", eq)), list(x = 1i))
-Re(r) / Im(r)
## [1] -2004200
3b) If we move the rhs to lhs then B equals it at x=0 and A equals the derivative wrt x so another base R solution would be:
e <- parse(text = sub("==", "-", eq))
- eval(e, list(x = 0)) / eval(D(e, "x"))
## [1] -200420
Here is a base R solution.
Rewrite the equation in the form of a function, use curve to get two end points where the function has different signs and put uniroot to work.
f <- function(x) ((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) - 1
curve(f, -1e7, 1)
uniroot(f, c(-1e7, 1))
#$root
#[1] -2004200
#
#$f.root
#[1] 0
#
#$iter
#[1] 1
#
#$init.it
#[1] NA
#
#$estim.prec
#[1] 7995800
Following the discussion in the comments to the question, here is a general solution. The function whose roots are to be found now accepts an argument params in order to pass the values of rent, salary, number of workers, price, unit cost and capital cost. This argument must be a named list.
f <- function(x, K = 1, params) {
A <- with(params, rent + salary*workers)
with(params, (A + (x + A)*capitalcost)/(price - unitcost) - K)
}
params <- list(
rent = 2300,
salary = 1900,
workers = 1,
price = 600,
unitcost = 400,
capitalcost = 0.002
)
curve(f(x, params = params), -1e7, 1)
uniroot(f, c(-1e7, 1), params = params)
If you want something quick: rootSolve library is your go-to.
library(rootSolve)
func_ <- function(x) ((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400)-1
uniroot.all(func_, c(-1e9, 1e9))
[1] -2004200
Note that most of the time reducing the interval is better.
If you will maintain the same structure, then in Base R, you could do:
solveX <- function(eq){
U <- function(x)abs(eval(parse(text = sub("=+","-", eq)), list(x=x)))
optim(0, U, method = "L-BFGS-B")$par
}
eq <- "((2300+1900*1)+(x+2300+1900*1)*0.002)/(600-400) ==1 "
solveX(eq)
[1] -2004200

R: solving for a variable

I wonder if there's any function that can solve for a variable in an equation in terms of other values.
For example, I have:
(a-1/3)/(a+b-2/3)==0.3
The output of this function should be:
(0.3*b+0.1333333)/(0.7)
Or something along these lines.
Thank you
You can use Yacas through the Ryacas package:
library(Ryacas)
a <- Sym("a")
b <- Sym("b")
Solve((a-1/3)/(a+b-2/3)==0.3, a)
# Yacas vector:
# [1] a == -((-0.3 * b - 0.1333333333)/0.7)
To get the solution as an expression, do:
solution <- Solve((a-1/3)/(a+b-2/3)==0.3, a)
yacas(paste0("a Where ", solution))
# expression(-((-0.3 * b - 0.1333333333)/0.7))
You can define a function returning the solution in function of b as follows:
f <- function(b) {}
body(f) <- yacas(paste0("a Where ", solution))$text
f
# function (x)
# -((-0.3 * b - 0.1333333333)/0.7)
Also note that you do rational calculus to get exact values:
q1 <- Sym(1)/Sym(3)
q2 <- Sym(2)/Sym(3)
solution <- Solve((a-q1)/(a+b-q2)==0.3, a)
solution
# [1] a == -(3 * (-0.3 * b - 1.2/9)/2.1)
Simplify(solution)
# [1] a + (-0.9 * b/2.1 - 3.6/18.9) == 0

Summation of a sequence

If n(1) = 1 ,n(2) = 5, n(3) = 13, n(4) = 25, ...
I am using a for loop for summation of these terms
1 + (1*4 - 4) + (2*4 - 4) + (3*4 - 4) + ..
This is the function I am using with a for loop:
shapeArea <- function(n) {
terms <- as.numeric(1)
for(i in 1:n){
terms <- append(terms, (i*4 - 4))
}
sum(terms)
}
This works fine (as shown here):
> shapeArea(3)
[1] 13
> shapeArea(2)
[1] 5
> shapeArea(4)
[1] 25
Yet I was also thinking how can I do this without saving the terms of the series in numeric vector terms. In other words is there a way to find summations of terms without saving them in a vector first. Or is this the efficient way to do this.
Thanks
You can change your shapeArea function to a one-liner
shapeArea <- function(num) {
1 + sum(seq(num) * 4) - (4 * num)
}
shapeArea(1)
#[1] 1
shapeArea(2)
#[1] 5
shapeArea(3)
#[1] 13
shapeArea(4)
#[1] 25

Use IFELSE in a function

I am having a problem implementing the ifelse command. I would like to return only positives (or 0) outputs. For example, in the following equation y=-50+(x^2), when y<=0, y should return 0. When y>0 it should return the proper output value. When I implement the following code:
test = function (x) 50+(x^2)
if(test <= 0) test <- 0 else y <-50+(x^2)
I always obtain 0.
A possible solution:
test <- function(x) (x ^ 2 > 50) * (x ^ 2 - 50)
test(5)
# [1] 0
test(10)
# [1] 50
Another approach:
test2 <- function(x) pmax(0, x ^ 2 - 50)
One solution
test = function(x) ifelse(0>(-50+x^2), 0, -50+x^2)
test(10)
[1] 50
test(100)
[1] 9950

Resources