Commit cb6cc91a authored by Brice Videau's avatar Brice Videau
Browse files

Added a sample of a C application calling a ruby tuner via the API.

parent 816c6c18
ACLOCAL_AMFLAGS = -I m4
SUBDIRS = src include tests
SUBDIRS = src include tests samples
pkgconfigdir = $(libdir)/pkgconfig
pkgconfig_DATA = cconfigspace.pc
......
......@@ -169,7 +169,7 @@ module CCS
}
askwrapper = lambda { |data, count, p_configurations, p_count|
begin
configurations, count_ret = ask.call(data, p_configurations.null? ? 0 : count)
configurations, count_ret = ask.call(data, p_configurations.null? ? nil : count)
raise CCSError, :CCS_INVALID_VALUE if !p_configurations.null? && count < count_ret
if !p_configurations.null?
configurations.each_with_index { |c, i|
......
......@@ -51,7 +51,7 @@ class CConfigSpaceTestTuner < Minitest::Test
optimums = []
del = lambda { |data| nil }
ask = lambda { |data, count|
if count > 0
if count
cs = CCS::ConfigurationSpace::from_handle(data[:common_data][:configuration_space])
[cs.samples(count), count]
else
......
......@@ -22,6 +22,9 @@ AC_PROG_CC_STDC
AC_TYPE_SIZE_T
AC_HEADER_ASSERT
#
PKG_CHECK_MODULES([RUBY], [ruby >= 2.3])
#check for libraries
AC_CHECK_LIB([m],[cos])
AC_CHECK_LIB([gslcblas],[cblas_dgemm])
......@@ -36,8 +39,10 @@ AX_VALGRIND_CHECK
AC_CONFIG_HEADERS([src/config.h])
AC_CONFIG_FILES([Makefile
include/Makefile
src/Makefile
tests/Makefile
cconfigspace.pc])
include/Makefile
src/Makefile
tests/Makefile
samples/Makefile
cconfigspace.pc])
AC_CONFIG_LINKS([samples/test_ruby.rb:samples/test_ruby.rb])
AC_OUTPUT
AM_COLOR_TESTS = yes
AM_CFLAGS = -I$(top_srcdir)/include -Wall -Werror -Wpedantic $(RUBY_CFLAGS)
AM_LDFLAGS = ../src/libcconfigspace.la $(RUBY_LIBS)
CCONFIGSPACE_TESTS = \
test_ruby
# unit tests
UNIT_TESTS = \
$(CCONFIGSPACE_TESTS)
# all tests
TEST_PROGS = $(UNIT_TESTS)
check_PROGRAMS = $(TEST_PROGS)
TESTS = $(TEST_PROGS)
#include <stdlib.h>
#include <assert.h>
#include <cconfigspace.h>
#include <string.h>
#include <ruby.h>
ccs_hyperparameter_t create_numerical(const char * name, double lower, double upper) {
ccs_hyperparameter_t hyperparameter;
ccs_result_t err;
err = ccs_create_numerical_hyperparameter(name, CCS_NUM_FLOAT,
CCSF(lower), CCSF(upper),
CCSF(0.0), CCSF(0),
NULL, &hyperparameter);
assert( err == CCS_SUCCESS );
return hyperparameter;
}
void create_problem(ccs_configuration_space_t *cs, ccs_objective_space_t *os) {
ccs_hyperparameter_t hyperparameter1, hyperparameter2;
ccs_hyperparameter_t hyperparameter3;
ccs_configuration_space_t cspace;
ccs_objective_space_t ospace;
ccs_expression_t expression;
ccs_result_t err;
hyperparameter1 = create_numerical("x", -5.0, 5.0);
hyperparameter2 = create_numerical("y", -5.0, 5.0);
err = ccs_create_configuration_space("2dplane", NULL, &cspace);
assert( err == CCS_SUCCESS );
err = ccs_configuration_space_add_hyperparameter(cspace, hyperparameter1, NULL);
assert( err == CCS_SUCCESS );
err = ccs_configuration_space_add_hyperparameter(cspace, hyperparameter2, NULL);
assert( err == CCS_SUCCESS );
hyperparameter3 = create_numerical("z", -CCS_INFINITY, CCS_INFINITY);
err = ccs_create_variable(hyperparameter3, &expression);
assert( err == CCS_SUCCESS );
err = ccs_create_objective_space("height", NULL, &ospace);
assert( err == CCS_SUCCESS );
err = ccs_objective_space_add_hyperparameter(ospace, hyperparameter3);
assert( err == CCS_SUCCESS );
err = ccs_objective_space_add_objective(ospace, expression, CCS_MINIMIZE);
assert( err == CCS_SUCCESS );
err = ccs_release_object(hyperparameter1);
assert( err == CCS_SUCCESS );
err = ccs_release_object(hyperparameter2);
assert( err == CCS_SUCCESS );
err = ccs_release_object(hyperparameter3);
assert( err == CCS_SUCCESS );
err = ccs_release_object(&expression);
assert( err == CCS_SUCCESS );
*cs = cspace;
*os = ospace;
}
void test_tuner(ccs_tuner_t tuner, ccs_objective_space_t ospace) {
ccs_result_t err;
for (size_t i = 0; i < 100; i++) {
ccs_datum_t values[2], res;
ccs_configuration_t configuration;
ccs_evaluation_t evaluation;
err = ccs_tuner_ask(tuner, 1, &configuration, NULL);
assert( err == CCS_SUCCESS );
err = ccs_configuration_get_values(configuration, 2, values, NULL);
assert( err == CCS_SUCCESS );
res = ccs_float((values[0].value.f - 1)*(values[0].value.f - 1) +
(values[1].value.f - 2)*(values[1].value.f - 2));
ccs_create_evaluation(ospace, configuration, CCS_SUCCESS, 1, &res, NULL, &evaluation);
err = ccs_tuner_tell(tuner, 1, &evaluation);
assert( err == CCS_SUCCESS );
err = ccs_release_object(configuration);
assert( err == CCS_SUCCESS );
err = ccs_release_object(evaluation);
assert( err == CCS_SUCCESS );
}
size_t count;
ccs_evaluation_t history[100];
ccs_datum_t min = ccs_float(INFINITY);
err = ccs_tuner_get_history(tuner, 100, history, &count);
assert( err == CCS_SUCCESS );
assert( count == 100 );
for (size_t i = 0; i < 100; i++) {
ccs_datum_t res;
err = ccs_evaluation_get_objective_value(history[i], 0, &res);
assert( err == CCS_SUCCESS );
if (res.value.f < min.value.f)
min.value.f = res.value.f;
}
ccs_evaluation_t evaluation;
ccs_datum_t res;
err = ccs_tuner_get_optimums(tuner, 1, &evaluation, NULL);
assert( err == CCS_SUCCESS );
err = ccs_evaluation_get_objective_value(evaluation, 0, &res);
assert( res.value.f == min.value.f );
}
void test() {
ccs_tuner_t t;
ccs_configuration_space_t cs;
ccs_objective_space_t os;
ccs_result_t err;
create_problem(&cs, &os);
ruby_init();
ruby_init_loadpath();
ruby_script("test_ruby");
int state;
rb_eval_string_protect("require_relative './test_ruby.rb'", &state);
if (state) {
ruby_cleanup(state);
return;
}
VALUE tuner;
VALUE top_self;
top_self = rb_eval_string("self");
tuner = rb_funcall(top_self, rb_intern("create_test_tuner"),
2, ULL2NUM((uintptr_t)cs), ULL2NUM((uintptr_t)os));
t = (ccs_tuner_t)NUM2ULL(rb_funcall(rb_funcall(tuner, rb_intern("handle"), 0), rb_intern("to_i"), 0));
ccs_retain_object(t);
test_tuner(t, os);
err = ccs_release_object(t);
assert( err == CCS_SUCCESS );
err = ccs_release_object(os);
assert( err == CCS_SUCCESS );
err = ccs_release_object(cs);
assert( err == CCS_SUCCESS );
ruby_cleanup(0);
}
int main() {
ccs_init();
test();
return 0;
}
require 'rubygems'
require_relative '../bindings/ruby/lib/cconfigspace'
class TestTuner < CCS::UserDefinedTuner
def initialize(cs, os)
@history = []
@optimums = []
del = lambda { |data| nil }
ask = lambda { |data, count|
if count
cs = CCS::ConfigurationSpace::from_handle(data[:common_data][:configuration_space])
[cs.samples(count), count]
else
[nil, 1]
end
}
tell = lambda { |data, evaluations|
@history += evaluations
evaluations.each { |e|
discard = false
@optimums = @optimums.collect { |o|
unless discard
case e.cmp(o)
when :CCS_EQUIVALENT, :CCS_WORSE
discard = true
o
when :CCS_NOT_COMPARABLE
o
else
nil
end
else
o
end
}.compact
@optimums.push(e) unless discard
}
}
get_history = lambda { |data|
@history
}
get_optimums = lambda { |data|
@optimums
}
super(name: "tuner", configuration_space: cs, objective_space: os, del: del, ask: ask, tell: tell, get_optimums: get_optimums, get_history: get_history)
end
end
def create_test_tuner(cs_ptr, os_ptr)
cs_handle = FFI::Pointer::new(cs_ptr)
os_handle = FFI::Pointer::new(os_ptr)
TestTuner::new(CCS::ConfigurationSpace.from_handle(cs_handle),
CCS::ObjectiveSpace.from_handle(os_handle))
end
def create_tuning_problem
cs = CCS::ConfigurationSpace::new(name: "cspace")
h1 = CCS::NumericalHyperparameter::new(lower: -5.0, upper: 5.0)
h2 = CCS::NumericalHyperparameter::new(lower: -5.0, upper: 5.0)
h3 = CCS::NumericalHyperparameter::new(lower: -5.0, upper: 5.0)
cs.add_hyperparameters [h1, h2, h3]
os = CCS::ObjectiveSpace::new(name: "ospace")
v1 = CCS::NumericalHyperparameter::new(lower: -Float::INFINITY, upper: Float::INFINITY)
v2 = CCS::NumericalHyperparameter::new(lower: -Float::INFINITY, upper: Float::INFINITY)
os.add_hyperparameters [v1, v2]
e1 = CCS::Variable::new(hyperparameter: v1)
e2 = CCS::Variable::new(hyperparameter: v2)
os.add_objectives( [e1, e2] )
[cs, os]
end
......@@ -3,7 +3,7 @@ AM_COLOR_TESTS = yes
AM_CFLAGS = -I$(top_srcdir)/include -Wall -Werror -Wpedantic
AM_LDFLAGS = ../src/libcconfigspace.la
RNG_TESTS = \
CCONFIGSPACE_TESTS = \
test_rng \
test_interval \
test_uniform_distribution \
......@@ -21,11 +21,11 @@ RNG_TESTS = \
# unit tests
UNIT_TESTS = \
$(RNG_TESTS)
$(CCONFIGSPACE_TESTS)
# all tests
TST_PROGS = $(UNIT_TESTS)
check_PROGRAMS = $(TST_PROGS)
TESTS = $(TST_PROGS)
TEST_PROGS = $(UNIT_TESTS)
check_PROGRAMS = $(TEST_PROGS)
TESTS = $(TEST_PROGS)
@VALGRIND_CHECK_RULES@
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment