automl / ConfigSpace

Domain specific language for configuration spaces in Python. Useful for hyperparameter optimization and algorithm configuration.
https://automl.github.io/ConfigSpace/
Other
202 stars 93 forks source link

Duplicate forbiddens in ConfigurationSpace #354

Open aron-bram opened 5 months ago

aron-bram commented 5 months ago

I noticed it was possible to add the same forbidden clause multiple times to the same space. Not sure if this is intended or not, so I thought I would raise a quick issue for it.

Here is how to replicate it:

import ConfigSpace as CS
import ConfigSpace.hyperparameters as CSH

cs = CS.ConfigurationSpace()

lower_bound = CSH.UniformIntegerHyperparameter('lower_bound', lower=0, upper=10)
upper_bound = CSH.UniformIntegerHyperparameter('upper_bound', lower=0, upper=10)

cs.add_hyperparameter(lower_bound)
cs.add_hyperparameter(upper_bound)

# add duplicate forbiddens to the same space
fgt1 = CS.ForbiddenGreaterThanRelation(lower_bound, upper_bound)
fgt2 = CS.ForbiddenGreaterThanRelation(lower_bound, upper_bound)
fgt3 = CS.ForbiddenGreaterThanRelation(lower_bound, upper_bound)

cs.add_forbidden_clause(fgt1)
cs.add_forbidden_clause(fgt2)
cs.add_forbidden_clause(fgt2)

print(cs)

What it outputs:

Configuration space object:
  Hyperparameters:
    lower_bound, Type: UniformInteger, Range: [0, 10], Default: 5
    upper_bound, Type: UniformInteger, Range: [0, 10], Default: 5
  Forbidden Clauses:
    Forbidden: lower_bound > upper_bound
    Forbidden: lower_bound > upper_bound
    Forbidden: lower_bound > upper_bound

Notice how the same forbidden appears 3 times.

eddiebergman commented 2 months ago

Hmmm, good find. It's not really problematic in the sense that it causes logical issue, however it could make sampling a bit slower if you need to generate large amount of samples, fast.

What would you expect the behavior be? I have 3 different ideas:

(classifier== 'adaboost' && preprocessor== 'densifier'),
(classifier== 'adaboost' && preprocessor== 'kitchen_sinks'),
(classifier== 'adaboost' && preprocessor == 'nystroem_sampler')
(classifier== 'adaboost'
&& preprocessor in ('nystroem_sampler', 'kitchen_sinks', 'densifier'))