From ccbd8e24f25750ea7b6f12e1607e2f4bad88222f Mon Sep 17 00:00:00 2001 From: Brice Videau Date: Fri, 11 Oct 2024 10:55:09 -0500 Subject: [PATCH] Evaluations are immutable and created valid. --- bindings/python/cconfigspace/evaluation.py | 7 -- .../python/cconfigspace/objective_space.py | 8 -- bindings/python/test/test_evaluation.py | 2 - bindings/python/test/test_objective_space.py | 2 +- bindings/python/test/test_tree_evaluation.py | 2 - bindings/ruby/lib/cconfigspace/evaluation.rb | 7 -- .../ruby/lib/cconfigspace/objective_space.rb | 7 -- bindings/ruby/test/test_evaluation.rb | 2 - bindings/ruby/test/test_objective_space.rb | 2 +- bindings/ruby/test/test_tree_evaluation.rb | 2 - include/cconfigspace/evaluation.h | 19 ---- include/cconfigspace/objective_space.h | 27 ------ src/evaluation.c | 91 ++++++++++--------- src/evaluation_internal.h | 2 + src/objective_space.c | 36 -------- 15 files changed, 50 insertions(+), 166 deletions(-) diff --git a/bindings/python/cconfigspace/evaluation.py b/bindings/python/cconfigspace/evaluation.py index 0c9690e9..c0bef486 100644 --- a/bindings/python/cconfigspace/evaluation.py +++ b/bindings/python/cconfigspace/evaluation.py @@ -18,7 +18,6 @@ class Comparison(CEnumeration): ccs_evaluation_get_objective_values = _ccs_get_function("ccs_evaluation_get_objective_values", [ccs_evaluation, ct.c_size_t, ct.POINTER(Datum), ct.POINTER(ct.c_size_t)]) ccs_evaluation_get_result = _ccs_get_function("ccs_evaluation_get_result", [ccs_evaluation, ct.POINTER(ccs_evaluation_result)]) ccs_evaluation_compare = _ccs_get_function("ccs_evaluation_compare", [ccs_evaluation, ccs_evaluation, ct.POINTER(Comparison)]) -ccs_evaluation_check = _ccs_get_function("ccs_evaluation_check", [ccs_evaluation, ct.POINTER(ccs_bool)]) class Evaluation(Binding): def __init__(self, handle = None, retain = False, auto_release = True, @@ -114,9 +113,3 @@ def compare(self, other): Error.check(res) return v.value - def check(self): - valid = ccs_bool() - res = ccs_evaluation_check(self.handle, ct.byref(valid)) - Error.check(res) - return False if valid.value == 0 else True - diff --git a/bindings/python/cconfigspace/objective_space.py b/bindings/python/cconfigspace/objective_space.py index ea8ecc65..36b59e53 100644 --- a/bindings/python/cconfigspace/objective_space.py +++ b/bindings/python/cconfigspace/objective_space.py @@ -16,7 +16,6 @@ class ObjectiveType(CEnumeration): ccs_objective_space_get_search_space = _ccs_get_function("ccs_objective_space_get_search_space", [ccs_objective_space, ct.POINTER(ccs_search_space)]) ccs_objective_space_get_objective = _ccs_get_function("ccs_objective_space_get_objective", [ccs_objective_space, ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ObjectiveType)]) ccs_objective_space_get_objectives = _ccs_get_function("ccs_objective_space_get_objectives", [ccs_objective_space, ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ObjectiveType), ct.POINTER(ct.c_size_t)]) -ccs_objective_space_check_evaluation = _ccs_get_function("ccs_objective_space_check_evaluation", [ccs_objective_space, ccs_evaluation, ct.POINTER(ccs_bool)]) class ObjectiveSpace(Context): def __init__(self, handle = None, retain = False, auto_release = True, @@ -94,10 +93,3 @@ def objectives(self): Error.check(res) self._objectives = tuple((Expression.from_handle(ccs_expression(v[x])), t[x].value) for x in range(sz)) return self._objectives - - def check(self, evaluation): - valid = ccs_bool() - res = ccs_objective_space_check_evaluation(self.handle, evaluation.handle, ct.byref(valid)) - Error.check(res) - return False if valid.value == 0 else True - diff --git a/bindings/python/test/test_evaluation.py b/bindings/python/test/test_evaluation.py index 49f7d9b0..c45a39fb 100644 --- a/bindings/python/test/test_evaluation.py +++ b/bindings/python/test/test_evaluation.py @@ -19,8 +19,6 @@ def test_create(self): ev1 = ccs.Evaluation(objective_space = os, configuration = cs.sample(), values = [0.5, 0.6]) self.assertEqual( (0.5, 0.6), ev1.values ) self.assertEqual( (0.5, 0.6), ev1.objective_values ) - self.assertTrue( ev1.check ) - self.assertTrue( os.check(ev1) ) ev2 = ccs.Evaluation(objective_space = os, configuration = cs.sample(), values = [0.5, 0.6]) self.assertEqual( (0.5, 0.6), ev2.values ) self.assertEqual( (0.5, 0.6), ev2.objective_values ) diff --git a/bindings/python/test/test_objective_space.py b/bindings/python/test/test_objective_space.py index 095e6653..6e91fb2e 100644 --- a/bindings/python/test/test_objective_space.py +++ b/bindings/python/test/test_objective_space.py @@ -35,7 +35,7 @@ def test_features(self): fs = ccs.FeatureSpace(parameters = [f]) p = ccs.NumericalParameter.Float() cs = ccs.ConfigurationSpace(name = "cs", parameters = [p], feature_space = fs) - h = ccs.NumericalParameter.Float() + h = ccs.NumericalParameter.Float(lower = -1.0, upper = 1.0, default = 0.0) e1 = ccs.Expression.Add(left = f, right = p) e2 = ccs.Expression.Variable(parameter = h) os = ccs.ObjectiveSpace(name = "space", search_space = cs, parameters = [h], objectives = [e1, e2], types = [ccs.ObjectiveType.MINIMIZE, ccs.ObjectiveType.MAXIMIZE]) diff --git a/bindings/python/test/test_tree_evaluation.py b/bindings/python/test/test_tree_evaluation.py index 6511efdf..8c6f9643 100644 --- a/bindings/python/test/test_tree_evaluation.py +++ b/bindings/python/test/test_tree_evaluation.py @@ -26,8 +26,6 @@ def test_create(self): ev1 = ccs.Evaluation(objective_space = os, configuration = ts.sample(), values = [0.5, 0.6]) self.assertEqual( (0.5, 0.6), ev1.values ) self.assertEqual( (0.5, 0.6), ev1.objective_values ) - self.assertTrue( ev1.check ) - self.assertTrue( os.check(ev1) ) ev2 = ccs.Evaluation(objective_space = os, configuration = ts.sample(), values = [0.5, 0.6]) self.assertEqual( (0.5, 0.6), ev2.values ) self.assertEqual( (0.5, 0.6), ev2.objective_values ) diff --git a/bindings/ruby/lib/cconfigspace/evaluation.rb b/bindings/ruby/lib/cconfigspace/evaluation.rb index f5da8428..e204aab0 100644 --- a/bindings/ruby/lib/cconfigspace/evaluation.rb +++ b/bindings/ruby/lib/cconfigspace/evaluation.rb @@ -17,7 +17,6 @@ def read_ccs_comparison_t attach_function :ccs_evaluation_get_result, [:ccs_evaluation_t, :pointer], :ccs_result_t attach_function :ccs_evaluation_get_objective_values, [:ccs_evaluation_t, :size_t, :pointer, :pointer], :ccs_result_t attach_function :ccs_evaluation_compare, [:ccs_evaluation_t, :ccs_evaluation_t, :pointer], :ccs_result_t - attach_function :ccs_evaluation_check, [:ccs_evaluation_t, :pointer], :ccs_result_t class Evaluation < Binding alias objective_space context @@ -53,12 +52,6 @@ def self.from_handle(handle, retain: true, auto_release: true) self::new(handle, retain: retain, auto_release: auto_release) end - def check - ptr = MemoryPointer::new(:ccs_bool_t) - CCS.error_check CCS.ccs_evaluation_check(@handle, ptr) - return ptr.read_ccs_bool_t == CCS::FALSE ? false : true - end - def compare(other) ptr = MemoryPointer::new(:ccs_comparison_t) CCS.error_check CCS.ccs_evaluation_compare(@handle, other, ptr) diff --git a/bindings/ruby/lib/cconfigspace/objective_space.rb b/bindings/ruby/lib/cconfigspace/objective_space.rb index a7acf265..c118b426 100644 --- a/bindings/ruby/lib/cconfigspace/objective_space.rb +++ b/bindings/ruby/lib/cconfigspace/objective_space.rb @@ -22,7 +22,6 @@ def read_array_of_ccs_objective_type_t(count) attach_function :ccs_objective_space_get_search_space, [:ccs_objective_space_t, :pointer], :ccs_result_t attach_function :ccs_objective_space_get_objective, [:ccs_objective_space_t, :size_t, :pointer, :pointer], :ccs_result_t attach_function :ccs_objective_space_get_objectives, [:ccs_objective_space_t, :size_t, :pointer, :pointer, :pointer], :ccs_result_t - attach_function :ccs_objective_space_check_evaluation, [:ccs_objective_space_t, :ccs_evaluation_t, :pointer], :ccs_result_t class ObjectiveSpace < Context add_handle_property :search_space, :ccs_search_space_t, :ccs_objective_space_get_search_space, memoize: true @@ -90,11 +89,5 @@ def objectives exprs.zip(types).freeze end end - - def check(evaluation) - ptr2 = MemoryPointer::new(:ccs_bool_t) - CCS.error_check CCS.ccs_objective_space_check_evaluation(@handle, evaluation.handle, ptr2) - return ptr2.read_ccs_bool_t == CCS::FALSE ? false : true - end end end diff --git a/bindings/ruby/test/test_evaluation.rb b/bindings/ruby/test/test_evaluation.rb index 3ef2fc7c..3ed44e6f 100644 --- a/bindings/ruby/test/test_evaluation.rb +++ b/bindings/ruby/test/test_evaluation.rb @@ -15,8 +15,6 @@ def test_create ev1 = CCS::Evaluation::new(objective_space: os, configuration: cs.sample, values: [0.5, 0.6]) assert_equal( [0.5, 0.6], ev1.values ) assert_equal( [0.5, 0.6], ev1.objective_values ) - assert( ev1.check ) - assert( os.check(ev1) ) ev2 = CCS::Evaluation::new(objective_space: os, configuration: cs.sample, values: [0.5, 0.6]) assert_equal( [0.5, 0.6], ev2.values ) assert_equal( [0.5, 0.6], ev2.objective_values ) diff --git a/bindings/ruby/test/test_objective_space.rb b/bindings/ruby/test/test_objective_space.rb index c0cc56fc..f04d8710 100644 --- a/bindings/ruby/test/test_objective_space.rb +++ b/bindings/ruby/test/test_objective_space.rb @@ -33,7 +33,7 @@ def test_features fs = CCS::FeatureSpace::new(parameters: [f]) p = CCS::NumericalParameter::Float.new cs = CCS::ConfigurationSpace::new(name: "cs", parameters: [p], feature_space: fs) - h = CCS::NumericalParameter::Float.new + h = CCS::NumericalParameter::Float.new(lower: -1.0, upper: 1.0, default: 0.0) e1 = CCS::Expression::Add.new(left: f, right: p) e2 = CCS::Expression::Variable.new(parameter: h) os = CCS::ObjectiveSpace::new(name: "space", search_space: cs, parameters: [h], objectives: [e1, e2], types: [:CCS_OBJECTIVE_TYPE_MINIMIZE, :CCS_OBJECTIVE_TYPE_MAXIMIZE]) diff --git a/bindings/ruby/test/test_tree_evaluation.rb b/bindings/ruby/test/test_tree_evaluation.rb index 82541666..0791e70c 100644 --- a/bindings/ruby/test/test_tree_evaluation.rb +++ b/bindings/ruby/test/test_tree_evaluation.rb @@ -24,8 +24,6 @@ def test_create ev1 = CCS::Evaluation.new(objective_space: os, configuration: ts.sample, values: [0.5, 0.6]) assert_equal( [0.5, 0.6], ev1.values ) assert_equal( [0.5, 0.6], ev1.objective_values ) - assert( ev1.check ) - assert( os.check(ev1) ) ev2 = CCS::Evaluation.new(objective_space: os, configuration: ts.sample, values: [0.5, 0.6]) assert_equal( [0.5, 0.6], ev2.values ) assert_equal( [0.5, 0.6], ev2.objective_values ) diff --git a/include/cconfigspace/evaluation.h b/include/cconfigspace/evaluation.h index 9f88b76c..cd834389 100644 --- a/include/cconfigspace/evaluation.h +++ b/include/cconfigspace/evaluation.h @@ -192,25 +192,6 @@ ccs_evaluation_get_objective_values( ccs_datum_t *values, size_t *num_values_ret); -/** - * Check that an evaluation values are valid in the objective space. - * @param[in] evaluation - * @param[out] is_valid_ret a pointer to a variable that will hold the result - * of the check. Result will be #CCS_TRUE if the - * evaluation is valid. Result will be #CCS_FALSE if - * an parameter value is not a valid value - * for this parameter - * @return #CCS_RESULT_SUCCESS on success - * @return #CCS_RESULT_ERROR_INVALID_OBJECT if \p evaluation is not a valid CCS - * evaluation - * @return #CCS_RESULT_ERROR_INVALID_EVALUATION if \p evaluation was found to be - * invalid in the context of the objective space - * @remarks - * This function is thread-safe - */ -extern ccs_result_t -ccs_evaluation_check(ccs_evaluation_t evaluation, ccs_bool_t *is_valid_ret); - /** * Compare two successful evaluations objectives. * @param[in] evaluation the first evaluation diff --git a/include/cconfigspace/objective_space.h b/include/cconfigspace/objective_space.h index 78f00852..ad3018fb 100644 --- a/include/cconfigspace/objective_space.h +++ b/include/cconfigspace/objective_space.h @@ -150,33 +150,6 @@ ccs_objective_space_get_objectives( ccs_objective_type_t *types, size_t *num_objectives_ret); -/** - * Check that a evaluation is a valid in a objective space. - * @param[in] objective_space - * @param[in] evaluation - * @param[out] is_valid_ret a pointer to a variable that will hold the result - * of the check. Result will be #CCS_TRUE if the - * evaluation is valid. Result will be #CCS_FALSE - * if an active parameter value is not a valid value - * for this parameter; or if an inactive parameter - * value is not inactive; or if a forbidden clause - * would be evaluating to #ccs_true - * @return #CCS_RESULT_SUCCESS on success - * @return #CCS_RESULT_ERROR_INVALID_OBJECT if \p objective_space is not a - * valid CCS objective space; or if \p evaluation is not a valid CCS - * evaluation - * @return #CCS_RESULT_ERROR_INVALID_VALUE if \p is_valid_ret is NULL - * @return #CCS_RESULT_ERROR_INVALID_EVALUATION if \p evaluation - * is not associated to the objective space - * @remarks - * This function is thread-safe - */ -extern ccs_result_t -ccs_objective_space_check_evaluation( - ccs_objective_space_t objective_space, - ccs_evaluation_t evaluation, - ccs_bool_t *is_valid_ret); - #ifdef __cplusplus } #endif diff --git a/src/evaluation.c b/src/evaluation.c index 33459cf1..314c127b 100644 --- a/src/evaluation.c +++ b/src/evaluation.c @@ -254,43 +254,44 @@ ccs_create_evaluation( CCS_CHECK_ARY(num_values, values); ccs_result_t err; size_t num_parameters = objective_space->data->num_parameters; + size_t num_objectives; + CCS_VALIDATE(ccs_objective_space_get_objectives( + objective_space, 0, NULL, NULL, &num_objectives)); CCS_REFUTE( - values && num_parameters != num_values, - CCS_RESULT_ERROR_INVALID_VALUE); + num_parameters != num_values, CCS_RESULT_ERROR_INVALID_VALUE); uintptr_t mem = (uintptr_t)calloc( 1, sizeof(struct _ccs_evaluation_s) + sizeof(struct _ccs_evaluation_data_s) + - num_parameters * sizeof(ccs_datum_t)); + num_parameters * sizeof(ccs_datum_t) + + num_objectives * sizeof(ccs_datum_t)); + uintptr_t cur_mem = mem; CCS_REFUTE(!mem, CCS_RESULT_ERROR_OUT_OF_MEMORY); CCS_VALIDATE_ERR_GOTO(err, ccs_retain_object(objective_space), errmem); CCS_VALIDATE_ERR_GOTO(err, ccs_retain_object(configuration), erros); ccs_evaluation_t eval; - eval = (ccs_evaluation_t)mem; + eval = (ccs_evaluation_t)cur_mem; + cur_mem += sizeof(struct _ccs_evaluation_s); _ccs_object_init( &(eval->obj), CCS_OBJECT_TYPE_EVALUATION, (_ccs_object_ops_t *)&_evaluation_ops); - eval->data = (struct _ccs_evaluation_data_s - *)(mem + sizeof(struct _ccs_evaluation_s)); + eval->data = (struct _ccs_evaluation_data_s *)(cur_mem); + cur_mem += sizeof(struct _ccs_evaluation_data_s); eval->data->num_values = num_parameters; + eval->data->num_objectives = num_objectives; eval->data->objective_space = objective_space; eval->data->configuration = configuration; eval->data->result = result; - eval->data->values = - (ccs_datum_t - *)(mem + sizeof(struct _ccs_evaluation_s) + sizeof(struct _ccs_evaluation_data_s)); - if (values) { - memcpy(eval->data->values, values, - num_parameters * sizeof(ccs_datum_t)); - for (size_t i = 0; i < num_values; i++) - if (values[i].flags & CCS_DATUM_FLAG_TRANSIENT) - CCS_VALIDATE_ERR_GOTO( - err, - ccs_context_validate_value( - (ccs_context_t)objective_space, - i, values[i], - eval->data->values + i), - errc); - } + eval->data->values = (ccs_datum_t *)(cur_mem); + cur_mem += num_parameters * sizeof(ccs_datum_t); + eval->data->objective_values = (ccs_datum_t *)(cur_mem); + + for (size_t i = 0; i < num_values; i++) + CCS_VALIDATE_ERR_GOTO( + err, + ccs_context_validate_value( + (ccs_context_t)objective_space, i, values[i], + eval->data->values + i), + errc); eval->data->bindings[0] = (ccs_binding_t)eval; eval->data->num_bindings = 1; if (configuration->obj.type == CCS_OBJECT_TYPE_CONFIGURATION) { @@ -308,6 +309,26 @@ ccs_create_evaluation( (ccs_binding_t)features; eval->data->num_bindings++; } + if (result == CCS_RESULT_SUCCESS) { + for (size_t i = 0; i < num_objectives; i++) { + ccs_expression_t expression; + ccs_objective_type_t type; + + CCS_VALIDATE_ERR_GOTO( + err, + ccs_objective_space_get_objective( + eval->data->objective_space, i, + &expression, &type), + errc); + CCS_VALIDATE_ERR_GOTO( + err, + ccs_expression_eval( + expression, eval->data->num_bindings, + eval->data->bindings, + eval->data->objective_values + i), + errc); + } + } *evaluation_ret = eval; return CCS_RESULT_SUCCESS; errc: @@ -365,15 +386,6 @@ ccs_evaluation_get_features( return CCS_RESULT_SUCCESS; } -ccs_result_t -ccs_evaluation_check(ccs_evaluation_t evaluation, ccs_bool_t *is_valid_ret) -{ - CCS_CHECK_OBJ(evaluation, CCS_OBJECT_TYPE_EVALUATION); - CCS_VALIDATE(ccs_objective_space_check_evaluation( - evaluation->data->objective_space, evaluation, is_valid_ret)); - return CCS_RESULT_SUCCESS; -} - ccs_result_t ccs_evaluation_get_objective_value( ccs_evaluation_t evaluation, @@ -402,22 +414,11 @@ ccs_evaluation_get_objective_values( CCS_CHECK_OBJ(evaluation, CCS_OBJECT_TYPE_EVALUATION); CCS_CHECK_ARY(num_values, values); CCS_REFUTE(!values && !num_values_ret, CCS_RESULT_ERROR_INVALID_VALUE); - size_t count; - CCS_VALIDATE(ccs_objective_space_get_objectives( - evaluation->data->objective_space, 0, NULL, NULL, &count)); + size_t count = evaluation->data->num_objectives; if (values) { CCS_REFUTE(count < num_values, CCS_RESULT_ERROR_INVALID_VALUE); - for (size_t i = 0; i < count; i++) { - ccs_expression_t expression; - ccs_objective_type_t type; - - CCS_VALIDATE(ccs_objective_space_get_objective( - evaluation->data->objective_space, i, - &expression, &type)); - CCS_VALIDATE(ccs_expression_eval( - expression, evaluation->data->num_bindings, - evaluation->data->bindings, values + i)); - } + for (size_t i = 0; i < count; i++) + values[i] = evaluation->data->objective_values[i]; for (size_t i = count; i < num_values; i++) values[i] = ccs_none; } diff --git a/src/evaluation_internal.h b/src/evaluation_internal.h index 5e5fc3d5..4ca4638f 100644 --- a/src/evaluation_internal.h +++ b/src/evaluation_internal.h @@ -32,6 +32,8 @@ struct _ccs_evaluation_data_s { ccs_objective_space_t objective_space; size_t num_values; ccs_datum_t *values; + size_t num_objectives; + ccs_datum_t *objective_values; ccs_evaluation_result_t result; ccs_search_configuration_t configuration; size_t num_bindings; diff --git a/src/objective_space.c b/src/objective_space.c index 9f462cbd..a324446b 100644 --- a/src/objective_space.c +++ b/src/objective_space.c @@ -321,42 +321,6 @@ ccs_objective_space_get_search_space( return CCS_RESULT_SUCCESS; } -static inline ccs_result_t -_check_evaluation( - ccs_objective_space_t objective_space, - ccs_evaluation_t evaluation, - ccs_bool_t *is_valid_ret) -{ - ccs_parameter_t *parameters = objective_space->data->parameters; - size_t num_parameters = objective_space->data->num_parameters; - ccs_datum_t *values = evaluation->data->values; - - *is_valid_ret = CCS_TRUE; - for (size_t i = 0; i < num_parameters; i++) { - CCS_VALIDATE(ccs_parameter_check_value( - parameters[i], values[i], is_valid_ret)); - if (*is_valid_ret == CCS_FALSE) - return CCS_RESULT_SUCCESS; - } - return CCS_RESULT_SUCCESS; -} - -ccs_result_t -ccs_objective_space_check_evaluation( - ccs_objective_space_t objective_space, - ccs_evaluation_t evaluation, - ccs_bool_t *is_valid_ret) -{ - CCS_CHECK_OBJ(objective_space, CCS_OBJECT_TYPE_OBJECTIVE_SPACE); - CCS_CHECK_OBJ(evaluation, CCS_OBJECT_TYPE_EVALUATION); - CCS_REFUTE( - evaluation->data->objective_space != objective_space, - CCS_RESULT_ERROR_INVALID_EVALUATION); - CCS_VALIDATE( - _check_evaluation(objective_space, evaluation, is_valid_ret)); - return CCS_RESULT_SUCCESS; -} - ccs_result_t ccs_objective_space_get_objective( ccs_objective_space_t objective_space,