I have found the yield of a crop (Y) as a function of its nitrogen offtake (U) i.e., Y(U).
The rest of the values for this particular crop are:
Y_crit | U_crit | Q | p | U_max | Y |
---|---|---|---|---|---|
12327.9 | 123.2790 | 57.14286 | 0.75 | 198.38 | 14170 |
I want to solve for U.
I tried solving this using a binary search algorithm, using the uniroot() and polyroot(), all to no avail :(
I tried defining it as
fn <- function(U)
{
Y - Y_crit - Q * (U-U_Crit) ((Q/(p 1)) * ((U - U_crit)/(U_max - U_crit))^(p 1) * (U_max - U_crit)
}
U <- polyroot(fn)
print(U)
but it says: "Error in polyroot(fn) : unimplemented type 'closure' in 'polyroot'"
Please help. TIA!
EDIT: I had first presented the value of Y as 14170 (=Y_max) but then confusing it with data for another crop, changed it to 11000. I have now changed it back.
CodePudding user response:
I have rewritten the function in order to make it more clear what it is computing, there is an error in the question's version (wrong parenthesis).
- Pass the arguments values as one object and in the function coerce it to list. This will make argument passing easier and less error prone;
- repeating terms are pre-computed and reused.
- I have plotted the function with values starting with
U = 123.79
, the value in the data.frame, until a visual inspection found an interval where the root is.
fn <- function(U, args) {
with(as.list(args), {
term1 <- U - U_crit
term2 <- U_max - U_crit
lhs <- Y_crit Q*term1 - Q/(p 1) * (term1/term2)^(p 1) * term2
rhs <- Y
return(lhs - rhs)
})
}
U <- uniroot(fn, c(123.279, 350), args = args)
U
#> $root
#> [1] 308.6662
#>
#> $f.root
#> [1] 0.0004746999
#>
#> $iter
#> [1] 7
#>
#> $init.it
#> [1] NA
#>
#> $estim.prec
#> [1] 6.103516e-05
curve(fn(x, args), 123.3, 350, lwd = 2)
abline(h = 0)
points(U$root, U$f.root, col = "red", pch = 19)
Created on 2022-12-22 with reprex v2.0.2
Edit
According to its documentation, package optimx
Provides a replacement and extension of the optim() function to call to several function minimization codes in R in a single statement.
But it only minimises the objective function, so write a wrapper around it, gn
below.
``` r
library(optimx)
gn <- function(x0, args) {
with(as.list(x0), {
args$Y <- Y
-fn(U, args)
})
}
x0 <- c(U = 124, Y = 10000)
optimx(par = x0, gn,
method = c("Nelder-Mead", "BFGS", "CG", "L-BFGS-B"),
args = args)
#> U Y value fevals gevals niter
#> Nelder-Mead 1.887090e 19 -7.002469e 34 -6.310914e 34 501 NA NA
#> BFGS 1.917764e 02 8.128266e 03 -6.026305e 03 100 100 NA
#> CG 1.983800e 02 9.853717e 03 -4.315391e 03 201 101 NA
#> L-BFGS-B NA NA 8.988466e 307 NA NA NA
#> convcode kkt1 kkt2 xtime
#> Nelder-Mead 1 TRUE FALSE 0.00
#> BFGS 1 TRUE FALSE 0.06
#> CG 1 TRUE FALSE 0.02
#> L-BFGS-B 9999 NA NA 0.01
optimx(par = x0, gn, method = c("BFGS", "CG"), args = args)
#> U Y value fevals gevals niter convcode kkt1 kkt2 xtime
#> BFGS 191.7764 8128.266 -6026.305 100 100 NA 1 TRUE FALSE 0.04
#> CG 198.3800 9853.717 -4315.391 201 101 NA 1 TRUE FALSE 0.02
Created on 2022-12-23 with reprex v2.0.2
The first run with 4 methods gives similar results for methods BFGS and CG. The second run keeps only these two methods.
The function's values are the symmetric of the values in column value
.
Data
Here is the posted arguments data set as copy&paste able code.
args <- "Y_crit U_crit Q p U_max Y
12327.9 123.2790 57.14286 0.75 198.38 11000"
args <- read.table(textConnection(args), header = TRUE)
Created on 2022-12-22 with reprex v2.0.2