Ejemplo n.º 1
0
    def test_and_conjunction(self):
        self.assertRaises(TypeError, AndConjunction, "String1", "String2")

        hp1 = CategoricalHyperparameter("input1", [0, 1])
        hp2 = CategoricalHyperparameter("input2", [0, 1])
        hp3 = CategoricalHyperparameter("input3", [0, 1])
        hp4 = Constant("And", "True")
        cond1 = EqualsCondition(hp4, hp1, 1)

        # Only one condition in an AndConjunction!
        self.assertRaises(ValueError, AndConjunction, cond1)

        cond2 = EqualsCondition(hp4, hp2, 1)
        cond3 = EqualsCondition(hp4, hp3, 1)

        andconj1 = AndConjunction(cond1, cond2)
        andconj1_ = AndConjunction(cond1, cond2)
        self.assertEqual(andconj1, andconj1_)

        andconj2 = AndConjunction(cond2, cond3)
        self.assertNotEqual(andconj1, andconj2)

        andconj3 = AndConjunction(cond1, cond2, cond3)
        self.assertEqual(
            "(And | input1 == 1 && And | input2 == 1 && And | "
            "input3 == 1)", str(andconj3))

        # Test __eq__
        self.assertNotEqual(andconj1, andconj3)
        self.assertNotEqual(andconj1, "String")
Ejemplo n.º 2
0
    def test_get_parents(self):
        # Necessary because we couldn't call cs.get_parents for
        # clasp-sat-params-nat.pcs
        counter = UniformIntegerHyperparameter('bump', 10, 4096, log=True)
        _1_S_countercond = CategoricalHyperparameter('cony', ['yes', 'no'])
        _1_0_restarts = CategoricalHyperparameter('restarts', ['F', 'L', 'D',
                                                               'x', '+', 'no'],
                                                  default_value='x')

        condition = EqualsCondition(counter, _1_S_countercond, 'yes')
        # All conditions inherit get_parents from abstractcondition
        self.assertEqual([_1_S_countercond], condition.get_parents())
        condition2 = InCondition(counter, _1_0_restarts, ['F', 'D', 'L', 'x', '+'])
        # All conjunctions inherit get_parents from abstractconjunction
        conjunction = AndConjunction(condition, condition2)
        self.assertEqual([_1_S_countercond, _1_0_restarts], conjunction.get_parents())
Ejemplo n.º 3
0
def _construct_and_condition(
    condition: Dict,
    cs: ConfigurationSpace,
) -> AndConjunction:
    conditions = [
        _construct_condition(cond, cs) for cond in condition['conditions']
    ]
    return AndConjunction(*conditions)
Ejemplo n.º 4
0
    def test_get_parents(self):
        # Necessary because we couldn't call cs.get_parents for
        # clasp-sat-params-nat.pcs
        counter = UniformIntegerHyperparameter('bump', 10, 4096, log=True)
        _1_S_countercond = CategoricalHyperparameter('cony', ['yes', 'no'])
        _1_0_restarts = CategoricalHyperparameter(
            'restarts', ['F', 'L', 'D', 'x', '+', 'no'], default='x')

        condition = EqualsCondition(counter, _1_S_countercond, 'yes')
        # All conditions inherit get_parents from abstractcondition
        self.assertEqual([_1_S_countercond], condition.get_parents())
        condition2 = InCondition(counter, _1_0_restarts,
                                 ['F', 'D', 'L', 'x', '+'])
        # All conjunctions inherit get_parents from abstractconjunction
        conjunction = AndConjunction(condition, condition2)
        self.assertEqual([_1_S_countercond, _1_0_restarts],
                         conjunction.get_parents())
Ejemplo n.º 5
0
def _build_and_conjunction(conjunction: AndConjunction) -> Dict:
    child = conjunction.get_descendant_literal_conditions()[0].child.name
    cond_list = list()
    for component in conjunction.components:
        cond_list.append(_build_condition(component))
    return {
        'child': child,
        'type': 'AND',
        'conditions': cond_list,
    }
Ejemplo n.º 6
0
    def test_all_components_have_the_same_child(self):
        hp1 = CategoricalHyperparameter("input1", [0, 1])
        hp2 = CategoricalHyperparameter("input2", [0, 1])
        hp3 = CategoricalHyperparameter("input3", [0, 1])
        hp4 = CategoricalHyperparameter("input4", [0, 1])
        hp5 = CategoricalHyperparameter("input5", [0, 1])
        hp6 = Constant("AND", "True")

        cond1 = EqualsCondition(hp1, hp2, 1)
        cond2 = EqualsCondition(hp1, hp3, 1)
        cond3 = EqualsCondition(hp1, hp4, 1)
        cond4 = EqualsCondition(hp6, hp4, 1)
        cond5 = EqualsCondition(hp6, hp5, 1)

        AndConjunction(cond1, cond2, cond3)
        AndConjunction(cond4, cond5)
        self.assertRaisesRegexp(
            ValueError, "All Conjunctions and Conditions must have "
            "the same child.", AndConjunction, cond1, cond4)
Ejemplo n.º 7
0
def _build_and_conjunction(conjunction: AndConjunction) -> Dict:
    child = conjunction.get_descendant_literal_conditions()[0].child.name
    cond_list = list()
    for component in conjunction.components:
        cond_list.append(_build_condition(component))
    return {
        'child': child,
        'type': 'AND',
        'conditions': cond_list,
    }
    def get_hyperparameter_search_space(**kwargs):
        cs = ConfigurationSpace()
        penalty = CategoricalHyperparameter("penalty", ["l1", "l2", "elasticnet", "none"], default_value='l2')
        solver = CategoricalHyperparameter("solver", ["newton-cg", "lbfgs", "liblinear", "sag", "saga"],
                                           default_value="lbfgs")
        dual = CategoricalHyperparameter("dual", choices=[True, False], default_value=False)
        tol = UniformFloatHyperparameter("tol", lower=1e-7, upper=100., default_value=1.0e-4, log=True)
        C = UniformFloatHyperparameter("C", lower=1e-7, upper=100., default_value=1.0, log=True)
        fit_intercept = CategoricalHyperparameter("fit_intercept", choices=[True, False], default_value=True)
        intercept_scaling = UniformFloatHyperparameter("intercept_scaling", lower=0.0001, upper=2.0, default_value=1.0,
                                                       log=True)
        max_iter = UniformIntegerHyperparameter("max_iter", lower=50, upper=10000, default_value=100)
        multi_class = CategoricalHyperparameter("multi_class", ["ovr", "multinomial", "auto"], default_value="auto")
        l1_ratio = UniformFloatHyperparameter("l1_ratio", lower=0., upper=1., default_value=0.1)

        l1_ratio_condition = InCondition(l1_ratio, penalty, ["elasticnet"])
        dual_condition = AndConjunction(InCondition(dual, penalty, ["l2"]), InCondition(dual, solver, ["liblinear"]))
        cs.add_hyperparameters([penalty, solver, dual, tol, C, fit_intercept, intercept_scaling, max_iter, multi_class,
                                l1_ratio])

        penaltyAndLbfgs = ForbiddenAndConjunction(
            ForbiddenEqualsClause(solver, "lbfgs"),
            ForbiddenInClause(penalty, ["l1", "elasticnet"])
        )
        penaltyAndNewton = ForbiddenAndConjunction(
            ForbiddenEqualsClause(solver, "newton-cg"),
            ForbiddenInClause(penalty, ["l1", "elasticnet"])
        )
        penaltyAndSag = ForbiddenAndConjunction(
            ForbiddenEqualsClause(solver, "sag"),
            ForbiddenInClause(penalty, ["l1", "elasticnet"])
        )
        penaltyAndSaga = ForbiddenAndConjunction(
            ForbiddenInClause(penalty, ["elasticnet"]),
            ForbiddenInClause(solver, ["newton-cg", "lbfgs", "sag"])
        )
        penaltyAndSagaa = ForbiddenAndConjunction(
            ForbiddenInClause(penalty, ["elasticnet", "none"]),
            ForbiddenInClause(solver, ["liblinear"])
        )
        penaltyAndSagaaa = ForbiddenAndConjunction(
            ForbiddenInClause(multi_class, ["multinomial"]),
            ForbiddenInClause(solver, ["liblinear"])
        )

        cs.add_forbidden_clause(penaltyAndLbfgs)
        cs.add_forbidden_clause(penaltyAndNewton)
        cs.add_forbidden_clause(penaltyAndSag)
        cs.add_forbidden_clause(penaltyAndSagaa)
        cs.add_forbidden_clause(penaltyAndSaga)
        cs.add_forbidden_clause(penaltyAndSagaaa)
        cs.add_condition(l1_ratio_condition)
        cs.add_condition(dual_condition)
        return cs
Ejemplo n.º 9
0
    def test_and_conjunction(self):
        self.assertRaises(TypeError, AndConjunction, "String1", "String2")

        hp1 = CategoricalHyperparameter("input1", [0, 1])
        hp2 = CategoricalHyperparameter("input2", [0, 1])
        hp3 = CategoricalHyperparameter("input3", [0, 1])
        hp4 = Constant("And", "True")
        cond1 = EqualsCondition(hp4, hp1, 1)

        # Only one condition in an AndConjunction!
        self.assertRaises(ValueError, AndConjunction, cond1)

        cond2 = EqualsCondition(hp4, hp2, 1)
        cond3 = EqualsCondition(hp4, hp3, 1)

        andconj1 = AndConjunction(cond1, cond2)
        andconj1_ = AndConjunction(cond1, cond2)
        self.assertEqual(andconj1, andconj1_)

        # Test setting vector idx
        hyperparameter_idx = {
            hp1.name: 0,
            hp2.name: 1,
            hp3.name: 2,
            hp4.name: 3
        }
        andconj1.set_vector_idx(hyperparameter_idx)
        self.assertEqual(andconj1.get_parents_vector(), [0, 1])
        self.assertEqual(andconj1.get_children_vector(), [3, 3])

        andconj2 = AndConjunction(cond2, cond3)
        self.assertNotEqual(andconj1, andconj2)

        andconj3 = AndConjunction(cond1, cond2, cond3)
        self.assertEqual("(And | input1 == 1 && And | input2 == 1 && And | "
                         "input3 == 1)", str(andconj3))

        # Test __eq__
        self.assertNotEqual(andconj1, andconj3)
        self.assertNotEqual(andconj1, "String")
Ejemplo n.º 10
0
    def test_nested_conjunctions(self):
        hp1 = CategoricalHyperparameter("input1", [0, 1])
        hp2 = CategoricalHyperparameter("input2", [0, 1])
        hp3 = CategoricalHyperparameter("input3", [0, 1])
        hp4 = CategoricalHyperparameter("input4", [0, 1])
        hp5 = CategoricalHyperparameter("input5", [0, 1])
        hp6 = Constant("AND", "True")

        cond1 = EqualsCondition(hp6, hp1, 1)
        cond2 = EqualsCondition(hp6, hp2, 1)
        cond3 = EqualsCondition(hp6, hp3, 1)
        cond4 = EqualsCondition(hp6, hp4, 1)
        cond5 = EqualsCondition(hp6, hp5, 1)

        conj1 = AndConjunction(cond1, cond2)
        conj2 = OrConjunction(conj1, cond3)
        conj3 = AndConjunction(conj2, cond4, cond5)

        # TODO: this does not look nice, And should depend on a large
        # conjunction, there should not be many ANDs inside this string!
        self.assertEqual("(((AND | input1 == 1 && AND | input2 == 1) || AND | "
                         "input3 == 1) && AND | input4 == 1 && AND | input5 "
                         "== 1)", str(conj3))
Ejemplo n.º 11
0
    def test_and_conjunction(self):
        self.assertRaises(TypeError, AndConjunction, "String1", "String2")

        hp1 = CategoricalHyperparameter("input1", [0, 1])
        hp2 = CategoricalHyperparameter("input2", [0, 1])
        hp3 = CategoricalHyperparameter("input3", [0, 1])
        hp4 = Constant("And", "True")
        cond1 = EqualsCondition(hp4, hp1, 1)

        # Only one condition in an AndConjunction!
        self.assertRaises(ValueError, AndConjunction, cond1)

        cond2 = EqualsCondition(hp4, hp2, 1)
        cond3 = EqualsCondition(hp4, hp3, 1)

        andconj1 = AndConjunction(cond1, cond2)
        andconj1_ = AndConjunction(cond1, cond2)
        self.assertEqual(andconj1, andconj1_)

        # Test setting vector idx
        hyperparameter_idx = {
            hp1.name: 0,
            hp2.name: 1,
            hp3.name: 2,
            hp4.name: 3
        }
        andconj1.set_vector_idx(hyperparameter_idx)
        self.assertEqual(andconj1.get_parents_vector(), [0, 1])
        self.assertEqual(andconj1.get_children_vector(), [3, 3])

        andconj2 = AndConjunction(cond2, cond3)
        self.assertNotEqual(andconj1, andconj2)

        andconj3 = AndConjunction(cond1, cond2, cond3)
        self.assertEqual(
            "(And | input1 == 1 && And | input2 == 1 && And | "
            "input3 == 1)", str(andconj3))

        # Test __eq__
        self.assertNotEqual(andconj1, andconj3)
        self.assertNotEqual(andconj1, "String")
    def test_write_AndConjunction_condition(self):
        expected = "lp '--lp ' c {mi,bo}\nls '--ls ' c {sa,ca,ny}\ntemp '--temp ' r (0.500000, 1.000000)|  ls  %in%  c(sa,ca)  &&  lp  %in%  c(bo)\n"

        temp = UniformFloatHyperparameter("temp", 0.5, 1)
        ls = CategoricalHyperparameter("ls", ["sa", "ca", "ny"], "sa")
        lp = CategoricalHyperparameter("lp", ["mi", "bo"], "bo")

        cs = ConfigurationSpace()
        cs.add_hyperparameter(temp)
        cs.add_hyperparameter(lp)
        cs.add_hyperparameter(ls)

        c1 = InCondition(temp, ls, ['sa','ca'])
        c2 = InCondition(temp, lp, ['bo'])
        c3 = AndConjunction(c1, c2)
        cs.add_condition(c3)
        value = irace.write(cs)
        self.assertEqual(expected, value)
Ejemplo n.º 13
0
    def get_hyperparameter_search_space(dataset_properties=None):
        """Get the configuratin space used for hyperparameter searching."""
        cs = ConfigurationSpace()
        conditions = []

        base_estimator = CategoricalHyperparameter(
            name="base_estimator",
            choices=["rf", "lr", "svc"],
            default_value="rf",
        )
        n_features_to_select = UniformIntegerHyperparameter(
            name="n_features_to_select", lower=1, upper=30, default_value=10)
        step = UniformFloatHyperparameter(name="step",
                                          lower=0.01,
                                          upper=0.25,
                                          default_value=0.1)

        # RF
        rf_n_estimators = UniformIntegerHyperparameter(name="rf_n_estimators",
                                                       lower=1,
                                                       upper=1000,
                                                       default_value=100)
        rf_criterion = CategoricalHyperparameter(
            name="rf_criterion",
            choices=["gini", "entropy"],
            default_value="gini",
        )
        rf_max_depth = UniformIntegerHyperparameter(name="rf_max_depth",
                                                    lower=1,
                                                    upper=100,
                                                    default_value=10)
        rf_class_weight = CategoricalHyperparameter(
            name="rf_class_weight",
            choices=["balanced", "balanced_subsample"],
            default_value="balanced_subsample",
        )
        conditions.append(
            EqualsCondition(rf_n_estimators, base_estimator, "rf"))
        conditions.append(EqualsCondition(rf_criterion, base_estimator, "rf"))
        conditions.append(EqualsCondition(rf_max_depth, base_estimator, "rf"))
        conditions.append(
            EqualsCondition(rf_class_weight, base_estimator, "rf"))

        # LR
        lr_C = UniformFloatHyperparameter(name="lr_C",
                                          lower=1.0e-3,
                                          upper=1.0e3,
                                          default_value=1.0,
                                          log=True)
        lr_penalty = CategoricalHyperparameter(name="lr_penalty",
                                               choices=["l1", "l2"],
                                               default_value="l2")
        lr_fit_intercept = CategoricalHyperparameter(name="lr_fit_intercept",
                                                     choices=[True, False],
                                                     default_value=True)
        lr_intercept_scaling = UniformFloatHyperparameter(
            name="lr_intercept_scaling",
            lower=1.0,
            upper=1.0e3,
            default_value=1.0,
        )
        lr_class_weight = CategoricalHyperparameter(
            name="lr_class_weight",
            choices=["balanced", "None"],
            default_value="balanced",
        )
        conditions.append(EqualsCondition(lr_C, base_estimator, "lr"))
        conditions.append(EqualsCondition(lr_penalty, base_estimator, "lr"))
        conditions.append(
            EqualsCondition(lr_fit_intercept, base_estimator, "lr"))
        conditions.append(
            AndConjunction(
                EqualsCondition(lr_intercept_scaling, base_estimator, "lr"),
                EqualsCondition(lr_intercept_scaling, lr_fit_intercept, True),
            ))
        conditions.append(
            EqualsCondition(lr_class_weight, base_estimator, "lr"))

        # SVC
        svc_C = UniformFloatHyperparameter(name="svc_C",
                                           lower=1.0e-3,
                                           upper=1.0e3,
                                           default_value=1.0,
                                           log=True)
        svc_penalty = CategoricalHyperparameter(name="svc_penalty",
                                                choices=["l1", "l2"],
                                                default_value="l2")
        svc_class_weight = CategoricalHyperparameter(
            name="svc_class_weight",
            choices=["balanced", "None"],
            default_value="balanced",
        )
        svc_loss = CategoricalHyperparameter(
            name="svc_loss",
            choices=["hinge", "squared_hinge"],
            default_value="squared_hinge",
        )
        svc_fit_intercept = CategoricalHyperparameter(name="svc_fit_intercept",
                                                      choices=[True, False],
                                                      default_value=True)
        conditions.append(EqualsCondition(svc_C, base_estimator, "svc"))
        conditions.append(EqualsCondition(svc_penalty, base_estimator, "svc"))
        conditions.append(
            EqualsCondition(svc_class_weight, base_estimator, "svc"))
        conditions.append(EqualsCondition(svc_loss, base_estimator, "svc"))
        conditions.append(
            EqualsCondition(svc_fit_intercept, base_estimator, "svc"))

        cs.add_hyperparameters([
            base_estimator,
            n_features_to_select,
            step,
            rf_n_estimators,
            rf_criterion,
            rf_max_depth,
            rf_class_weight,
            lr_C,
            lr_penalty,
            lr_fit_intercept,
            lr_intercept_scaling,
            lr_class_weight,
            svc_C,
            svc_penalty,
            svc_class_weight,
            svc_loss,
            svc_fit_intercept,
        ])
        for c in conditions:
            cs.add_condition(c)

        return cs
Ejemplo n.º 14
0
def read(pcs_string, debug=False):
    configuration_space = ConfigurationSpace()
    conditions = []
    forbidden = []

    # some statistics
    ct = 0
    cont_ct = 0
    cat_ct = 0
    line_ct = 0

    for line in pcs_string:
        line_ct += 1

        if "#" in line:
            # It contains a comment
            pos = line.find("#")
            line = line[:pos]

        # Remove quotes and whitespaces at beginning and end
        line = line.replace('"', "").replace("'", "")
        line = line.strip()

        if "|" in line:
            # It's a condition
            try:
                c = pp_condition.parseString(line)
                conditions.append(c)
            except pyparsing.ParseException:
                raise NotImplementedError("Could not parse condition: %s" %
                                          line)
            continue
        if "}" not in line and "]" not in line:
            continue
        if line.startswith("{") and line.endswith("}"):
            forbidden.append(line)
            continue
        if len(line.strip()) == 0:
            continue

        ct += 1
        param = None

        create = {
            "int": UniformIntegerHyperparameter,
            "float": UniformFloatHyperparameter,
            "categorical": CategoricalHyperparameter
        }

        try:
            param_list = pp_cont_param.parseString(line)
            il = param_list[9:]
            if len(il) > 0:
                il = il[0]
            param_list = param_list[:9]
            name = param_list[0]
            lower = float(param_list[2])
            upper = float(param_list[4])
            paramtype = "int" if "i" in il else "float"
            log = True if "l" in il else False
            default = float(param_list[7])
            param = create[paramtype](name=name,
                                      lower=lower,
                                      upper=upper,
                                      q=None,
                                      log=log,
                                      default=default)
            cont_ct += 1
        except pyparsing.ParseException:
            pass

        try:
            param_list = pp_cat_param.parseString(line)
            name = param_list[0]
            choices = [c for c in param_list[2:-4:2]]
            default = param_list[-2]
            param = create["categorical"](name=name,
                                          choices=choices,
                                          default=default)
            cat_ct += 1
        except pyparsing.ParseException:
            pass

        if param is None:
            raise NotImplementedError("Could not parse: %s" % line)

        configuration_space.add_hyperparameter(param)

    for clause in forbidden:
        # TODO test this properly!
        # TODO Add a try/catch here!
        # noinspection PyUnusedLocal
        param_list = pp_forbidden_clause.parseString(clause)
        tmp_list = []
        clause_list = []
        for value in param_list[1:]:
            if len(tmp_list) < 3:
                tmp_list.append(value)
            else:
                # So far, only equals is supported by SMAC
                if tmp_list[1] == '=':
                    # TODO maybe add a check if the hyperparameter is
                    # actually in the configuration space
                    clause_list.append(
                        ForbiddenEqualsClause(
                            configuration_space.get_hyperparameter(
                                tmp_list[0]), tmp_list[2]))
                else:
                    raise NotImplementedError()
                tmp_list = []
        configuration_space.add_forbidden_clause(
            ForbiddenAndConjunction(*clause_list))

    #Now handle conditions
    # If there are two conditions for one child, these two conditions are an
    # AND-conjunction of conditions, thus we have to connect them
    conditions_per_child = OrderedDict()
    for condition in conditions:
        child_name = condition[0]
        if child_name not in conditions_per_child:
            conditions_per_child[child_name] = list()
        conditions_per_child[child_name].append(condition)

    for child_name in conditions_per_child:
        condition_objects = []
        for condition in conditions_per_child[child_name]:
            child = configuration_space.get_hyperparameter(child_name)
            parent_name = condition[2]
            parent = configuration_space.get_hyperparameter(parent_name)
            restrictions = condition[5:-1:2]

            # TODO: cast the type of the restriction!
            if len(restrictions) == 1:
                condition = EqualsCondition(child, parent, restrictions[0])
            else:
                condition = InCondition(child, parent, values=restrictions)
            condition_objects.append(condition)

        # Now we have all condition objects for this child, so we can build a
        #  giant AND-conjunction of them (if number of conditions >= 2)!

        if len(condition_objects) > 1:
            and_conjunction = AndConjunction(*condition_objects)
            configuration_space.add_condition(and_conjunction)
        else:
            configuration_space.add_condition(condition_objects[0])

    return configuration_space
Ejemplo n.º 15
0
def read(pcs_string, debug=False):
    """
    Reads in a :py:class:`~ConfigSpace.configuration_space.ConfigurationSpace`
    definition from a pcs file.

    Example
    -------

    >>> from ConfigSpace.read_and_write import pcs_new
    >>> with open('configspace.pcs', 'r') as fh:
    >>>     restored_conf = pcs_new.read(fh)

    Parameters
    ----------
    pcs_string : str
        ConfigSpace definition in pcs format
    debug : bool
        Provides debug information. Defaults to False.

    Returns
    -------
    :py:class:`~ConfigSpace.configuration_space.ConfigurationSpace`
        The restored ConfigurationSpace object

    """
    configuration_space = ConfigurationSpace()
    conditions = []
    forbidden = []

    # some statistics
    ct = 0
    cont_ct = 0
    cat_ct = 0
    ord_ct = 0
    line_ct = 0

    for line in pcs_string:
        line_ct += 1

        if "#" in line:
            # It contains a comment
            pos = line.find("#")
            line = line[:pos]

        # Remove quotes and whitespaces at beginning and end
        line = line.replace('"', "").replace("'", "")
        line = line.strip()
        if "|" in line:
            # It's a condition
            try:
                c = pp_condition.parseString(line)
                conditions.append(c)
            except pyparsing.ParseException:
                raise NotImplementedError("Could not parse condition: %s" %
                                          line)
            continue
        if "}" not in line and "]" not in line:
            continue
        if line.startswith("{") and line.endswith("}"):
            forbidden.append(line)
            continue
        if len(line.strip()) == 0:
            continue

        ct += 1
        param = None

        create = {
            "int": UniformIntegerHyperparameter,
            "float": UniformFloatHyperparameter,
            "categorical": CategoricalHyperparameter,
            "ordinal": OrdinalHyperparameter
        }

        try:
            param_list = pp_cont_param.parseString(line)
            name = param_list[0]
            if param_list[1] == 'integer':
                paramtype = 'int'
            elif param_list[1] == 'real':
                paramtype = 'float'
            else:
                paramtype = None

            if paramtype in ['int', 'float']:
                log = param_list[10:]
                param_list = param_list[:10]
                if len(log) > 0:
                    log = log[0]
                lower = float(param_list[3])
                upper = float(param_list[5])
                log_on = True if "log" in log else False
                default_value = float(param_list[8])
                param = create[paramtype](name=name,
                                          lower=lower,
                                          upper=upper,
                                          q=None,
                                          log=log_on,
                                          default_value=default_value)
                cont_ct += 1

        except pyparsing.ParseException:
            pass

        try:
            if "categorical" in line:
                param_list = pp_cat_param.parseString(line)
                name = param_list[0]
                choices = [choice for choice in param_list[3:-4:2]]
                default_value = param_list[-2]
                param = create["categorical"](name=name,
                                              choices=choices,
                                              default_value=default_value)
                cat_ct += 1

            elif "ordinal" in line:
                param_list = pp_ord_param.parseString(line)
                name = param_list[0]
                sequence = [seq for seq in param_list[3:-4:2]]
                default_value = param_list[-2]
                param = create["ordinal"](name=name,
                                          sequence=sequence,
                                          default_value=default_value)
                ord_ct += 1

        except pyparsing.ParseException:
            pass

        if param is None:
            raise NotImplementedError("Could not parse: %s" % line)

        configuration_space.add_hyperparameter(param)

    for clause in forbidden:
        param_list = pp_forbidden_clause.parseString(clause)
        tmp_list = []
        clause_list = []
        for value in param_list[1:]:
            if len(tmp_list) < 3:
                tmp_list.append(value)
            else:
                # So far, only equals is supported by SMAC
                if tmp_list[1] == '=':
                    # TODO maybe add a check if the hyperparameter is
                    # actually in the configuration space
                    clause_list.append(
                        ForbiddenEqualsClause(
                            configuration_space.get_hyperparameter(
                                tmp_list[0]), tmp_list[2]))
                else:
                    raise NotImplementedError()
                tmp_list = []
        configuration_space.add_forbidden_clause(
            ForbiddenAndConjunction(*clause_list))

    conditions_per_child = OrderedDict()
    for condition in conditions:
        child_name = condition[0]
        if child_name not in conditions_per_child:
            conditions_per_child[child_name] = list()
        conditions_per_child[child_name].append(condition)

    for child_name in conditions_per_child:
        for condition in conditions_per_child[child_name]:
            condition = condition[2:]
            condition = ' '.join(condition)
            if '||' in str(condition):
                ors = []
                # 1st case we have a mixture of || and &&
                if '&&' in str(condition):
                    ors_combis = []
                    for cond_parts in str(condition).split('||'):
                        condition = str(cond_parts).split('&&')
                        # if length is 1 it must be or
                        if len(condition) == 1:
                            element_list = condition[0].split()
                            ors_combis.append(
                                condition_specification(
                                    child_name, element_list,
                                    configuration_space))
                        else:
                            # now taking care of ands
                            ands = []
                            for and_part in condition:
                                element_list = [
                                    element for part in condition
                                    for element in and_part.split()
                                ]
                                ands.append(
                                    condition_specification(
                                        child_name, element_list,
                                        configuration_space))
                            ors_combis.append(AndConjunction(*ands))
                    mixed_conjunction = OrConjunction(*ors_combis)
                    configuration_space.add_condition(mixed_conjunction)
                else:
                    # 2nd case: we only have ors
                    for cond_parts in str(condition).split('||'):
                        element_list = [
                            element for element in cond_parts.split()
                        ]
                        ors.append(
                            condition_specification(child_name, element_list,
                                                    configuration_space))
                    or_conjunction = OrConjunction(*ors)
                    configuration_space.add_condition(or_conjunction)
            else:
                # 3rd case: we only have ands
                if '&&' in str(condition):
                    ands = []
                    for cond_parts in str(condition).split('&&'):
                        element_list = [
                            element for element in cond_parts.split()
                        ]
                        ands.append(
                            condition_specification(child_name, element_list,
                                                    configuration_space))
                    and_conjunction = AndConjunction(*ands)
                    configuration_space.add_condition(and_conjunction)
                else:
                    # 4th case: we have a normal condition
                    element_list = [element for element in condition.split()]
                    normal_condition = condition_specification(
                        child_name, element_list, configuration_space)
                    configuration_space.add_condition(normal_condition)

    return configuration_space
Ejemplo n.º 16
0
    def test_read_new_configuration_space_complex_conditionals(self):
        classi = OrdinalHyperparameter(
            "classi",
            [
                "random_forest", "extra_trees", "k_nearest_neighbors",
                "something"
            ],
        )
        knn_weights = CategoricalHyperparameter("knn_weights",
                                                ["uniform", "distance"])
        weather = OrdinalHyperparameter(
            "weather", ["sunny", "rainy", "cloudy", "snowing"])
        temperature = CategoricalHyperparameter("temperature", ["high", "low"])
        rain = CategoricalHyperparameter("rain", ["yes", "no"])
        gloves = OrdinalHyperparameter("gloves",
                                       ["none", "yarn", "leather", "gortex"])
        heur1 = CategoricalHyperparameter("heur1", ["off", "on"])
        heur2 = CategoricalHyperparameter("heur2", ["off", "on"])
        heur_order = CategoricalHyperparameter("heur_order",
                                               ["heur1then2", "heur2then1"])
        gloves_condition = OrConjunction(
            EqualsCondition(gloves, rain, "yes"),
            EqualsCondition(gloves, temperature, "low"))
        heur_condition = AndConjunction(
            EqualsCondition(heur_order, heur1, "on"),
            EqualsCondition(heur_order, heur2, "on"))
        and_conjunction = AndConjunction(
            NotEqualsCondition(knn_weights, classi, "extra_trees"),
            EqualsCondition(knn_weights, classi, "random_forest"))
        Cl_condition = OrConjunction(
            EqualsCondition(knn_weights, classi, "k_nearest_neighbors"),
            and_conjunction, EqualsCondition(knn_weights, classi, "something"))

        and1 = AndConjunction(EqualsCondition(temperature, weather, "rainy"),
                              EqualsCondition(temperature, weather, "cloudy"))
        and2 = AndConjunction(
            EqualsCondition(temperature, weather, "sunny"),
            NotEqualsCondition(temperature, weather, "snowing"))
        another_condition = OrConjunction(and1, and2)

        complex_conditional_space = ConfigurationSpace()
        complex_conditional_space.add_hyperparameter(classi)
        complex_conditional_space.add_hyperparameter(knn_weights)
        complex_conditional_space.add_hyperparameter(weather)
        complex_conditional_space.add_hyperparameter(temperature)
        complex_conditional_space.add_hyperparameter(rain)
        complex_conditional_space.add_hyperparameter(gloves)
        complex_conditional_space.add_hyperparameter(heur1)
        complex_conditional_space.add_hyperparameter(heur2)
        complex_conditional_space.add_hyperparameter(heur_order)

        complex_conditional_space.add_condition(gloves_condition)
        complex_conditional_space.add_condition(heur_condition)
        complex_conditional_space.add_condition(Cl_condition)
        complex_conditional_space.add_condition(another_condition)

        complex_cs = list()
        complex_cs.append(
            "classi ordinal {random_forest,extra_trees,k_nearest_neighbors, something} "
            "[random_forest]")
        complex_cs.append(
            "knn_weights categorical {uniform, distance} [uniform]")
        complex_cs.append(
            "weather ordinal {sunny, rainy, cloudy, snowing} [sunny]")
        complex_cs.append("temperature categorical {high, low} [high]")
        complex_cs.append("rain categorical { yes, no } [yes]")
        complex_cs.append(
            "gloves ordinal { none, yarn, leather, gortex } [none]")
        complex_cs.append("heur1 categorical { off, on } [off]")
        complex_cs.append("heur2 categorical { off, on } [off]")
        complex_cs.append(
            "heur_order categorical { heur1then2, heur2then1 } [heur1then2]")
        complex_cs.append("gloves | rain == yes || temperature == low")
        complex_cs.append("heur_order | heur1 == on && heur2 == on")
        complex_cs.append(
            "knn_weights | classi == k_nearest_neighbors || "
            "classi != extra_trees && classi == random_forest || classi == something"
        )
        complex_cs.append(
            "temperature | weather == rainy && weather == cloudy || "
            "weather == sunny && weather != snowing")
        cs_new = pcs_new.read(complex_cs)
        self.assertEqual(cs_new, complex_conditional_space)
Ejemplo n.º 17
0
def read(pcs_string, debug=False):
    """
    Read in a :py:class:`~ConfigSpace.configuration_space.ConfigurationSpace`
    definition from a pcs file.

    Example
    -------

    .. testsetup:: pcs_new_test

        from ConfigSpace import ConfigurationSpace
        import ConfigSpace.hyperparameters as CSH
        from ConfigSpace.read_and_write import pcs_new
        cs = ConfigurationSpace()
        cs.add_hyperparameter(CSH.CategoricalHyperparameter('a', choices=[1, 2, 3]))
        with open('configspace.pcs_new', 'w') as f:
             f.write(pcs_new.write(cs))

    .. doctest:: pcs_new_test

        >>> from ConfigSpace.read_and_write import pcs_new
        >>> with open('configspace.pcs_new', 'r') as fh:
        ...     deserialized_conf = pcs_new.read(fh)

    Parameters
    ----------
    pcs_string : str
        ConfigSpace definition in pcs format
    debug : bool
        Provides debug information. Defaults to False.

    Returns
    -------
    :py:class:`~ConfigSpace.configuration_space.ConfigurationSpace`
        The deserialized ConfigurationSpace object

    """
    configuration_space = ConfigurationSpace()
    conditions = []
    forbidden = []

    # some statistics
    ct = 0
    cont_ct = 0
    cat_ct = 0
    ord_ct = 0
    line_ct = 0

    for line in pcs_string:
        line_ct += 1

        if "#" in line:
            # It contains a comment
            pos = line.find("#")
            line = line[:pos]

        # Remove quotes and whitespaces at beginning and end
        line = line.replace('"', "").replace("'", "")
        line = line.strip()
        if "|" in line:
            # It's a condition
            try:
                c = pp_condition.parseString(line)
                conditions.append(c)
            except pyparsing.ParseException:
                raise NotImplementedError("Could not parse condition: %s" %
                                          line)
            continue
        if "}" not in line and "]" not in line:
            continue
        if line.startswith("{") and line.endswith("}"):
            forbidden.append(line)
            continue
        if len(line.strip()) == 0:
            continue

        ct += 1
        param = None

        create = {
            "int": UniformIntegerHyperparameter,
            "float": UniformFloatHyperparameter,
            "categorical": CategoricalHyperparameter,
            "ordinal": OrdinalHyperparameter
        }

        try:
            param_list = pp_cont_param.parseString(line)
            name = param_list[0]
            if param_list[1] == 'integer':
                paramtype = 'int'
            elif param_list[1] == 'real':
                paramtype = 'float'
            else:
                paramtype = None

            if paramtype in ['int', 'float']:
                log = param_list[10:]
                param_list = param_list[:10]
                if len(log) > 0:
                    log = log[0]
                lower = float(param_list[3])
                upper = float(param_list[5])
                log_on = True if "log" in log else False
                default_value = float(param_list[8])
                param = create[paramtype](name=name,
                                          lower=lower,
                                          upper=upper,
                                          q=None,
                                          log=log_on,
                                          default_value=default_value)
                cont_ct += 1

        except pyparsing.ParseException:
            pass

        try:
            if "categorical" in line:
                param_list = pp_cat_param.parseString(line)
                name = param_list[0]
                choices = [choice for choice in param_list[3:-4:2]]
                default_value = param_list[-2]
                param = create["categorical"](
                    name=name,
                    choices=choices,
                    default_value=default_value,
                )
                cat_ct += 1

            elif "ordinal" in line:
                param_list = pp_ord_param.parseString(line)
                name = param_list[0]
                sequence = [seq for seq in param_list[3:-4:2]]
                default_value = param_list[-2]
                param = create["ordinal"](
                    name=name,
                    sequence=sequence,
                    default_value=default_value,
                )
                ord_ct += 1

        except pyparsing.ParseException:
            pass

        if param is None:
            raise NotImplementedError("Could not parse: %s" % line)

        configuration_space.add_hyperparameter(param)

    for clause in forbidden:
        param_list = pp_forbidden_clause.parseString(clause)
        tmp_list = []
        clause_list = []
        for value in param_list[1:]:
            if len(tmp_list) < 3:
                tmp_list.append(value)
            else:
                # So far, only equals is supported by SMAC
                if tmp_list[1] == '=':
                    hp = configuration_space.get_hyperparameter(tmp_list[0])
                    if isinstance(hp, NumericalHyperparameter):
                        if isinstance(hp, IntegerHyperparameter):
                            forbidden_value = int(tmp_list[2])
                        elif isinstance(hp, FloatHyperparameter):
                            forbidden_value = float(tmp_list[2])
                        else:
                            raise NotImplementedError
                        if forbidden_value < hp.lower or forbidden_value > hp.upper:
                            raise ValueError(
                                f'forbidden_value is set out of the bound, it needs to'
                                f' be set between [{hp.lower}, {hp.upper}]'
                                f' but its value is {forbidden_value}')
                    elif isinstance(
                            hp,
                        (CategoricalHyperparameter, OrdinalHyperparameter)):
                        hp_values = hp.choices if isinstance(hp, CategoricalHyperparameter)\
                            else hp.sequence
                        forbidden_value_in_hp_values = tmp_list[2] in hp_values
                        if forbidden_value_in_hp_values:
                            forbidden_value = tmp_list[2]
                        else:
                            raise ValueError(
                                f'forbidden_value is set out of the allowed value '
                                f'sets, it needs to be one member from {hp_values} '
                                f'but its value is {forbidden_value}')
                    else:
                        raise ValueError('Unsupported Hyperparamter sorts')

                    clause_list.append(
                        ForbiddenEqualsClause(
                            configuration_space.get_hyperparameter(
                                tmp_list[0]), forbidden_value))
                else:
                    raise NotImplementedError()
                tmp_list = []
        configuration_space.add_forbidden_clause(
            ForbiddenAndConjunction(*clause_list))

    conditions_per_child = OrderedDict()
    for condition in conditions:
        child_name = condition[0]
        if child_name not in conditions_per_child:
            conditions_per_child[child_name] = list()
        conditions_per_child[child_name].append(condition)

    for child_name in conditions_per_child:
        for condition in conditions_per_child[child_name]:
            condition = condition[2:]
            condition = ' '.join(condition)
            if '||' in str(condition):
                ors = []
                # 1st case we have a mixture of || and &&
                if '&&' in str(condition):
                    ors_combis = []
                    for cond_parts in str(condition).split('||'):
                        condition = str(cond_parts).split('&&')
                        # if length is 1 it must be or
                        if len(condition) == 1:
                            element_list = condition[0].split()
                            ors_combis.append(
                                condition_specification(
                                    child_name,
                                    element_list,
                                    configuration_space,
                                ))
                        else:
                            # now taking care of ands
                            ands = []
                            for and_part in condition:
                                element_list = [
                                    element for part in condition
                                    for element in and_part.split()
                                ]
                                ands.append(
                                    condition_specification(
                                        child_name,
                                        element_list,
                                        configuration_space,
                                    ))
                            ors_combis.append(AndConjunction(*ands))
                    mixed_conjunction = OrConjunction(*ors_combis)
                    configuration_space.add_condition(mixed_conjunction)
                else:
                    # 2nd case: we only have ors
                    for cond_parts in str(condition).split('||'):
                        element_list = [
                            element for element in cond_parts.split()
                        ]
                        ors.append(
                            condition_specification(
                                child_name,
                                element_list,
                                configuration_space,
                            ))
                    or_conjunction = OrConjunction(*ors)
                    configuration_space.add_condition(or_conjunction)
            else:
                # 3rd case: we only have ands
                if '&&' in str(condition):
                    ands = []
                    for cond_parts in str(condition).split('&&'):
                        element_list = [
                            element for element in cond_parts.split()
                        ]
                        ands.append(
                            condition_specification(
                                child_name,
                                element_list,
                                configuration_space,
                            ))
                    and_conjunction = AndConjunction(*ands)
                    configuration_space.add_condition(and_conjunction)
                else:
                    # 4th case: we have a normal condition
                    element_list = [element for element in condition.split()]
                    normal_condition = condition_specification(
                        child_name,
                        element_list,
                        configuration_space,
                    )
                    configuration_space.add_condition(normal_condition)

    return configuration_space