fnchk.Rdfnchk checks a user-provided R function, ffn.
fnchk(xpar, ffn, trace=0, ... )fnchk attempts to discover various errors in function setup in user-supplied
functions primarily intended for use in optimization calculations. There are always
more conditions that could be tested!
The output is a list consisting of list(fval=fval, infeasible=infeasible, excode=excode, msg=msg)
The calculated value of the function at parameters xpar if the function
can be evaluated.
FALSE if the function can be evaluated, TRUE if not.
An exit code, which has a relationship to
A text string giving information about the result of the function check: Messages and
the corresponding values of excode are:
excode = 0;
infeasible = FALSE
excode = -1; infeasible = TRUE
excode = -4; infeasible = TRUE
excode = -4; infeasible = TRUE
excode = -4; infeasible = TRUE
excode = -4; infeasible = TRUE
excode = -4; infeasible = TRUE
excode = 0;excode = -1; infeasible = TRUE
excode = -1; infeasible = TRUE
# Want to illustrate each case.
# Ben Bolker idea for a function that is NOT scalar
# rm(list=ls())
# library(optimx)
sessionInfo()
#> R version 4.4.1 (2024-06-14)
#> Platform: x86_64-pc-linux-gnu
#> Running under: Ubuntu 22.04.5 LTS
#>
#> Matrix products: default
#> BLAS: /usr/lib/x86_64-linux-gnu/openblas-pthread/libblas.so.3
#> LAPACK: /usr/lib/x86_64-linux-gnu/openblas-pthread/libopenblasp-r0.3.20.so; LAPACK version 3.10.0
#>
#> locale:
#> [1] LC_CTYPE=en_US.UTF-8 LC_NUMERIC=C
#> [3] LC_TIME=en_US.UTF-8 LC_COLLATE=C
#> [5] LC_MONETARY=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8
#> [7] LC_PAPER=en_US.UTF-8 LC_NAME=C
#> [9] LC_ADDRESS=C LC_TELEPHONE=C
#> [11] LC_MEASUREMENT=en_US.UTF-8 LC_IDENTIFICATION=C
#>
#> time zone: Etc/UTC
#> tzcode source: system (glibc)
#>
#> attached base packages:
#> [1] stats graphics grDevices utils datasets methods base
#>
#> other attached packages:
#> [1] numDeriv_2016.8-1.1 optimx_2025-4.9
#>
#> loaded via a namespace (and not attached):
#> [1] ucminf_1.2.2 compiler_4.4.1 marqLevAlg_2.0.8 Rcpp_1.1.0
#> [5] xml2_1.4.0 parallel_4.4.1 dfoptim_2023.1.0 systemfonts_1.2.3
#> [9] textshaping_1.0.1 yaml_2.3.10 fastmap_1.2.0 R6_2.6.1
#> [13] curl_7.0.0 httr2_1.2.1 knitr_1.50 iterators_1.0.14
#> [17] subplex_1.9 tibble_3.3.0 nloptr_2.2.1 desc_1.4.3
#> [21] minqa_1.2.8 pillar_1.11.0 rlang_1.1.6 cachem_1.1.0
#> [25] BB_2019.10-1 xfun_0.53 fs_1.6.6 quadprog_1.5-8
#> [29] doParallel_1.0.17 memoise_2.0.1 cli_3.6.5 pkgdown_2.1.3
#> [33] withr_3.0.2 magrittr_2.0.3 lbfgs_1.2.1.2 foreach_1.5.2
#> [37] digest_0.6.37 rappdirs_0.3.3 lbfgsb3c_2024-3.5 lifecycle_1.0.4
#> [41] vctrs_0.6.5 downlit_0.4.4 evaluate_1.0.4 pracma_2.4.4
#> [45] glue_1.8.0 whisker_0.4.1 codetools_0.2-20 ragg_1.4.0
#> [49] fansi_1.0.6 rmarkdown_2.29 purrr_1.1.0 tools_4.4.1
#> [53] pkgconfig_2.0.3 htmltools_0.5.8.1
benbad<-function(x, y){
# y may be provided with different structures
f<-(x-y)^2
} # very simple, but ...
y<-1:10
x<-c(1)
cat("fc01: test benbad() with y=1:10, x=c(1)\n")
#> fc01: test benbad() with y=1:10, x=c(1)
fc01<-fnchk(x, benbad, trace=4, y)
#> fnchk: ffn =
#> function (x, y)
#> {
#> f <- (x - y)^2
#> }
#> <environment: 0x5577aa5b1280>
#> fnchk: xpar:[1] 1
#> fnchk: dots:[[1]]
#> [1] 1 2 3 4 5 6 7 8 9 10
#>
#> about to call ffn(xpar, ...)
#> ffn:function (x, y)
#> {
#> f <- (x - y)^2
#> }
#> <environment: 0x5577aa5b1280>
#> xpar & dots:[1] 1
#> [[1]]
#> [1] 1 2 3 4 5 6 7 8 9 10
#>
#> test in fnchk: [1] 0 1 4 9 16 25 36 49 64 81
#> Function value at supplied parameters = [1] 0 1 4 9 16 25 36 49 64 81
#> num [1:10] 0 1 4 9 16 25 36 49 64 81
#> NULL
#> [1] TRUE
#> Function evaluation returns a vector not a scalar
#> Function evaluation returned non-numeric value
#> Function evaluation returned Inf or NA (non-computable)
#> Function at given point= NA
print(fc01)
#> $fval
#> [1] NA
#>
#> $infeasible
#> [1] TRUE
#>
#> $excode
#> [1] -1
#>
#> $msg
#> [1] "Function evaluation returned Inf or NA (non-computable)"
#>
y<-as.vector(y)
cat("fc02: test benbad() with y=as.vector(1:10), x=c(1)\n")
#> fc02: test benbad() with y=as.vector(1:10), x=c(1)
fc02<-fnchk(x, benbad, trace=1, y)
#> Function value at supplied parameters = [1] 0 1 4 9 16 25 36 49 64 81
#> num [1:10] 0 1 4 9 16 25 36 49 64 81
#> NULL
#> [1] TRUE
#> Function evaluation returns a vector not a scalar
#> Function evaluation returned non-numeric value
#> Function evaluation returned Inf or NA (non-computable)
#> Function at given point= NA
print(fc02)
#> $fval
#> [1] NA
#>
#> $infeasible
#> [1] TRUE
#>
#> $excode
#> [1] -1
#>
#> $msg
#> [1] "Function evaluation returned Inf or NA (non-computable)"
#>
y<-as.matrix(y)
cat("fc03: test benbad() with y=as.matrix(1:10), x=c(1)\n")
#> fc03: test benbad() with y=as.matrix(1:10), x=c(1)
fc03<-fnchk(x, benbad, trace=1, y)
#> Function value at supplied parameters = [,1]
#> [1,] 0
#> [2,] 1
#> [3,] 4
#> [4,] 9
#> [5,] 16
#> [6,] 25
#> [7,] 36
#> [8,] 49
#> [9,] 64
#> [10,] 81
#> num [1:10, 1] 0 1 4 9 16 25 36 49 64 81
#> NULL
#> [1] FALSE
#> Function evaluation returns a matrix list not a scalar
#> Function evaluation returned non-numeric value
#> Function evaluation returned Inf or NA (non-computable)
#> Function at given point= NA
print(fc03)
#> $fval
#> [1] NA
#>
#> $infeasible
#> [1] TRUE
#>
#> $excode
#> [1] -1
#>
#> $msg
#> [1] "Function evaluation returned Inf or NA (non-computable)"
#>
y<-as.array(y)
cat("fc04: test benbad() with y=as.array(1:10), x=c(1)\n")
#> fc04: test benbad() with y=as.array(1:10), x=c(1)
fc04<-fnchk(x, benbad, trace=1, y)
#> Function value at supplied parameters = [,1]
#> [1,] 0
#> [2,] 1
#> [3,] 4
#> [4,] 9
#> [5,] 16
#> [6,] 25
#> [7,] 36
#> [8,] 49
#> [9,] 64
#> [10,] 81
#> num [1:10, 1] 0 1 4 9 16 25 36 49 64 81
#> NULL
#> [1] FALSE
#> Function evaluation returns a matrix list not a scalar
#> Function evaluation returned non-numeric value
#> Function evaluation returned Inf or NA (non-computable)
#> Function at given point= NA
print(fc04)
#> $fval
#> [1] NA
#>
#> $infeasible
#> [1] TRUE
#>
#> $excode
#> [1] -1
#>
#> $msg
#> [1] "Function evaluation returned Inf or NA (non-computable)"
#>
y<-"This is a string"
cat("test benbad() with y a string, x=c(1)\n")
#> test benbad() with y a string, x=c(1)
fc05<-fnchk(x, benbad, trace=1, y)
#> Error in x - y : non-numeric argument to binary operator
#> Function value at supplied parameters =[1] NA
#> attr(,"inadmissible")
#> [1] TRUE
#> logi NA
#> - attr(*, "inadmissible")= logi TRUE
#> NULL
#> [1] FALSE
#> Function evaluation returns INADMISSIBLE
#> Function evaluation returned non-numeric value
#> Function evaluation returned Inf or NA (non-computable)
#> Function at given point= NA
print(fc05)
#> $fval
#> [1] NA
#>
#> $infeasible
#> [1] TRUE
#>
#> $excode
#> [1] -1
#>
#> $msg
#> [1] "Function evaluation returned Inf or NA (non-computable)"
#>
cat("fnchk with Rosenbrock\n")
#> fnchk with Rosenbrock
fr <- function(x) { ## Rosenbrock Banana function
x1 <- x[1]
x2 <- x[2]
100 * (x2 - x1 * x1)^2 + (1 - x1)^2
}
xtrad<-c(-1.2,1)
ros1<-fnchk(xtrad, fr, trace=1)
#> Function value at supplied parameters =[1] 24.2
#> num 24.2
#> NULL
#> [1] TRUE
#> Function at given point= 24.2
print(ros1)
#> $fval
#> [1] 24.2
#>
#> $infeasible
#> [1] FALSE
#>
#> $excode
#> [1] 0
#>
#> $msg
#> [1] "fnchk OK"
#>
npar<-2
opros<-list2env(list(fn=fr, gr=NULL, hess=NULL, MAXIMIZE=FALSE, PARSCALE=rep(1,npar), FNSCALE=1,
KFN=0, KGR=0, KHESS=0, dots=NULL))
uros1<-fnchk(xtrad, fr, trace=1)
#> Function value at supplied parameters =[1] 24.2
#> num 24.2
#> NULL
#> [1] TRUE
#> Function at given point= 24.2
print(uros1)
#> $fval
#> [1] 24.2
#>
#> $infeasible
#> [1] FALSE
#>
#> $excode
#> [1] 0
#>
#> $msg
#> [1] "fnchk OK"
#>