@@ -13,6 +13,14 @@ infillOptFocus = function(infill.crit, models, control, par.set, opt.path, desig
13
13
for (restart.iter in seq_len(control $ infill.opt.restarts )) {
14
14
# copy parset so we can shrink it
15
15
ps.local = par.set
16
+
17
+ # handle discrete vectors:
18
+ # The problem is that for discrete vectors, we can't adjust the values dimension-wise.
19
+ # Therefore, for discrete vectors, we always drop the last level and instead have a
20
+ # mapping that maps, for each discrete vector param and for each dimension, from
21
+ # the sampled value (levels 1 to n - #(dropped levels)) to levels with random dropouts.
22
+ discreteVectorMapping = lapply(filterParams(par.set , type = c(" discretevector" , " logicalvector" ))$ pars ,
23
+ function (param ) rep(list (setNames(names(param $ values ), names(param $ values ))), param $ len ))
16
24
17
25
# do iterations where we focus the region-of-interest around the current best point
18
26
for (local.iter in seq_len(control $ infill.opt.focussearch.maxit )) {
@@ -21,13 +29,22 @@ infillOptFocus = function(infill.crit, models, control, par.set, opt.path, desig
21
29
22
30
# convert to param encoding our model was trained on and can use
23
31
newdesign = convertDataFrameCols(newdesign , ints.as.num = TRUE , logicals.as.factor = TRUE )
24
- y = infill.crit(newdesign , models , control , ps.local , design , iter , ... )
32
+
33
+ # handle discrete vectors
34
+ for (dvparam in filterParams(par.set , type = c(" discretevector" , " logicalvector" ))$ pars ) {
35
+ for (dimnum in seq_len(dvparam $ len )) {
36
+ dfindex = paste0(dvparam $ id , dimnum )
37
+ mapping = discreteVectorMapping [[dvparam $ id ]][[dimnum ]]
38
+ levels(newdesign [[dfindex ]]) = mapping [levels(newdesign [[dfindex ]])]
39
+ }
40
+ }
41
+ y = infill.crit(newdesign , models , control , par.set , design , iter , ... )
25
42
26
43
# get current best value
27
44
local.index = getMinIndex(y , ties.method = " random" )
28
45
local.y = y [local.index ]
29
46
local.x.df = newdesign [local.index , , drop = FALSE ]
30
- local.x.list = dfRowToList(recodeTypes(local.x.df , ps.local ), ps.local , 1 )
47
+ local.x.list = dfRowToList(recodeTypes(local.x.df , par.set ), par.set , 1 )
31
48
32
49
# if we found a new best value, store it
33
50
if (local.y < global.y ) {
@@ -39,24 +56,46 @@ infillOptFocus = function(infill.crit, models, control, par.set, opt.path, desig
39
56
ps.local $ pars = lapply(ps.local $ pars , function (par ) {
40
57
# only shrink when there is a value
41
58
val = local.x.list [[par $ id ]]
42
- if (! isScalarNA(val )) {
43
- if (isNumeric(par )) {
44
- # shrink to range / 2, centered at val
45
- range = par $ upper - par $ lower
46
- par $ lower = pmax(par $ lower , val - (range / 4 ))
47
- par $ upper = pmin(par $ upper , val + (range / 4 ))
48
- if (isInteger(par )) {
49
- par $ lower = floor(par $ lower )
50
- par $ upper = ceiling(par $ upper )
59
+ if (isScalarNA(val )) {
60
+ return (par )
61
+ }
62
+ if (isNumeric(par )) {
63
+ # shrink to range / 2, centered at val
64
+ range = par $ upper - par $ lower
65
+ par $ lower = pmax(par $ lower , val - (range / 4 ))
66
+ par $ upper = pmin(par $ upper , val + (range / 4 ))
67
+ if (isInteger(par )) {
68
+ par $ lower = floor(par $ lower )
69
+ par $ upper = ceiling(par $ upper )
70
+ }
71
+ } else if (isDiscrete(par )) {
72
+ # randomly drop a level, which is not val
73
+ if (length(par $ values ) < = 1L ) {
74
+ return (par )
75
+ }
76
+ # need to do some magic to handle discrete vectors
77
+ if (par $ type %nin % c(" discretevector" , " logicalvector" )) {
78
+ val.names = names(par $ values )
79
+ # remove current val from delete options, should work also for NA
80
+ val.names = val.names [! sapply(par $ values , identical , y = val )] # remember, 'val' may not even be a character
81
+ to.del = sample(val.names , 1 )
82
+ par $ values [to.del ] = NULL
83
+ } else {
84
+ # we remove the last element of par$values and a random element for
85
+ # each dimension in discreteVectorMapping.
86
+ par $ values = par $ values [- length(par $ values )]
87
+ if (par $ type != " logicalvector" ) {
88
+ # for discretevectorparam val would be a list; convert to character vector
89
+ val = names(val )
51
90
}
52
- } else if (isDiscrete (par )) {
53
- # randomly drop a level, which is not val
54
- if (length( par $ values ) > 1L ) {
55
- val.names = names( par $ values )
56
- # remove current val from delete options, should work also for NA
57
- val.names = setdiff( val.names , val )
58
- to.del = sample(seq_along( val. names), 1 )
59
- par $ values = par $ values [ - to.del ]
91
+ for ( dimnum in seq_len (par $ len )) {
92
+ val.names = discreteVectorMapping [[ par $ id ]][[ dimnum ]]
93
+ newmap = val.names
94
+ val.names = val. names[ val.names != val [ dimnum ]]
95
+ to.del = sample( val.names , 1 )
96
+ newmap = newmap [ newmap != to.del ]
97
+ names( newmap ) = names( par $ values )
98
+ discreteVectorMapping [[ par $ id ]][[ dimnum ]] <<- newmap
60
99
}
61
100
}
62
101
}
0 commit comments