RIckHenr
RIckHenr

Reputation: 361

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

Upvotes: 3

Views: 290

Answers (5)

G. Grothendieck
G. Grothendieck

Reputation: 269905

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

Upvotes: 2

Rui Barradas
Rui Barradas

Reputation: 76615

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)

Upvotes: 1

Onyambu
Onyambu

Reputation: 79318

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

Upvotes: 0

tanglef
tanglef

Reputation: 116

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.

Upvotes: 1

Ben Bolker
Ben Bolker

Reputation: 226627

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

Upvotes: 2

Related Questions