Commit 6220c0f6 authored by Brice Videau's avatar Brice Videau
Browse files

Added binding abstraction. Added validation to transient datums.

parent 9f3c6ad8
......@@ -10,6 +10,7 @@ include_ccs_HEADERS = \
cconfigspace/configuration_space.h \
cconfigspace/hyperparameter.h \
cconfigspace/expression.h \
cconfigspace/binding.h \
cconfigspace/configuration.h \
cconfigspace/objective_space.h \
cconfigspace/evaluation.h \
......
......@@ -2,6 +2,7 @@
#define _CCS_BASE_H
#include <limits.h>
#include <math.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
......@@ -37,6 +38,7 @@ typedef struct _ccs_hyperparameter_s *ccs_hyperparameter_t;
typedef struct _ccs_expression_s *ccs_expression_t;
typedef struct _ccs_context_s *ccs_context_t;
typedef struct _ccs_configuration_space_s *ccs_configuration_space_t;
typedef struct _ccs_binding_s *ccs_binding_t;
typedef struct _ccs_configuration_s *ccs_configuration_t;
typedef struct _ccs_objective_space_s *ccs_objective_space_t;
typedef struct _ccs_evaluation_s *ccs_evaluation_t;
......@@ -63,6 +65,7 @@ enum ccs_error_e {
CCS_INACTIVE_HYPERPARAMETER,
CCS_OUT_OF_MEMORY,
CCS_UNSUPPORTED_OPERATION,
CCS_INVALID_EVALUATION,
CCS_ERROR_MAX,
CCS_ERROR_FORCE_32BIT = INT32_MAX
};
......@@ -104,6 +107,8 @@ typedef uint32_t ccs_datum_flags_t;
enum ccs_datum_flag_e {
CCS_FLAG_DEFAULT = 0,
CCS_FLAG_TRANSIENT = (1 << 0),
CCS_FLAG_UNPOOLED = (1 << 1),
CCS_DATUM_FLAG_FORCE_32BIT = INT32_MAX
};
......@@ -213,6 +218,32 @@ ccs_string(const char *v) {
return d;
}
static inline int ccs_datum_cmp(ccs_datum_t a, ccs_datum_t b) {
if (a.type < b.type) {
return -1;
} else if (a.type > b.type) {
return 1;
} else {
switch(a.type) {
case CCS_STRING:
if (a.value.s == b.value.s)
return 0;
else if (!a.value.s)
return -1;
else if (!b.value.s)
return 1;
else
return strcmp(a.value.s, b.value.s);
case CCS_NONE:
case CCS_INACTIVE:
return 0;
break;
default:
return memcmp(&(a.value), &(b.value), sizeof(ccs_value_t));
}
}
}
extern const ccs_datum_t ccs_none;
extern const ccs_datum_t ccs_inactive;
extern const ccs_datum_t ccs_true;
......
#ifndef _CCS_BINDING_H
#define _CCS_BINDING_H
#ifdef __cplusplus
extern "C" {
#endif
extern ccs_result_t
ccs_binding_get_context(ccs_binding_t binding,
ccs_context_t *context_ret);
extern ccs_result_t
ccs_binding_get_user_data(ccs_binding_t binding,
void **user_data_ret);
extern ccs_result_t
ccs_binding_get_value(ccs_binding_t binding,
size_t index,
ccs_datum_t *value_ret);
extern ccs_result_t
ccs_binding_set_value(ccs_binding_t binding,
size_t index,
ccs_datum_t value);
extern ccs_result_t
ccs_binding_get_values(ccs_binding_t binding,
size_t num_values,
ccs_datum_t *values,
size_t *num_values_ret);
extern ccs_result_t
ccs_binding_get_value_by_name(ccs_binding_t binding,
const char *name,
ccs_datum_t *value_ret);
extern ccs_result_t
ccs_binding_hash(ccs_binding_t binding,
ccs_hash_t *hash_ret);
extern ccs_result_t
ccs_binding_cmp(ccs_binding_t binding,
ccs_binding_t other_binding,
int *cmp_ret);
#ifdef __cplusplus
}
#endif
#endif //_CCS_BINDING_H
......@@ -94,6 +94,12 @@ ccs_configuration_space_get_hyperparameters(ccs_configuration_space_t configura
ccs_hyperparameter_t *hyperparameters,
size_t *num_hyperparameters_ret);
extern ccs_result_t
ccs_configuration_space_validate_value(ccs_configuration_space_t configuration_space,
size_t index,
ccs_datum_t value,
ccs_datum_t *value_ret);
extern ccs_result_t
ccs_configuration_space_set_condition(ccs_configuration_space_t configuration_space,
size_t hyperparameter_index,
......
......@@ -50,6 +50,12 @@ ccs_context_get_hyperparameter_indexes(
ccs_hyperparameter_t *hyperparameters,
size_t *indexes);
extern ccs_result_t
ccs_context_validate_value(ccs_context_t context,
size_t index,
ccs_datum_t value,
ccs_datum_t *value_ret);
#ifdef __cplusplus
}
#endif
......
......@@ -65,6 +65,9 @@ ccs_evaluation_get_value_by_name(ccs_evaluation_t evaluation,
const char *name,
ccs_datum_t *value_ret);
extern ccs_result_t
ccs_evaluation_check(ccs_evaluation_t evaluation);
extern ccs_result_t
ccs_evaluation_get_objective_value(ccs_evaluation_t evaluation,
size_t index,
......
......@@ -116,6 +116,19 @@ ccs_hyperparameter_check_values(ccs_hyperparameter_t hyperparameter,
const ccs_datum_t *values,
ccs_bool_t *results);
extern ccs_result_t
ccs_hyperparameter_validate_value(ccs_hyperparameter_t hyperparameter,
ccs_datum_t value,
ccs_datum_t *value_ret,
ccs_bool_t *result_ret);
extern ccs_result_t
ccs_hyperparameter_validate_values(ccs_hyperparameter_t hyperparameter,
size_t num_values,
const ccs_datum_t *values,
ccs_datum_t *values_ret,
ccs_bool_t *results);
extern ccs_result_t
ccs_hyperparameter_convert_samples(ccs_hyperparameter_t hyperparameter,
ccs_bool_t oversampling,
......
......@@ -64,12 +64,34 @@ ccs_objective_space_get_hyperparameter_index(
ccs_hyperparameter_t hyperparameter,
size_t *index_ret);
extern ccs_result_t
ccs_objective_space_get_hyperparameter_indexes(
ccs_objective_space_t objective_space,
size_t num_hyperparameters,
ccs_hyperparameter_t *hyperparameters,
size_t *indexes);
extern ccs_result_t
ccs_objective_space_get_hyperparameters(ccs_objective_space_t objective_space,
size_t num_hyperparameters,
ccs_hyperparameter_t *hyperparameters,
size_t *num_hyperparameters_ret);
extern ccs_result_t
ccs_objective_space_check_evaluation(ccs_objective_space_t objective_space,
ccs_evaluation_t evaluation);
extern ccs_result_t
ccs_objective_space_check_evaluation_values(ccs_objective_space_t objective_space,
size_t num_values,
ccs_datum_t *values);
extern ccs_result_t
ccs_objective_space_validate_value(ccs_objective_space_t objective_space,
size_t index,
ccs_datum_t value,
ccs_datum_t *value_ret);
extern ccs_result_t
ccs_objective_space_add_objective(ccs_objective_space_t objective_space,
ccs_expression_t expression,
......
......@@ -21,6 +21,7 @@ libcconfigspace_la_SOURCES = \
hyperparameter_internal.h \
hyperparameter_numerical.c \
uthash.h \
datum_uthash.h \
datum_hash.h \
hyperparameter_categorical.c \
hyperparameter_discrete.c \
......@@ -29,6 +30,8 @@ libcconfigspace_la_SOURCES = \
context_internal.h \
configuration_space.c \
configuration_space_internal.h \
binding.c \
binding_internal.h \
configuration.c \
configuration_internal.h \
expression.c \
......
#include "cconfigspace_internal.h"
#include "binding_internal.h"
static inline _ccs_binding_ops_t *
ccs_binding_get_ops(ccs_binding_t binding) {
return (_ccs_binding_ops_t *)binding->obj.ops;
}
ccs_result_t
ccs_binding_get_context(ccs_binding_t binding,
ccs_context_t *context_ret) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_get_context(binding, context_ret);
}
ccs_result_t
ccs_binding_get_user_data(ccs_binding_t binding,
void **user_data_ret) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_get_user_data(binding, user_data_ret);
}
ccs_result_t
ccs_binding_get_value(ccs_binding_t binding,
size_t index,
ccs_datum_t *value_ret) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_get_value(binding, index, value_ret);
}
ccs_result_t
ccs_binding_set_value(ccs_binding_t binding,
size_t index,
ccs_datum_t value) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_set_value(binding, index, value);
}
ccs_result_t
ccs_binding_get_values(ccs_binding_t binding,
size_t num_values,
ccs_datum_t *values,
size_t *num_values_ret) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_get_values(binding, num_values, values, num_values_ret);
}
ccs_result_t
ccs_binding_get_value_by_name(ccs_binding_t binding,
const char *name,
ccs_datum_t *value_ret) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_get_value_by_name(binding, name, value_ret);
}
ccs_result_t
ccs_binding_hash(ccs_binding_t binding,
ccs_hash_t *hash_ret) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_hash(binding, hash_ret);
}
ccs_result_t
ccs_binding_cmp(ccs_binding_t binding,
ccs_binding_t other_binding,
int *cmp_ret) {
if (!binding || !binding->data)
return -CCS_INVALID_OBJECT;
return _ccs_binding_cmp(binding, other_binding, cmp_ret);
}
#ifndef _BINDING_INTERNAL_H
#define _BINDING_INTERNAL_H
#include "datum_hash.h"
typedef struct _ccs_binding_data_s _ccs_binding_data_t;
struct _ccs_binding_ops_s {
_ccs_object_ops_t obj_ops;
};
typedef struct _ccs_binding_ops_s _ccs_binding_ops_t;
struct _ccs_binding_data_s {
void *user_data;
ccs_context_t context;
size_t num_values;
ccs_datum_t *values;
};
struct _ccs_binding_s {
_ccs_object_internal_t obj;
_ccs_binding_data_t *data;
};
static inline ccs_result_t
_ccs_binding_get_context(ccs_binding_t binding,
ccs_context_t *context_ret) {
CCS_CHECK_PTR(context_ret);
*context_ret = binding->data->context;
return CCS_SUCCESS;
}
static inline ccs_result_t
_ccs_binding_get_user_data(ccs_binding_t binding,
void **user_data_ret) {
CCS_CHECK_PTR(user_data_ret);
*user_data_ret = binding->data->user_data;
return CCS_SUCCESS;
}
static inline ccs_result_t
_ccs_binding_get_value(ccs_binding_t binding,
size_t index,
ccs_datum_t *value_ret) {
CCS_CHECK_PTR(value_ret);
if (index >= binding->data->num_values)
return -CCS_OUT_OF_BOUNDS;
*value_ret = binding->data->values[index];
return CCS_SUCCESS;
}
static inline ccs_result_t
_ccs_binding_set_value(ccs_binding_t binding,
size_t index,
ccs_datum_t value) {
if (index >= binding->data->num_values)
return -CCS_OUT_OF_BOUNDS;
if (value.flags & CCS_FLAG_TRANSIENT) {
ccs_result_t err = ccs_context_validate_value(
binding->data->context, index, value, &value);
if (unlikely(err))
return err;
}
binding->data->values[index] = value;
return CCS_SUCCESS;
}
static inline ccs_result_t
_ccs_binding_get_values(ccs_binding_t binding,
size_t num_values,
ccs_datum_t *values,
size_t *num_values_ret) {
CCS_CHECK_ARY(num_values, values);
if (!num_values_ret && !values)
return -CCS_INVALID_VALUE;
size_t num = binding->data->num_values;
if (values) {
if (num_values < num)
return -CCS_INVALID_VALUE;
memcpy(values, binding->data->values, num*sizeof(ccs_datum_t));
for (size_t i = num; i < num_values; i++) {
values[i].type = CCS_NONE;
values[i].value.i = 0;
}
}
if (num_values_ret)
*num_values_ret = num;
return CCS_SUCCESS;
}
static inline ccs_result_t
_ccs_binding_get_value_by_name(ccs_binding_t binding,
const char *name,
ccs_datum_t *value_ret) {
CCS_CHECK_PTR(name);
size_t index;
ccs_result_t err;
err = ccs_context_get_hyperparameter_index_by_name(
binding->data->context, name, &index);
if (err)
return err;
*value_ret = binding->data->values[index];
return CCS_SUCCESS;
}
static inline ccs_result_t
_ccs_binding_hash(ccs_binding_t binding,
ccs_hash_t *hash_ret) {
CCS_CHECK_PTR(hash_ret);
_ccs_binding_data_t *data = binding->data;
ccs_hash_t h, ht;
HASH_JEN(&(data->context), sizeof(data->context), h);
HASH_JEN(&(data->num_values), sizeof(data->num_values), ht);
h = _hash_combine(h, ht);
for (size_t i = 0; i < data->num_values; i++) {
ht = _hash_datum(data->values + i);
h = _hash_combine(h, ht);
}
*hash_ret = h;
return CCS_SUCCESS;
}
static inline ccs_result_t
_ccs_binding_cmp(ccs_binding_t binding,
ccs_binding_t other_binding,
int *cmp_ret) {
CCS_CHECK_PTR(cmp_ret);
if (binding == other_binding) {
*cmp_ret = 0;
return CCS_SUCCESS;
}
_ccs_binding_data_t *data = binding->data;
_ccs_binding_data_t *other_data = other_binding->data;
*cmp_ret = data->context < other_data->context ? -1 :
data->context > other_data->context ? 1 : 0;
if (*cmp_ret)
return CCS_SUCCESS;
*cmp_ret = data->num_values < other_data->num_values ? -1 :
data->num_values > other_data->num_values ? 1 : 0;
if (*cmp_ret)
return CCS_SUCCESS;
for (size_t i = 0; i < data->num_values; i++) {
if ( (*cmp_ret = _datum_cmp(data->values + i, other_data->values + i)) )
return CCS_SUCCESS;
}
return CCS_SUCCESS;
}
#endif //_BINDING_INTERNAL_H
#include "cconfigspace_internal.h"
#include "configuration_internal.h"
#include "datum_hash.h"
#include <string.h>
static inline _ccs_configuration_ops_t *
......@@ -50,8 +49,20 @@ ccs_create_configuration(ccs_configuration_space_t configuration_space,
config->data->num_values = num;
config->data->configuration_space = configuration_space;
config->data->values = (ccs_datum_t *)(mem + sizeof(struct _ccs_configuration_s) + sizeof(struct _ccs_configuration_data_s));
if (values)
if (values) {
memcpy(config->data->values, values, num*sizeof(ccs_datum_t));
for (size_t i = 0; i < num_values; i++) {
if (values[i].flags & CCS_FLAG_TRANSIENT) {
err = ccs_configuration_space_validate_value(
configuration_space, i, values[i],
config->data->values + i);
if (unlikely(err)) {
free((void*)mem);
return err;
}
}
}
}
*configuration_ret = config;
return CCS_SUCCESS;
}
......@@ -60,18 +71,16 @@ ccs_result_t
ccs_configuration_get_configuration_space(ccs_configuration_t configuration,
ccs_configuration_space_t *configuration_space_ret) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
CCS_CHECK_PTR(configuration_space_ret);
*configuration_space_ret = configuration->data->configuration_space;
return CCS_SUCCESS;
return _ccs_binding_get_context(
(ccs_binding_t)configuration, (ccs_context_t *)configuration_space_ret);
}
ccs_result_t
ccs_configuration_get_user_data(ccs_configuration_t configuration,
void **user_data_ret) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
CCS_CHECK_PTR(user_data_ret);
*user_data_ret = configuration->data->user_data;
return CCS_SUCCESS;
return _ccs_binding_get_user_data(
(ccs_binding_t)configuration, user_data_ret);
}
ccs_result_t
......@@ -79,11 +88,8 @@ ccs_configuration_get_value(ccs_configuration_t configuration,
size_t index,
ccs_datum_t *value_ret) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
CCS_CHECK_PTR(value_ret);
if (index >= configuration->data->num_values)
return -CCS_OUT_OF_BOUNDS;
*value_ret = configuration->data->values[index];
return CCS_SUCCESS;
return _ccs_binding_get_value(
(ccs_binding_t)configuration, index, value_ret);
}
ccs_result_t
......@@ -91,10 +97,8 @@ ccs_configuration_set_value(ccs_configuration_t configuration,
size_t index,
ccs_datum_t value) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
if (index >= configuration->data->num_values)
return -CCS_OUT_OF_BOUNDS;
configuration->data->values[index] = value;
return CCS_SUCCESS;
return _ccs_binding_set_value(
(ccs_binding_t)configuration, index, value);
}
ccs_result_t
......@@ -103,22 +107,8 @@ ccs_configuration_get_values(ccs_configuration_t configuration,
ccs_datum_t *values,
size_t *num_values_ret) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
CCS_CHECK_ARY(num_values, values);
if (!num_values_ret && !values)
return -CCS_INVALID_VALUE;
size_t num = configuration->data->num_values;
if (values) {
if (num_values < num)
return -CCS_INVALID_VALUE;
memcpy(values, configuration->data->values, num*sizeof(ccs_datum_t));
for (size_t i = num; i < num_values; i++) {
values[i].type = CCS_NONE;
values[i].value.i = 0;
}
}
if (num_values_ret)
*num_values_ret = num;
return CCS_SUCCESS;
return _ccs_binding_get_values(
(ccs_binding_t)configuration, num_values, values, num_values_ret);
}
ccs_result_t
......@@ -126,15 +116,8 @@ ccs_configuration_get_value_by_name(ccs_configuration_t configuration,
const char *name,
ccs_datum_t *value_ret) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
CCS_CHECK_PTR(name);
size_t index;
ccs_result_t err;
err = ccs_configuration_space_get_hyperparameter_index_by_name(
configuration->data->configuration_space, name, &index);
if (err)
return err;
*value_ret = configuration->data->values[index];
return CCS_SUCCESS;
return _ccs_binding_get_value_by_name(
(ccs_binding_t)configuration, name, value_ret);
}
ccs_result_t
......@@ -148,18 +131,7 @@ ccs_result_t
ccs_configuration_hash(ccs_configuration_t configuration,
ccs_hash_t *hash_ret) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
CCS_CHECK_PTR(hash_ret);
_ccs_configuration_data_t *data = configuration->data;
ccs_hash_t h, ht;
HASH_JEN(&(data->configuration_space), sizeof(data->configuration_space), h);
HASH_JEN(&(data->num_values), sizeof(data->num_values), ht);
h = _hash_combine(h, ht);
for (size_t i = 0; i < data->num_values; i++) {
ht = _hash_datum(data->values + i);
h = _hash_combine(h, ht);
}
*hash_ret = h;
return CCS_SUCCESS;
return _ccs_binding_hash((ccs_binding_t)configuration, hash_ret);
}
ccs_result_t
......@@ -168,25 +140,7 @@ ccs_configuration_cmp(ccs_configuration_t configuration,
int *cmp_ret) {
CCS_CHECK_OBJ(configuration, CCS_CONFIGURATION);
CCS_CHECK_OBJ(other_configuration, CCS_CONFIGURATION);
CCS_CHECK_PTR(cmp_ret);
if (configuration == other_configuration) {
*cmp_ret = 0;
return CCS_SUCCESS;
}
_ccs_configuration_data_t *data = configuration->data;
_ccs_configuration_data_t *other_data = other_configuration->data;
*cmp_ret = data->configuration_space < other_data->configuration_space ? -1 :
data->configuration_space > other_data->configuration_space ? 1 : 0;
if (*cmp_ret)