From 10a903075e7dd0bd82881526070cfcdf875f03a6 Mon Sep 17 00:00:00 2001 From: Brice Videau Date: Fri, 3 Nov 2023 16:58:36 -0500 Subject: [PATCH] Conditions are now specified at configuration space creation. --- .github/workflows/presubmit.yml | 12 + Makefile.am | 3 +- .../cconfigspace/configuration_space.py | 38 +- bindings/python/cconfigspace/parameter.py | 3 + .../python/test/test_configuration_space.py | 43 +- .../lib/cconfigspace/configuration_space.rb | 48 +- .../ruby/test/test_configuration_space.rb | 47 +- connectors/kokkos/ccs-kokkos-connector.cpp | 2 +- include/cconfigspace/configuration_space.h | 35 +- samples/test_python.c | 2 +- samples/test_ruby.c | 2 +- src/configuration_space.c | 427 +++++++++--------- src/configuration_space_deserialize.h | 33 +- tests/test_condition.c | 43 +- tests/test_configuration_space.c | 39 +- tests/test_distribution_space.c | 6 +- tests/test_expression.c | 8 +- tests/test_forbidden.c | 25 +- tests/test_random_features_tuner.c | 4 +- tests/test_random_tuner.c | 4 +- tests/test_user_defined_features_tuner.c | 2 +- tests/test_user_defined_tuner.c | 2 +- 22 files changed, 411 insertions(+), 417 deletions(-) diff --git a/.github/workflows/presubmit.yml b/.github/workflows/presubmit.yml index 62f47bb7..99c207d5 100644 --- a/.github/workflows/presubmit.yml +++ b/.github/workflows/presubmit.yml @@ -35,6 +35,10 @@ jobs: if: ${{ matrix.os == 'ubuntu-latest' }} - run: brew install gsl automake if: ${{ matrix.os == 'macos-latest' }} + - uses: actions/setup-python@v4 + with: + python-version: '3.11' + if: ${{ matrix.os == 'macos-latest' }} - run: gem install --user-install rake ffi ffi-value whittle - run: pip3 install --user parglare==0.12.0 - run: ./autogen.sh @@ -74,6 +78,10 @@ jobs: if: ${{ matrix.os == 'ubuntu-latest' }} - run: brew install gsl automake if: ${{ matrix.os == 'macos-latest' }} + - uses: actions/setup-python@v4 + with: + python-version: '3.11' + if: ${{ matrix.os == 'macos-latest' }} - run: gem install --user-install rake ffi ffi-value whittle - run: pip3 install --user parglare==0.12.0 - run: ./autogen.sh @@ -98,6 +106,10 @@ jobs: if: ${{ matrix.os == 'ubuntu-latest' }} - run: brew install gsl automake if: ${{ matrix.os == 'macos-latest' }} + - uses: actions/setup-python@v4 + with: + python-version: '3.11' + if: ${{ matrix.os == 'macos-latest' }} - run: gem install --user-install rake ffi ffi-value whittle - run: pip3 install --user parglare==0.12.0 - run: ./autogen.sh diff --git a/Makefile.am b/Makefile.am index fd0d085a..c55ac9bd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,9 +1,8 @@ ACLOCAL_AMFLAGS = -I m4 -SUBDIRS = src include tests connectors +SUBDIRS = src include tests connectors bindings if SAMPLES SUBDIRS += samples endif -SUBDIRS += bindings cconfigspace.pc: cconfigspace.pc.subst .version_timestamp @echo Processing $@; sh $(top_srcdir)/build-aux/version-subst $(CURVER) $< $@ diff --git a/bindings/python/cconfigspace/configuration_space.py b/bindings/python/cconfigspace/configuration_space.py index 6973df53..197bfc97 100644 --- a/bindings/python/cconfigspace/configuration_space.py +++ b/bindings/python/cconfigspace/configuration_space.py @@ -8,10 +8,9 @@ from .rng import Rng from parglare.parser import Context as PContext -ccs_create_configuration_space = _ccs_get_function("ccs_create_configuration_space", [ct.c_char_p, ct.c_size_t, ct.POINTER(ccs_parameter), ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ccs_configuration_space)]) +ccs_create_configuration_space = _ccs_get_function("ccs_create_configuration_space", [ct.c_char_p, ct.c_size_t, ct.POINTER(ccs_parameter), ct.POINTER(ccs_expression), ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ccs_configuration_space)]) ccs_configuration_space_set_rng = _ccs_get_function("ccs_configuration_space_set_rng", [ccs_configuration_space, ccs_rng]) ccs_configuration_space_get_rng = _ccs_get_function("ccs_configuration_space_get_rng", [ccs_configuration_space, ct.POINTER(ccs_rng)]) -ccs_configuration_space_set_condition = _ccs_get_function("ccs_configuration_space_set_condition", [ccs_configuration_space, ct.c_size_t, ccs_expression]) ccs_configuration_space_get_condition = _ccs_get_function("ccs_configuration_space_get_condition", [ccs_configuration_space, ct.c_size_t, ct.POINTER(ccs_expression)]) ccs_configuration_space_get_conditions = _ccs_get_function("ccs_configuration_space_get_conditions", [ccs_configuration_space, ct.c_size_t, ct.POINTER(ccs_expression), ct.POINTER(ct.c_size_t)]) ccs_configuration_space_get_forbidden_clause = _ccs_get_function("ccs_configuration_space_get_forbidden_clause", [ccs_configuration_space, ct.c_size_t, ct.POINTER(ccs_expression)]) @@ -24,23 +23,40 @@ class ConfigurationSpace(Context): def __init__(self, handle = None, retain = False, auto_release = True, - name = "", parameters = None, forbidden_clauses = None): + name = "", parameters = None, conditions = None, forbidden_clauses = None): if handle is None: count = len(parameters) + if forbidden_clauses is not None: numfc = len(forbidden_clauses) if numfc > 0: ctx = dict(zip([x.name for x in parameters], parameters)) - fc_expressions = [ parser.parse(fc, context = PContext(extra=ctx)) if isinstance(fc, str) else fc for fc in forbidden_clauses ] - fcv = (ccs_expression * numfc)(*[x.handle.value for x in fc_expressions]) + forbidden_clauses = [ parser.parse(fc, context = PContext(extra=ctx)) if isinstance(fc, str) else fc for fc in forbidden_clauses ] + fcv = (ccs_expression * numfc)(*[x.handle.value for x in forbidden_clauses]) else: fcv = None else: numfc = 0 fcv = None + + if conditions is not None: + namedict = dict(zip([x.name for x in parameters], parameters)) + indexdict = dict(reversed(ele) for ele in enumerate(parameters)) + cv = (ccs_expression * count)() + conditions = dict( (k, parser.parse(v, context = PContext(extra=namedict)) if isinstance(v, str) else v) for (k, v) in conditions.items() ) + for (k, v) in conditions.items(): + if isinstance(k, Parameter): + cv[indexdict[k]] = v.handle.value + elif isinstance(k, str): + cv[indexdict[namedict[k]]] = v.handle.value + else: + cv[k] = v.handle.value + else: + cv = None + parameters = (ccs_parameter * count)(*[x.handle.value for x in parameters]) handle = ccs_configuration_space() - res = ccs_create_configuration_space(str.encode(name), count, parameters, numfc, fcv, ct.byref(handle)) + res = ccs_create_configuration_space(str.encode(name), count, parameters, cv, numfc, fcv, ct.byref(handle)) Error.check(res) super().__init__(handle = handle, retain = False) else: @@ -62,16 +78,6 @@ def rng(self, r): res = ccs_configuration_space_set_rng(self.handle, r.handle) Error.check(res) - def set_condition(self, parameter, expression): - if isinstance(expression, str): - expression = parser.parse(expression, context = PContext(extra=self)) - if isinstance(parameter, Parameter): - parameter = self.parameter_index(parameter) - elif isinstance(parameter, str): - parameter = self.parameter_index_by_name(parameter) - res = ccs_configuration_space_set_condition(self.handle, parameter, expression.handle) - Error.check(res) - def condition(self, parameter): if isinstance(parameter, Parameter): parameter = self.parameter_index(parameter) diff --git a/bindings/python/cconfigspace/parameter.py b/bindings/python/cconfigspace/parameter.py index 00790a19..b5929384 100644 --- a/bindings/python/cconfigspace/parameter.py +++ b/bindings/python/cconfigspace/parameter.py @@ -130,6 +130,9 @@ def samples(self, count, distribution = None, rng = None): def __eq__(self, other): return self.__class__ == other.__class__ and self.handle.value == other.handle.value + def __hash__(self): + return hash(self.handle.value) + ccs_create_float_numerical_parameter = _ccs_get_function("ccs_create_float_numerical_parameter", [ct.c_char_p, ccs_float, ccs_float, ccs_float, ccs_float, ct.POINTER(ccs_parameter)]) ccs_create_int_numerical_parameter = _ccs_get_function("ccs_create_int_numerical_parameter", [ct.c_char_p, ccs_int, ccs_int, ccs_int, ccs_int, ct.POINTER(ccs_parameter)]) diff --git a/bindings/python/test/test_configuration_space.py b/bindings/python/test/test_configuration_space.py index a95de053..0b8af162 100644 --- a/bindings/python/test/test_configuration_space.py +++ b/bindings/python/test/test_configuration_space.py @@ -60,12 +60,10 @@ def test_conditions(self): h1 = ccs.NumericalParameter.Float(lower = -1.0, upper = 1.0, default = 0.0) h2 = ccs.NumericalParameter.Float(lower = -1.0, upper = 1.0) h3 = ccs.NumericalParameter.Float(lower = -1.0, upper = 1.0) - f1 = ccs.Expression.Less(left = h1, right = 0.0) - cs = ccs.ConfigurationSpace(name = "space", parameters = [h1, h2, h3], forbidden_clauses = [f1]) e1 = ccs.Expression.Less(left = h2, right = 0.0) - cs.set_condition(h3, e1) e2 = ccs.Expression.Less(left = h3, right = 0.0) - cs.set_condition(h1, e2) + f1 = ccs.Expression.Less(left = h1, right = 0.0) + cs = ccs.ConfigurationSpace(name = "space", parameters = [h1, h2, h3], conditions = {h1: e2, h3: e1}, forbidden_clauses = [f1]) conditions = cs.conditions conditional_parameters = cs.conditional_parameters unconditional_parameters = cs.unconditional_parameters @@ -145,8 +143,6 @@ def test_omp(self): forbiddend = ccs.Expression.Equal(left = p3, right = ' ') forbidden1 = ccs.Expression.And(left = forbiddenc, right = forbiddend) - cs = ccs.ConfigurationSpace(name = "omp", parameters = [p1, p2, p3, p4, p5, p6, p7, p8, p9], forbidden_clauses = [forbidden0, forbidden1]) - cond0 = ccs.Expression.Equal(left = p1, right = '#pragma omp #P2') cond1 = ccs.Expression.Equal(left = p1, right = '#pragma omp target teams distribute #P2') cond2 = ccs.Expression.Equal(left = p1, right = '#pragma omp target teams distribute #P4') @@ -163,14 +159,16 @@ def test_omp(self): cond10 = ccs.Expression.Equal(left = p6, right = 'numthreads(#P9)') - cs.set_condition(p2, ccs.Expression.Or(left = cond0, right = cond1)) - cs.set_condition(p4, cond2) - cs.set_condition(p3, ccs.Expression.Or(left = cond3, right = cond4)) - cs.set_condition(p5, cond5) - cs.set_condition(p6, cond6) - cs.set_condition(p7, ccs.Expression.Or(left = cond8, right = cond9)) - cs.set_condition(p8, ccs.Expression.Or(left = cond7, right = cond9)) - cs.set_condition(p9, cond10) + cs = ccs.ConfigurationSpace(name = "omp", parameters = [p1, p2, p3, p4, p5, p6, p7, p8, p9], + conditions = {p2: ccs.Expression.Or(left = cond0, right = cond1), + p4: cond2, + p3: ccs.Expression.Or(left = cond3, right = cond4), + p5: cond5, + p6: cond6, + p7: ccs.Expression.Or(left = cond8, right = cond9), + p8: ccs.Expression.Or(left = cond7, right = cond9), + p9: cond10}, + forbidden_clauses = [forbidden0, forbidden1]) all_params = [ "p{}".format(i) for i in range(1,10) ] for i in range(1000): @@ -233,18 +231,17 @@ def test_omp_parse(self): values = ['1', '8', '16']) cs = ccs.ConfigurationSpace(name = "omp", parameters = [p1, p2, p3, p4, p5, p6, p7, p8, p9], + conditions = {p2: "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']", + p4: "p1 == '#pragma omp target teams distribute #P4'", + p3: "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'", + p5: "p2 == 'parallel for #P5'", + p6: "p2 == 'parallel for #P6'", + p7: "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']", + p8: "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'", + p9: "p6 == 'numthreads(#P9)'"}, forbidden_clauses = ["p1 == '#pragma omp #P2' && p2 == ' '", "p1 == '#pragma omp #P3' && p3 == ' '"]) - cs.set_condition(p2, "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']") - cs.set_condition(p4, "p1 == '#pragma omp target teams distribute #P4'") - cs.set_condition(p3, "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'") - cs.set_condition(p5, "p2 == 'parallel for #P5'") - cs.set_condition(p6, "p2 == 'parallel for #P6'") - cs.set_condition(p7, "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']") - cs.set_condition(p8, "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'") - cs.set_condition(p9, "p6 == 'numthreads(#P9)'") - all_params = [ "p{}".format(i) for i in range(1,10) ] for i in range(1000): s = cs.sample() diff --git a/bindings/ruby/lib/cconfigspace/configuration_space.rb b/bindings/ruby/lib/cconfigspace/configuration_space.rb index 2d072644..358db5fd 100644 --- a/bindings/ruby/lib/cconfigspace/configuration_space.rb +++ b/bindings/ruby/lib/cconfigspace/configuration_space.rb @@ -1,8 +1,7 @@ module CCS - attach_function :ccs_create_configuration_space, [:string, :size_t, :pointer, :size_t, :pointer, :pointer], :ccs_result_t + attach_function :ccs_create_configuration_space, [:string, :size_t, :pointer, :pointer, :size_t, :pointer, :pointer], :ccs_result_t attach_function :ccs_configuration_space_set_rng, [:ccs_configuration_space_t, :ccs_rng_t], :ccs_result_t attach_function :ccs_configuration_space_get_rng, [:ccs_configuration_space_t, :pointer], :ccs_result_t - attach_function :ccs_configuration_space_set_condition, [:ccs_configuration_space_t, :size_t, :ccs_expression_t], :ccs_result_t attach_function :ccs_configuration_space_get_condition, [:ccs_configuration_space_t, :size_t, :pointer], :ccs_result_t attach_function :ccs_configuration_space_get_conditions, [:ccs_configuration_space_t, :size_t, :pointer, :pointer], :ccs_result_t attach_function :ccs_configuration_space_get_forbidden_clause, [:ccs_configuration_space_t, :size_t, :pointer], :ccs_result_t @@ -16,7 +15,7 @@ module CCS class ConfigurationSpace < Context def initialize(handle = nil, retain: false, auto_release: true, - name: "", parameters: nil, forbidden_clauses: nil) + name: "", parameters: nil, conditions: nil, forbidden_clauses: nil) if handle super(handle, retain: retain, auto_release: auto_release) else @@ -24,18 +23,43 @@ def initialize(handle = nil, retain: false, auto_release: true, p_parameters = MemoryPointer::new(:ccs_parameter_t, count) p_parameters.write_array_of_pointer(parameters.collect(&:handle)) ptr = MemoryPointer::new(:ccs_configuration_space_t) + if forbidden_clauses ctx = parameters.map { |p| [p.name, p] }.to_h p = ExpressionParser::new(ctx) forbidden_clauses = forbidden_clauses.collect { |e| e.kind_of?(String) ? p.parse(e) : e } fccount = forbidden_clauses.size - fcptr = MemoryPointer::new(:ccs_expression_t, count) + fcptr = MemoryPointer::new(:ccs_expression_t, fccount) fcptr.write_array_of_pointer(forbidden_clauses.collect(&:handle)) else fccount = 0 fcptr = nil end - CCS.error_check CCS.ccs_create_configuration_space(name, count, p_parameters, fccount, fcptr, ptr) + + if conditions + ctx = parameters.map { |p| [p.name, p] }.to_h + indexdict = parameters.each_with_index.to_h + p = ExpressionParser::new(ctx) + conditions = conditions.transform_values { |v| v.kind_of?(String) ? p.parse(v) : v } + cond_handles = [0]*count + conditions.each do |k, v| + index = case k + when Parameter + indexdict[k] + when String, Symbol + indexdict[ctx[k]] + else + k + end + cond_handles[index] = v.handle + end + cptr = MemoryPointer::new(:ccs_expression_t, count) + cptr.write_array_of_pointer(cond_handles) + else + cptr = nil + end + + CCS.error_check CCS.ccs_create_configuration_space(name, count, p_parameters, cptr, fccount, fcptr, ptr) super(ptr.read_ccs_configuration_space_t, retain:false) end end @@ -55,20 +79,6 @@ def rng=(r) r end - def set_condition(parameter, expression) - if expression.kind_of? String - expression = ExpressionParser::new(self).parse(expression) - end - case parameter - when Parameter - parameter = parameter_index(parameter); - when String, Symbol - parameter = parameter_index_by_name(parameter); - end - CCS.error_check CCS.ccs_configuration_space_set_condition(@handle, parameter, expression) - self - end - def condition(parameter) case parameter when Parameter diff --git a/bindings/ruby/test/test_configuration_space.rb b/bindings/ruby/test/test_configuration_space.rb index aedc59df..1e75d950 100644 --- a/bindings/ruby/test/test_configuration_space.rb +++ b/bindings/ruby/test/test_configuration_space.rb @@ -60,12 +60,10 @@ def test_conditions h1 = CCS::NumericalParameter::Float.new(lower: -1.0, upper: 1.0, default: 0.0) h2 = CCS::NumericalParameter::Float.new(lower: -1.0, upper: 1.0) h3 = CCS::NumericalParameter::Float.new(lower: -1.0, upper: 1.0) - f1 = CCS::Expression::Less.new(left: h1, right: 0.0) - cs = CCS::ConfigurationSpace::new(name: "space", parameters: [h1, h2, h3], forbidden_clauses: [f1]) e1 = CCS::Expression::Less.new(left: h2, right: 0.0) - cs.set_condition(h3, e1) e2 = CCS::Expression::Less.new(left: h3, right: 0.0) - cs.set_condition(h1, e2) + f1 = CCS::Expression::Less.new(left: h1, right: 0.0) + cs = CCS::ConfigurationSpace::new(name: "space", parameters: [h1, h2, h3], conditions: {h1 => e2, h3 => e1}, forbidden_clauses: [f1]) conditions = cs.conditions conditional_parameters = cs.conditional_parameters unconditional_parameters = cs.unconditional_parameters @@ -154,9 +152,6 @@ def test_omp forbiddend = CCS::Expression::Equal.new(left: p3, right: ' ') forbidden1 = CCS::Expression::And.new(left: forbiddenc, right: forbiddend) - cs = CCS::ConfigurationSpace::new(name: "omp", parameters: [p1, p2, p3, p4, p5, p6, p7, p8, p9], - forbidden_clauses: [forbidden0, forbidden1]) - cond0 = CCS::Expression::Equal.new(left: p1, right: '#pragma omp #P2') cond1 = CCS::Expression::Equal.new(left: p1, right: '#pragma omp target teams distribute #P2') cond2 = CCS::Expression::Equal.new(left: p1, right: '#pragma omp target teams distribute #P4') @@ -173,15 +168,17 @@ def test_omp cond10 = CCS::Expression::Equal.new(left: p6, right: 'numthreads(#P9)') - cs.set_condition(p2, CCS::Expression::Or.new(left: cond0, right: cond1)) - cs.set_condition(p4, cond2) - cs.set_condition(p3, CCS::Expression::Or.new(left: cond3, right: cond4)) - cs.set_condition(p5, cond5) - cs.set_condition(p6, cond6) - cs.set_condition(p7, CCS::Expression::Or.new(left: cond8, right: cond9)) - cond_p8 = CCS::Expression::Or.new(left: cond7, right: cond9) - cs.set_condition(p8, cond_p8) - cs.set_condition(p9, cond10) + cs = CCS::ConfigurationSpace::new(name: "omp", parameters: [p1, p2, p3, p4, p5, p6, p7, p8, p9], + conditions: { + p2 => CCS::Expression::Or.new(left: cond0, right: cond1), + p4 => cond2, + p3 => CCS::Expression::Or.new(left: cond3, right: cond4), + p5 => cond5, + p6 => cond6, + p7 => CCS::Expression::Or.new(left: cond8, right: cond9), + p8 => CCS::Expression::Or.new(left: cond7, right: cond9), + p9 => cond10 }, + forbidden_clauses: [forbidden0, forbidden1]) all_params = (1..9).collect { |i| "p#{i}" } @@ -249,18 +246,18 @@ def test_omp_parse values: ['1', '8', '16']) cs = CCS::ConfigurationSpace::new(name: "omp", parameters: [p1, p2, p3, p4, p5, p6, p7, p8, p9], + conditions: { + p2 => "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']", + p4 => "p1 == '#pragma omp target teams distribute #P4'", + p3 => "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'", + p5 => "p2 == 'parallel for #P5'", + p6 => "p2 == 'parallel for #P6'", + p7 => "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']", + p8 => "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'", + p9 => "p6 == 'numthreads(#P9)'" }, forbidden_clauses: ["p1 == '#pragma omp #P2' && p2 == ' '", "p1 == '#pragma omp #P3' && p3 == ' '"]) - cs.set_condition(p2, "p1 # ['#pragma omp #P2', '#pragma omp target teams distribute #P2']") - cs.set_condition(p4, "p1 == '#pragma omp target teams distribute #P4'") - cs.set_condition(p3, "p1 == '#pragma omp #P3' || p2 == 'parallel for #P3'") - cs.set_condition(p5, "p2 == 'parallel for #P5'") - cs.set_condition(p6, "p2 == 'parallel for #P6'") - cs.set_condition(p7, "p5 # ['schedule(#P7)', 'schedule(#P7,#P8)']") - cs.set_condition(p8, "p4 == 'dist_schedule(static, #P8)' || p5 == 'schedule(#P7,#P8)'") - cs.set_condition(p9, "p6 == 'numthreads(#P9)'") - all_params = (1..9).collect { |i| "p#{i}" } 1000.times { diff --git a/connectors/kokkos/ccs-kokkos-connector.cpp b/connectors/kokkos/ccs-kokkos-connector.cpp index f2e87f55..7d6d16d8 100644 --- a/connectors/kokkos/ccs-kokkos-connector.cpp +++ b/connectors/kokkos/ccs-kokkos-connector.cpp @@ -515,7 +515,7 @@ kokkosp_request_values( CCS_CHECK(ccs_create_configuration_space( ("cs (region: " + std::to_string(regionCounter) + ")").c_str(), - numTuningVariables, cs_parameters, 0, NULL, &cs)); + numTuningVariables, cs_parameters, NULL, 0, NULL, &cs)); delete[] cs_parameters; #if CCS_DEBUG diff --git a/include/cconfigspace/configuration_space.h b/include/cconfigspace/configuration_space.h index a1a29ff1..e17e4be1 100644 --- a/include/cconfigspace/configuration_space.h +++ b/include/cconfigspace/configuration_space.h @@ -19,6 +19,10 @@ extern "C" { * @param[in] num_parameters the number of provided parameters * @param[in] parameters an array of \p num_parameters parameters * to add to the configuration space + * @param[in] conditions an optional array of \p num_parameters expressions + * setting the active condition of respective parameters. + * a NULL entry in the array means no condition is + * attached to the corresponding parameter. * @param[in] num_forbidden_clauses the number of provided forbidden clauses * @param[in] forbidden_clauses an array o \p num_forbidden_clauses expressions * to add as forbidden clauses to the @@ -38,6 +42,8 @@ extern "C" { * expression references a parameter that is not in the configuration space * @return #CCS_RESULT_ERROR_INVALID_CONFIGURATION if adding one of the provided * forbidden clause would render the default configuration invalid + * @return #CCS_RESULT_ERROR_INVALID_GRAPH if the addition of the conditions + * would cause the dependency graph to become invalid (cyclic) * @return #CCS_RESULT_ERROR_OUT_OF_MEMORY if there was a lack of memory to * allocate the new configuration space * @remarks @@ -48,6 +54,7 @@ ccs_create_configuration_space( const char *name, size_t num_parameters, ccs_parameter_t *parameters, + ccs_expression_t *conditions, size_t num_forbidden_clauses, ccs_expression_t *forbidden_clauses, ccs_configuration_space_t *configuration_space_ret); @@ -286,34 +293,6 @@ ccs_configuration_space_validate_value( ccs_datum_t value, ccs_datum_t *value_ret); -/** - * Set the active condition of a parameter in a configuration space given - * it's index. - * @param[in, out] configuration_space - * @param[in] parameter_index the index of the parameter to set the condition - * @param[in] expression the condition to associate to the parameter - * @return #CCS_RESULT_SUCCESS on success - * @return #CCS_RESULT_ERROR_INVALID_OBJECT if \p configuration_space is not a - * valid CCS configuration space; or if \p expression is not a valid CCS - * expression - * @return #CCS_RESULT_ERROR_OUT_OF_BOUNDS if index is greater than the number - * of parameters in \p configuration_space - * @return #CCS_RESULT_ERROR_INVALID_PARAMETER if parameter at index is already - * associated with a condition; or if the condition references a parameter that - * is not in the configuration space - * @return #CCS_RESULT_ERROR_OUT_OF_MEMORY if there was not enough memory to - * process the dependency graph - * @return #CCS_RESULT_ERROR_INVALID_GRAPH if the addition of the condition - * would cause the dependency graph to become invalid (cyclic) - * @remarks - * This function is thread-safe - */ -extern ccs_result_t -ccs_configuration_space_set_condition( - ccs_configuration_space_t configuration_space, - size_t parameter_index, - ccs_expression_t expression); - /** * Get the active condition of a parameter in a configuration space given * it's index. diff --git a/samples/test_python.c b/samples/test_python.c index 8c300ee4..cb9c61e0 100644 --- a/samples/test_python.c +++ b/samples/test_python.c @@ -32,7 +32,7 @@ create_problem(ccs_configuration_space_t *cs, ccs_objective_space_t *os) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); parameter3 = create_numerical("z", -CCS_INFINITY, CCS_INFINITY); diff --git a/samples/test_ruby.c b/samples/test_ruby.c index a0d45b72..c9d615ee 100644 --- a/samples/test_ruby.c +++ b/samples/test_ruby.c @@ -41,7 +41,7 @@ create_problem(ccs_configuration_space_t *cs, ccs_objective_space_t *os) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); parameter3 = create_numerical("z", -CCS_INFINITY, CCS_INFINITY); diff --git a/src/configuration_space.c b/src/configuration_space.c index 84e6cbfc..d48968e2 100644 --- a/src/configuration_space.c +++ b/src/configuration_space.c @@ -313,6 +313,210 @@ _ccs_configuration_space_add_forbidden_clauses( return err; } +static int +_size_t_sort(const void *a, const void *b) +{ + const size_t sa = *(const size_t *)a; + const size_t sb = *(const size_t *)b; + return sa < sb ? -1 : sa > sb ? 1 : 0; +} + +static void +_uniq_size_t_array(UT_array *array) +{ + size_t count = utarray_len(array); + if (count == 0) + return; + utarray_sort(array, &_size_t_sort); + size_t real_count = 0; + size_t *p = (size_t *)utarray_front(array); + size_t *p2 = p; + real_count++; + while ((p = (size_t *)utarray_next(array, p))) { + if (*p != *p2) { + p2 = (size_t *)utarray_next(array, p2); + *p2 = *p; + real_count++; + } + } + utarray_resize(array, real_count); +} + +struct _parameter_list_s; +struct _parameter_list_s { + size_t in_edges; + size_t index; + struct _parameter_list_s *next; + struct _parameter_list_s *prev; +}; + +#undef utarray_oom +#define utarray_oom() \ + { \ + free((void *)list); \ + CCS_RAISE( \ + CCS_RESULT_ERROR_OUT_OF_MEMORY, \ + "Not enough memory to allocate array"); \ + } +static ccs_result_t +_topological_sort(ccs_configuration_space_t configuration_space) +{ + _ccs_configuration_space_data_t *data = configuration_space->data; + size_t num_parameters = data->num_parameters; + size_t *indexes = data->sorted_indexes; + UT_array **parents = data->parents; + UT_array **children = data->children; + + for (size_t i = 0; i < num_parameters; i++) + indexes[i] = 0; + + struct _parameter_list_s *list = (struct _parameter_list_s *)calloc( + 1, sizeof(struct _parameter_list_s) * num_parameters); + CCS_REFUTE(!list, CCS_RESULT_ERROR_OUT_OF_MEMORY); + struct _parameter_list_s *queue = NULL; + for (size_t index = 0; index < num_parameters; index++) { + size_t in_edges = utarray_len(parents[index]); + list[index].in_edges = in_edges; + list[index].index = index; + if (in_edges == 0) + DL_APPEND(queue, list + index); + } + size_t processed = 0; + while (queue) { + struct _parameter_list_s *e = queue; + DL_DELETE(queue, queue); + size_t *child = NULL; + while ((child = (size_t *)utarray_next( + children[e->index], child))) { + list[*child].in_edges--; + if (list[*child].in_edges == 0) { + DL_APPEND(queue, list + *child); + } + } + indexes[processed++] = e->index; + }; + free(list); + CCS_REFUTE(processed < num_parameters, CCS_RESULT_ERROR_INVALID_GRAPH); + return CCS_RESULT_SUCCESS; +} + +#undef utarray_oom +#define utarray_oom() \ + { \ + CCS_RAISE_ERR_GOTO( \ + err, CCS_RESULT_ERROR_OUT_OF_MEMORY, errmem, \ + "Not enough memory to allocate array"); \ + } +static ccs_result_t +_recompute_graph(ccs_configuration_space_t configuration_space) +{ + _ccs_configuration_space_data_t *data = configuration_space->data; + size_t num_parameters = data->num_parameters; + UT_array **pparents = data->parents; + UT_array **pchildren = data->children; + ccs_expression_t *conditions = data->conditions; + + for (size_t index = 0; index < num_parameters; index++) { + utarray_clear(pparents[index]); + utarray_clear(pchildren[index]); + } + intptr_t mem = 0; + ccs_result_t err = CCS_RESULT_SUCCESS; + for (size_t index = 0; index < num_parameters; index++) { + ccs_expression_t condition = conditions[index]; + if (!condition) + continue; + size_t count; + CCS_VALIDATE_ERR_GOTO( + err, + ccs_expression_get_parameters( + condition, 0, NULL, &count), + errmem); + if (count == 0) + continue; + ccs_parameter_t *parents = NULL; + size_t *parents_index = NULL; + intptr_t oldmem = mem; + mem = (intptr_t)realloc( + (void *)oldmem, + count * (sizeof(ccs_parameter_t) + sizeof(size_t))); + if (!mem) { + mem = oldmem; + CCS_RAISE_ERR_GOTO( + err, CCS_RESULT_ERROR_OUT_OF_MEMORY, errmem, + "Not enough memory to reallocate array"); + } + parents = (ccs_parameter_t *)mem; + parents_index = + (size_t *)(mem + count * sizeof(ccs_parameter_t)); + CCS_VALIDATE_ERR_GOTO( + err, + ccs_expression_get_parameters( + condition, count, parents, NULL), + errmem); + CCS_VALIDATE_ERR_GOTO( + err, + ccs_configuration_space_get_parameter_indexes( + configuration_space, count, parents, + parents_index), + errmem); + for (size_t i = 0; i < count; i++) { + utarray_push_back(pparents[index], parents_index + i); + utarray_push_back(pchildren[parents_index[i]], &index); + } + } + for (size_t index = 0; index < num_parameters; index++) { + _uniq_size_t_array(pparents[index]); + _uniq_size_t_array(pchildren[index]); + } +errmem: + if (mem) + free((void *)mem); + return err; +} +#undef utarray_oom +#define utarray_oom() \ + { \ + exit(-1); \ + } + +static ccs_result_t +_generate_constraints(ccs_configuration_space_t configuration_space) +{ + CCS_VALIDATE(_recompute_graph(configuration_space)); + CCS_VALIDATE(_topological_sort(configuration_space)); + configuration_space->data->graph_ok = CCS_TRUE; + return CCS_RESULT_SUCCESS; +} + +static inline ccs_result_t +_ccs_configuration_space_set_condition( + ccs_configuration_space_t configuration_space, + size_t parameter_index, + ccs_expression_t expression) +{ + CCS_VALIDATE(ccs_expression_check_context( + expression, (ccs_context_t)configuration_space)); + CCS_VALIDATE(ccs_retain_object(expression)); + configuration_space->data->conditions[parameter_index] = expression; + return CCS_RESULT_SUCCESS; +} + +static ccs_result_t +_ccs_configuration_space_set_conditions( + ccs_configuration_space_t configuration_space, + ccs_expression_t *conditions) +{ + for (size_t i = 0; i < configuration_space->data->num_parameters; i++) { + if (conditions[i]) + CCS_VALIDATE(_ccs_configuration_space_set_condition( + configuration_space, i, conditions[i])); + } + configuration_space->data->graph_ok = CCS_FALSE; + CCS_VALIDATE(_generate_constraints(configuration_space)); + return CCS_RESULT_SUCCESS; +} + #undef utarray_oom #define utarray_oom() \ { \ @@ -326,6 +530,7 @@ ccs_create_configuration_space( const char *name, size_t num_parameters, ccs_parameter_t *parameters, + ccs_expression_t *conditions, size_t num_forbidden_clauses, ccs_expression_t *forbidden_clauses, ccs_configuration_space_t *configuration_space_ret) @@ -335,6 +540,12 @@ ccs_create_configuration_space( CCS_CHECK_ARY(num_parameters, parameters); for (size_t i = 0; i < num_parameters; i++) CCS_CHECK_OBJ(parameters[i], CCS_OBJECT_TYPE_PARAMETER); + if (conditions) + for (size_t i = 0; i < num_parameters; i++) + if (conditions[i]) + CCS_CHECK_OBJ( + conditions[i], + CCS_OBJECT_TYPE_EXPRESSION); CCS_CHECK_ARY(num_forbidden_clauses, forbidden_clauses); for (size_t i = 0; i < num_forbidden_clauses; i++) CCS_CHECK_OBJ(forbidden_clauses[i], CCS_OBJECT_TYPE_EXPRESSION); @@ -404,6 +615,12 @@ ccs_create_configuration_space( utarray_new(config_space->data->parents[i], &_size_t_icd); utarray_new(config_space->data->children[i], &_size_t_icd); } + if (conditions) + CCS_VALIDATE_ERR_GOTO( + err, + _ccs_configuration_space_set_conditions( + config_space, conditions), + errparams); *configuration_space_ret = config_space; return CCS_RESULT_SUCCESS; errparams: @@ -901,216 +1118,6 @@ ccs_configuration_space_samples( return err; } -static int -_size_t_sort(const void *a, const void *b) -{ - const size_t sa = *(const size_t *)a; - const size_t sb = *(const size_t *)b; - return sa < sb ? -1 : sa > sb ? 1 : 0; -} - -static void -_uniq_size_t_array(UT_array *array) -{ - size_t count = utarray_len(array); - if (count == 0) - return; - utarray_sort(array, &_size_t_sort); - size_t real_count = 0; - size_t *p = (size_t *)utarray_front(array); - size_t *p2 = p; - real_count++; - while ((p = (size_t *)utarray_next(array, p))) { - if (*p != *p2) { - p2 = (size_t *)utarray_next(array, p2); - *p2 = *p; - real_count++; - } - } - utarray_resize(array, real_count); -} - -struct _parameter_list_s; -struct _parameter_list_s { - size_t in_edges; - size_t index; - struct _parameter_list_s *next; - struct _parameter_list_s *prev; -}; - -#undef utarray_oom -#define utarray_oom() \ - { \ - free((void *)list); \ - CCS_RAISE( \ - CCS_RESULT_ERROR_OUT_OF_MEMORY, \ - "Not enough memory to allocate array"); \ - } -static ccs_result_t -_topological_sort(ccs_configuration_space_t configuration_space) -{ - _ccs_configuration_space_data_t *data = configuration_space->data; - size_t num_parameters = data->num_parameters; - size_t *indexes = data->sorted_indexes; - UT_array **parents = data->parents; - UT_array **children = data->children; - - for (size_t i = 0; i < num_parameters; i++) - indexes[i] = 0; - - struct _parameter_list_s *list = (struct _parameter_list_s *)calloc( - 1, sizeof(struct _parameter_list_s) * num_parameters); - CCS_REFUTE(!list, CCS_RESULT_ERROR_OUT_OF_MEMORY); - struct _parameter_list_s *queue = NULL; - for (size_t index = 0; index < num_parameters; index++) { - size_t in_edges = utarray_len(parents[index]); - list[index].in_edges = in_edges; - list[index].index = index; - if (in_edges == 0) - DL_APPEND(queue, list + index); - } - size_t processed = 0; - while (queue) { - struct _parameter_list_s *e = queue; - DL_DELETE(queue, queue); - size_t *child = NULL; - while ((child = (size_t *)utarray_next( - children[e->index], child))) { - list[*child].in_edges--; - if (list[*child].in_edges == 0) { - DL_APPEND(queue, list + *child); - } - } - indexes[processed++] = e->index; - }; - free(list); - CCS_REFUTE(processed < num_parameters, CCS_RESULT_ERROR_INVALID_GRAPH); - return CCS_RESULT_SUCCESS; -} - -#undef utarray_oom -#define utarray_oom() \ - { \ - CCS_RAISE_ERR_GOTO( \ - err, CCS_RESULT_ERROR_OUT_OF_MEMORY, errmem, \ - "Not enough memory to allocate array"); \ - } -static ccs_result_t -_recompute_graph(ccs_configuration_space_t configuration_space) -{ - _ccs_configuration_space_data_t *data = configuration_space->data; - size_t num_parameters = data->num_parameters; - UT_array **pparents = data->parents; - UT_array **pchildren = data->children; - ccs_expression_t *conditions = data->conditions; - - for (size_t index = 0; index < num_parameters; index++) { - utarray_clear(pparents[index]); - utarray_clear(pchildren[index]); - } - intptr_t mem = 0; - ccs_result_t err = CCS_RESULT_SUCCESS; - for (size_t index = 0; index < num_parameters; index++) { - ccs_expression_t condition = conditions[index]; - if (!condition) - continue; - size_t count; - CCS_VALIDATE_ERR_GOTO( - err, - ccs_expression_get_parameters( - condition, 0, NULL, &count), - errmem); - if (count == 0) - continue; - ccs_parameter_t *parents = NULL; - size_t *parents_index = NULL; - intptr_t oldmem = mem; - mem = (intptr_t)realloc( - (void *)oldmem, - count * (sizeof(ccs_parameter_t) + sizeof(size_t))); - if (!mem) { - mem = oldmem; - CCS_RAISE_ERR_GOTO( - err, CCS_RESULT_ERROR_OUT_OF_MEMORY, errmem, - "Not enough memory to reallocate array"); - } - parents = (ccs_parameter_t *)mem; - parents_index = - (size_t *)(mem + count * sizeof(ccs_parameter_t)); - CCS_VALIDATE_ERR_GOTO( - err, - ccs_expression_get_parameters( - condition, count, parents, NULL), - errmem); - CCS_VALIDATE_ERR_GOTO( - err, - ccs_configuration_space_get_parameter_indexes( - configuration_space, count, parents, - parents_index), - errmem); - for (size_t i = 0; i < count; i++) { - utarray_push_back(pparents[index], parents_index + i); - utarray_push_back(pchildren[parents_index[i]], &index); - } - } - for (size_t index = 0; index < num_parameters; index++) { - _uniq_size_t_array(pparents[index]); - _uniq_size_t_array(pchildren[index]); - } -errmem: - if (mem) - free((void *)mem); - return err; -} -#undef utarray_oom -#define utarray_oom() \ - { \ - exit(-1); \ - } - -static ccs_result_t -_generate_constraints(ccs_configuration_space_t configuration_space) -{ - CCS_VALIDATE(_recompute_graph(configuration_space)); - CCS_VALIDATE(_topological_sort(configuration_space)); - configuration_space->data->graph_ok = CCS_TRUE; - return CCS_RESULT_SUCCESS; -} - -ccs_result_t -ccs_configuration_space_set_condition( - ccs_configuration_space_t configuration_space, - size_t parameter_index, - ccs_expression_t expression) -{ - CCS_CHECK_OBJ(configuration_space, CCS_OBJECT_TYPE_CONFIGURATION_SPACE); - CCS_CHECK_OBJ(expression, CCS_OBJECT_TYPE_EXPRESSION); - CCS_REFUTE( - parameter_index >= configuration_space->data->num_parameters, - CCS_RESULT_ERROR_OUT_OF_BOUNDS); - CCS_OBJ_WRLOCK(configuration_space); - ccs_result_t err = CCS_RESULT_SUCCESS; - ccs_expression_t *conditions = configuration_space->data->conditions; - CCS_REFUTE_ERR_GOTO( - err, conditions[parameter_index], - CCS_RESULT_ERROR_INVALID_PARAMETER, errwrapper); - CCS_VALIDATE_ERR_GOTO(err, ccs_retain_object(expression), errwrapper); - conditions[parameter_index] = expression; - // Recompute the whole graph for now - configuration_space->data->graph_ok = CCS_FALSE; - CCS_VALIDATE_ERR_GOTO( - err, _generate_constraints(configuration_space), erre); - CCS_OBJ_UNLOCK(configuration_space); - return CCS_RESULT_SUCCESS; -erre: - ccs_release_object(expression); - conditions[parameter_index] = NULL; - _generate_constraints(configuration_space); -errwrapper: - CCS_OBJ_UNLOCK(configuration_space); - return err; -} - ccs_result_t ccs_configuration_space_get_condition( ccs_configuration_space_t configuration_space, diff --git a/src/configuration_space_deserialize.h b/src/configuration_space_deserialize.h index f2c9e54f..30795596 100644 --- a/src/configuration_space_deserialize.h +++ b/src/configuration_space_deserialize.h @@ -12,7 +12,6 @@ struct _ccs_configuration_space_data_mock_s { size_t num_forbidden_clauses; ccs_rng_t rng; ccs_parameter_t *parameters; - size_t *cond_parameter_indices; ccs_expression_t *conditions; ccs_expression_t *forbidden_clauses; }; @@ -46,18 +45,15 @@ _ccs_deserialize_bin_ccs_configuration_space_data( return CCS_RESULT_SUCCESS; mem = (uintptr_t)calloc( data->num_parameters * sizeof(ccs_parameter_t) + - data->num_conditions * - (sizeof(ccs_expression_t) + sizeof(size_t)) + + data->num_parameters * sizeof(ccs_expression_t) + data->num_forbidden_clauses * sizeof(ccs_expression_t), 1); CCS_REFUTE(!mem, CCS_RESULT_ERROR_OUT_OF_MEMORY); data->parameters = (ccs_parameter_t *)mem; mem += data->num_parameters * sizeof(ccs_parameter_t); - data->cond_parameter_indices = (size_t *)mem; - mem += data->num_conditions * sizeof(size_t); data->conditions = (ccs_expression_t *)mem; - mem += data->num_conditions * sizeof(ccs_expression_t); + mem += data->num_parameters * sizeof(ccs_expression_t); data->forbidden_clauses = (ccs_expression_t *)mem; for (size_t i = 0; i < data->num_parameters; i++) @@ -66,10 +62,11 @@ _ccs_deserialize_bin_ccs_configuration_space_data( version, buffer_size, buffer, opts)); for (size_t i = 0; i < data->num_conditions; i++) { - CCS_VALIDATE(_ccs_deserialize_bin_size( - data->cond_parameter_indices + i, buffer_size, buffer)); + size_t index; + CCS_VALIDATE( + _ccs_deserialize_bin_size(&index, buffer_size, buffer)); CCS_VALIDATE(_ccs_expression_deserialize( - data->conditions + i, CCS_SERIALIZE_FORMAT_BINARY, + data->conditions + index, CCS_SERIALIZE_FORMAT_BINARY, version, buffer_size, buffer, opts)); } @@ -104,8 +101,8 @@ _ccs_deserialize_bin_configuration_space( new_opts.map_values = CCS_TRUE; CCS_VALIDATE(ccs_create_map(&new_opts.handle_map)); - _ccs_configuration_space_data_mock_t data = { - NULL, 0, 0, 0, NULL, NULL, NULL, NULL, NULL}; + _ccs_configuration_space_data_mock_t data = {NULL, 0, 0, 0, + NULL, NULL, NULL, NULL}; CCS_VALIDATE_ERR_GOTO( res, _ccs_deserialize_bin_ccs_configuration_space_data( @@ -115,22 +112,14 @@ _ccs_deserialize_bin_configuration_space( res, ccs_create_configuration_space( data.name, data.num_parameters, data.parameters, - data.num_forbidden_clauses, data.forbidden_clauses, - configuration_space_ret), + data.conditions, data.num_forbidden_clauses, + data.forbidden_clauses, configuration_space_ret), end); CCS_VALIDATE_ERR_GOTO( res, ccs_configuration_space_set_rng( *configuration_space_ret, data.rng), end); - for (size_t i = 0; i < data.num_conditions; i++) - CCS_VALIDATE_ERR_GOTO( - res, - ccs_configuration_space_set_condition( - *configuration_space_ret, - data.cond_parameter_indices[i], - data.conditions[i]), - err_configuration_space); if (opts && opts->map_values && opts->handle_map) CCS_VALIDATE_ERR_GOTO( res, @@ -151,7 +140,7 @@ _ccs_deserialize_bin_configuration_space( if (data.parameters[i]) ccs_release_object(data.parameters[i]); if (data.conditions) - for (size_t i = 0; i < data.num_conditions; i++) + for (size_t i = 0; i < data.num_parameters; i++) if (data.conditions[i]) ccs_release_object(data.conditions[i]); if (data.forbidden_clauses) diff --git a/tests/test_condition.c b/tests/test_condition.c index 2d21d585..f5ef4ad2 100644 --- a/tests/test_condition.c +++ b/tests/test_condition.c @@ -21,8 +21,8 @@ test_simple(void) { ccs_parameter_t parameter1, parameter2; ccs_parameter_t parameters[2]; + ccs_expression_t conditions[2] = {NULL, NULL}; ccs_configuration_space_t space; - ccs_expression_t expression; ccs_configuration_t configuration; ccs_datum_t values[2]; ccs_configuration_t configurations[100]; @@ -30,16 +30,13 @@ test_simple(void) parameters[0] = parameter1 = create_numerical("param1"); parameters[1] = parameter2 = create_numerical("param2"); - err = ccs_create_configuration_space( - "space", 2, parameters, 0, NULL, &space); + err = ccs_create_binary_expression( + CCS_EXPRESSION_TYPE_LESS, ccs_object(parameter1), + ccs_float(0.0), &conditions[1]); assert(err == CCS_RESULT_SUCCESS); - err = ccs_create_binary_expression( - CCS_EXPRESSION_TYPE_LESS, ccs_object(parameter1), - ccs_float(0.0), &expression); - assert(err == CCS_RESULT_SUCCESS); - - err = ccs_configuration_space_set_condition(space, 1, expression); + err = ccs_create_configuration_space( + "space", 2, parameters, conditions, 0, NULL, &space); assert(err == CCS_RESULT_SUCCESS); for (int i = 0; i < 100; i++) { @@ -90,7 +87,7 @@ test_simple(void) assert(err == CCS_RESULT_SUCCESS); } - err = ccs_release_object(expression); + err = ccs_release_object(conditions[1]); assert(err == CCS_RESULT_SUCCESS); err = ccs_release_object(parameter1); assert(err == CCS_RESULT_SUCCESS); @@ -104,8 +101,8 @@ void test_transitive(void) { ccs_parameter_t parameters[3]; + ccs_expression_t conditions[3] = {NULL, NULL, NULL}; ccs_configuration_space_t space; - ccs_expression_t expression; ccs_configuration_t configuration; ccs_datum_t values[3]; ccs_configuration_t configurations[100]; @@ -115,26 +112,22 @@ test_transitive(void) parameters[1] = create_numerical("param2"); parameters[2] = create_numerical("param3"); - err = ccs_create_configuration_space( - "space", 3, parameters, 0, NULL, &space); + err = ccs_create_binary_expression( + CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[1]), + ccs_float(0.0), &conditions[2]); assert(err == CCS_RESULT_SUCCESS); - err = ccs_create_binary_expression( - CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[1]), - ccs_float(0.0), &expression); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_configuration_space_set_condition(space, 2, expression); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_release_object(expression); + CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[2]), + ccs_float(0.0), &conditions[0]); assert(err == CCS_RESULT_SUCCESS); - err = ccs_create_binary_expression( - CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[2]), - ccs_float(0.0), &expression); + err = ccs_create_configuration_space( + "space", 3, parameters, conditions, 0, NULL, &space); assert(err == CCS_RESULT_SUCCESS); - err = ccs_configuration_space_set_condition(space, 0, expression); + + err = ccs_release_object(conditions[0]); assert(err == CCS_RESULT_SUCCESS); - err = ccs_release_object(expression); + err = ccs_release_object(conditions[2]); assert(err == CCS_RESULT_SUCCESS); for (int i = 0; i < 100; i++) { diff --git a/tests/test_configuration_space.c b/tests/test_configuration_space.c index fc8266b2..6a8e886b 100644 --- a/tests/test_configuration_space.c +++ b/tests/test_configuration_space.c @@ -98,7 +98,8 @@ test_empty(void) ccs_result_t err; err = ccs_create_configuration_space( - "my_config_space", 0, NULL, 0, NULL, &configuration_space); + "my_config_space", 0, NULL, NULL, 0, NULL, + &configuration_space); assert(err == CCS_RESULT_SUCCESS); err = ccs_configuration_space_sample( @@ -134,18 +135,19 @@ test_create(void) parameters[2] = parameters[0]; err = ccs_create_configuration_space( - "my_config_space", 3, NULL, 0, NULL, &configuration_space); + "my_config_space", 3, NULL, NULL, 0, NULL, + &configuration_space); assert(err == CCS_RESULT_ERROR_INVALID_VALUE); err = ccs_create_configuration_space( - "my_config_space", 3, parameters, 0, NULL, + "my_config_space", 3, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_ERROR_INVALID_PARAMETER); parameters[2] = parameter3; err = ccs_create_configuration_space( - "my_config_space", 3, parameters, 0, NULL, + "my_config_space", 3, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -186,7 +188,7 @@ test_sample(void) assert(err == CCS_RESULT_SUCCESS); err = ccs_create_configuration_space( - "my_config_space", 4, parameters, 0, NULL, + "my_config_space", 4, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -250,7 +252,7 @@ test_configuration_deserialize(void) parameters[2] = create_numerical("param3"); err = ccs_create_configuration_space( - "my_config_space", 3, parameters, 0, NULL, + "my_config_space", 3, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -316,6 +318,7 @@ void test_deserialize(void) { ccs_parameter_t parameters[3]; + ccs_expression_t conditions[3] = {NULL, NULL, NULL}; ccs_configuration_space_t space, space_ref; ccs_expression_t expression, expressions[3]; char *buff; @@ -333,30 +336,30 @@ test_deserialize(void) CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[0]), ccs_float(0.0), &expression); assert(err == CCS_RESULT_SUCCESS); - err = ccs_create_configuration_space( - "my_config_space", 3, parameters, 1, &expression, &space); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_release_object(expression); - assert(err == CCS_RESULT_SUCCESS); err = ccs_create_binary_expression( CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[1]), - ccs_float(0.0), &expression); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_configuration_space_set_condition(space, 2, expression); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_release_object(expression); + ccs_float(0.0), &conditions[2]); assert(err == CCS_RESULT_SUCCESS); err = ccs_create_binary_expression( CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[2]), - ccs_float(0.0), &expression); + ccs_float(0.0), &conditions[0]); assert(err == CCS_RESULT_SUCCESS); - err = ccs_configuration_space_set_condition(space, 0, expression); + + err = ccs_create_configuration_space( + "my_config_space", 3, parameters, conditions, 1, &expression, + &space); assert(err == CCS_RESULT_SUCCESS); err = ccs_release_object(expression); assert(err == CCS_RESULT_SUCCESS); + err = ccs_release_object(conditions[0]); + assert(err == CCS_RESULT_SUCCESS); + + err = ccs_release_object(conditions[2]); + assert(err == CCS_RESULT_SUCCESS); + for (size_t i = 0; i < 3; i++) { err = ccs_release_object(parameters[i]); assert(err == CCS_RESULT_SUCCESS); diff --git a/tests/test_distribution_space.c b/tests/test_distribution_space.c index 2e5ad7fe..3bb7f60e 100644 --- a/tests/test_distribution_space.c +++ b/tests/test_distribution_space.c @@ -129,7 +129,7 @@ test_create(void) parameters[2] = create_dummy_parameter("param3"); err = ccs_create_configuration_space( - "my_config_space", 3, parameters, 0, NULL, + "my_config_space", 3, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -176,7 +176,7 @@ test_set_distribution(void) parameters[2] = create_dummy_parameter("param3"); err = ccs_create_configuration_space( - "my_config_space", 3, parameters, 0, NULL, + "my_config_space", 3, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -323,7 +323,7 @@ test_deserialize(void) parameters[2] = create_numerical("param3"); err = ccs_create_configuration_space( - "my_config_space", 3, parameters, 0, NULL, &space); + "my_config_space", 3, parameters, NULL, 0, NULL, &space); assert(err == CCS_RESULT_SUCCESS); err = ccs_create_distribution_space(space, &distrib_space); diff --git a/tests/test_expression.c b/tests/test_expression.c index 3c3c3696..650b889c 100644 --- a/tests/test_expression.c +++ b/tests/test_expression.c @@ -168,7 +168,7 @@ test_equal_numerical(void) parameters[1] = create_dummy_numerical("param2"); err = ccs_create_configuration_space( - "my_config_space", 2, parameters, 0, NULL, + "my_config_space", 2, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -223,7 +223,7 @@ test_equal_categorical(void) parameters[0] = create_dummy_categorical("param1"); parameters[1] = create_dummy_categorical("param2"); err = ccs_create_configuration_space( - "my_config_space", 2, parameters, 0, NULL, + "my_config_space", 2, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -264,7 +264,7 @@ test_equal_ordinal(void) parameters[0] = create_dummy_ordinal("param1"); parameters[1] = create_dummy_ordinal("param2"); err = ccs_create_configuration_space( - "my_config_space", 2, parameters, 0, NULL, + "my_config_space", 2, parameters, NULL, 0, NULL, &configuration_space); assert(err == CCS_RESULT_SUCCESS); @@ -904,7 +904,7 @@ test_check_context(void) parameters[1] = parameter2; err = ccs_create_configuration_space( - "space", 2, parameters, 0, NULL, &space); + "space", 2, parameters, NULL, 0, NULL, &space); assert(err == CCS_RESULT_SUCCESS); err = ccs_create_binary_expression( diff --git a/tests/test_forbidden.c b/tests/test_forbidden.c index 0eeb3411..7cebdb81 100644 --- a/tests/test_forbidden.c +++ b/tests/test_forbidden.c @@ -35,7 +35,7 @@ test_simple(void) ccs_float(0.0), &expression); assert(err == CCS_RESULT_SUCCESS); err = ccs_create_configuration_space( - "space", 2, parameters, 1, &expression, &space); + "space", 2, parameters, NULL, 1, &expression, &space); assert(err == CCS_RESULT_SUCCESS); for (int i = 0; i < 100; i++) { @@ -97,6 +97,7 @@ void test_combined(void) { ccs_parameter_t parameters[3]; + ccs_expression_t conditions[3] = {NULL, NULL, NULL}; ccs_configuration_space_t space; ccs_expression_t expression; ccs_configuration_t configuration; @@ -112,30 +113,28 @@ test_combined(void) CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[0]), ccs_float(0.0), &expression); assert(err == CCS_RESULT_SUCCESS); - err = ccs_create_configuration_space( - "space", 3, parameters, 1, &expression, &space); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_release_object(expression); - assert(err == CCS_RESULT_SUCCESS); err = ccs_create_binary_expression( CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[1]), - ccs_float(0.0), &expression); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_configuration_space_set_condition(space, 2, expression); - assert(err == CCS_RESULT_SUCCESS); - err = ccs_release_object(expression); + ccs_float(0.0), &conditions[2]); assert(err == CCS_RESULT_SUCCESS); err = ccs_create_binary_expression( CCS_EXPRESSION_TYPE_LESS, ccs_object(parameters[2]), - ccs_float(0.0), &expression); + ccs_float(0.0), &conditions[0]); assert(err == CCS_RESULT_SUCCESS); - err = ccs_configuration_space_set_condition(space, 0, expression); + + err = ccs_create_configuration_space( + "space", 3, parameters, conditions, 1, &expression, &space); assert(err == CCS_RESULT_SUCCESS); err = ccs_release_object(expression); assert(err == CCS_RESULT_SUCCESS); + err = ccs_release_object(conditions[2]); + assert(err == CCS_RESULT_SUCCESS); + err = ccs_release_object(conditions[0]); + assert(err == CCS_RESULT_SUCCESS); + for (int i = 0; i < 100; i++) { ccs_float_t f; ccs_bool_t check; diff --git a/tests/test_random_features_tuner.c b/tests/test_random_features_tuner.c index 75257104..28adf36b 100644 --- a/tests/test_random_features_tuner.c +++ b/tests/test_random_features_tuner.c @@ -40,7 +40,7 @@ test(void) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); parameter3 = create_numerical("z", -CCS_INFINITY, CCS_INFINITY); @@ -264,7 +264,7 @@ test_evaluation_deserialize(void) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); err = ccs_configuration_space_sample(cspace, NULL, &configuration); assert(err == CCS_RESULT_SUCCESS); diff --git a/tests/test_random_tuner.c b/tests/test_random_tuner.c index 26fce85d..ae344448 100644 --- a/tests/test_random_tuner.c +++ b/tests/test_random_tuner.c @@ -36,7 +36,7 @@ test(void) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); parameter3 = create_numerical("z", -CCS_INFINITY, CCS_INFINITY); @@ -178,7 +178,7 @@ test_evaluation_deserialize(void) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); err = ccs_configuration_space_sample(cspace, NULL, &configuration); assert(err == CCS_RESULT_SUCCESS); diff --git a/tests/test_user_defined_features_tuner.c b/tests/test_user_defined_features_tuner.c index 6901f963..a1f847bf 100644 --- a/tests/test_user_defined_features_tuner.c +++ b/tests/test_user_defined_features_tuner.c @@ -181,7 +181,7 @@ test(void) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); parameter3 = create_numerical("z", -CCS_INFINITY, CCS_INFINITY); diff --git a/tests/test_user_defined_tuner.c b/tests/test_user_defined_tuner.c index cc3464d3..158be4e6 100644 --- a/tests/test_user_defined_tuner.c +++ b/tests/test_user_defined_tuner.c @@ -165,7 +165,7 @@ test(void) parameters[1] = parameter2 = create_numerical("y", -5.0, 5.0); err = ccs_create_configuration_space( - "2dplane", 2, parameters, 0, NULL, &cspace); + "2dplane", 2, parameters, NULL, 0, NULL, &cspace); assert(err == CCS_RESULT_SUCCESS); parameter3 = create_numerical("z", -CCS_INFINITY, CCS_INFINITY);