mlr-org/ParamHelpers

could not find function "discreteNameToValue"

Closed this issue · 9 comments

Minimum reproducible example:

par_set <- ParamHelpers::makeParamSet(
  ParamHelpers::makeDiscreteParam(id = "method", values = "A"),
  ParamHelpers::makeIntegerParam(id = "lower", lower = 2, upper = 15),
  ParamHelpers::makeIntegerParam(id = "upper", lower = 2, upper = 15),
  forbidden = quote(lower > upper)
)
ParamHelpers::generateDesign(10, par_set)

Results in:

 Error in discreteNameToValue(list(id = "method", type = "discrete", len = 1L,  : 
  could not find function "discreteNameToValue" 

The problem occurs at src/c_dfRowsToList.c#L19, only when there is both a DiscreteParam and a forbidden region in my ParamSet. Removing either the second line or the fifth line from the example stops the error from happening.

I would very much like this issue to be solved because it hinders me from using the package as part of my own package, unless I list "ParamHelpers" under the DEPENDS: section in my DESCRIPTION, which I would very much like to avoid.

Kind regards,
Robrecht

At the moment I am not entirely sure how to fix it the best way in ParamHelpers but there is a tiny workaround you can use until we fix it.
Just put this before you call generateDesign.

discreteNameToValue = utils::getFromNamespace(x = "discreteNameToValue", ns = "ParamHelpers")

Thanks for the quick response!
Unfortunately, when part of a function, this does not solve my problem.

fun <- function() {
  discreteNameToValue <- utils::getFromNamespace(x = "discreteNameToValue", ns = "ParamHelpers")
  par_set <- ParamHelpers::makeParamSet(
    ParamHelpers::makeDiscreteParam(id = "method", values = "A"),
    ParamHelpers::makeIntegerParam(id = "lower", lower = 2, upper = 15),
    ParamHelpers::makeIntegerParam(id = "upper", lower = 2, upper = 15),
    forbidden = quote(lower > upper)
  )
  ParamHelpers::generateDesign(10, par_set)
}
fun()
Error in discreteNameToValue(list(id = "method", type = "discrete", len = 1L,  : 
  could not find function "discreteNameToValue" 

Although this still does not fix the root of the problem another way to solve it, is to use the preferred (according to ?makeParamSet/forbidden) version of putting constraints:

par_set <- ParamHelpers::makeParamSet(
    ParamHelpers::makeDiscreteParam(id = "method", values = "A"),
    ParamHelpers::makeIntegerParam(id = "lower", lower = 2, upper = 15),
    ParamHelpers::makeIntegerParam(id = "upper", lower = 2, upper = 15, requires = expression(upper > lower))
  )
ParamHelpers::generateDesign(10, par_set)

Aha! This is even more intuitive to work with! Thanks!

Unfortunately, the two don't appear to return quite the same output. For brevity's sake, I've dropped all the ParamHelpers:: from the code:

With forbiddens:

par_set <- makeParamSet(
  makeDiscreteParam(id = "method", values = "A"),
  makeIntegerParam(id = "lower", lower = 2, upper = 15),
  makeIntegerParam(id = "upper", lower = 2, upper = 15),
  forbidden = quote(lower > upper)
)
generateDesign(10, par_set)
   method lower upper
1       A     9    10
2       A     6    12
3       A     2     6
5       A    14    15
9       A     5    13
11      A     4    10
21      A     8    15
51      A     3    11
12      A    11    11
22      A     4     5

With requires:

par_set <- makeParamSet(
  makeDiscreteParam(id = "method", values = "A"),
  makeIntegerParam(id = "lower", lower = 2, upper = 15),
  makeIntegerParam(id = "upper", lower = 2, upper = 15, requires = expression(upper > lower))
)
generateDesign(10, par_set)
   method lower upper
1       A     3     5
2       A    13    NA
3       A     6    11
4       A    11    15
5       A    15    NA
6       A    12    NA
7       A     4    NA
8       A    10    NA
9       A     8    NA
10      A     5     9

When I use the second solution, I run into a lot of problems with mlrMBO which does not expect NA's to occur in the parameter listings. Is this expected behaviour?

Dang, indeed the meaning of these two is different. The first way (your example) means that this region is not valid. The second way (my last proposal) means that upper can just exist, with values bigger then lower but also that values of lower can exist "on their own". This is obviously not want we want in your context. So I have to hand over to @berndbischl if he can check the C code. Maybe @mllg could help?

We have PR #192 now. @berndbischl Do you want a test? Can we do a test?

Is the PR #192 already tested? I'm looking forward to this issue being fixed :)

@berndbischl Could you please have a look at this?