mlr-org / ParamHelpers

Helpers for parameters in black-box optimization, tuning and machine learning.
https://paramhelpers.mlr-org.com
Other
25 stars 9 forks source link

could not find function "discreteNameToValue" #191

Closed rcannood closed 6 years ago

rcannood commented 6 years ago

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

jakob-r commented 6 years ago

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")
rcannood commented 6 years ago

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" 
jakob-r commented 6 years ago

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)
rcannood commented 6 years ago

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

rcannood commented 6 years ago

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?

jakob-r commented 6 years ago

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?

jakob-r commented 6 years ago

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

rcannood commented 6 years ago

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

rcannood commented 6 years ago

@berndbischl Could you please have a look at this?