Commit 6ae4708d authored by Brice Videau's avatar Brice Videau
Browse files

Started implementing expressions.

parent f41c5245
......@@ -70,6 +70,7 @@ enum ccs_data_type_e {
CCS_NONE,
CCS_INTEGER,
CCS_FLOAT,
CCS_BOOLEAN,
CCS_STRING,
CCS_OBJECT,
CCS_DATA_TYPE_MAX,
......
......@@ -6,63 +6,73 @@ extern "C" {
#endif
enum ccs_expression_type_e {
CCS_EQUALS,
CCS_LESS_THAN,
CCS_GREATER_THAN,
CCS_OR = 0,
CCS_AND,
CCS_EQUAL,
CCS_NOT_EQUAL,
CCS_LESS,
CCS_GREATER,
CCS_LESS_OR_EQUAL,
CCS_GREATER_OR_EQUAL,
CCS_IN,
CCS_ADD,
CCS_SUBSTRACT,
CCS_MULTIPLY,
CCS_DIVIDE,
CCS_MODULO,
CCS_POSITIVE,
CCS_NEGATIVE,
CCS_NOT,
CCS_AND,
CCS_OR,
CCS_CONDITION_TYPE_MAX,
CCS_CONDITION_FORCE_32BIT = INT_MAX
CCS_LIST,
CCS_EXPRESSION_TYPE_MAX,
CCS_EXPRESSION_FORCE_32BIT = INT_MAX
};
typedef enum ccs_expression_type_e ccs_expression_type_t;
// Expressions
extern ccs_error_t
ccs_create_binary_expression(ccs_expression_type_t expresion_type,
ccs_datum_t value_left,
ccs_datum_t value_right,
ccs_expression_t *expression_ret);
extern ccs_error_t
ccs_create_equals_expression(ccs_datum_t value_left,
ccs_datum_t value_right,
ccs_expression_t *expression_ret);
// Precedence classes: least from most (taken from C)
// Needed to parentheses correctly
// 0 : OR
// 1 : AND
// 2 : EQUAL, NOT_EQUAL
// 3 : LESS, GREATER, LESS_OR_EQUAL, GREATER_OR_EQUAL
// 4 : IN
// 5 : ADD, SUBSTRACT
// 6 : MULTIPLY, DIVIDE, MODULO
// 7 : POSITIVE, NEGATIVE, NOT
// max - 1: LIST
// max : LITERAL, VARIABLE, HYPERPARAMETER
extern ccs_error_t
ccs_create_less_than_expression(ccs_datum_t value_left,
ccs_datum_t value_right,
ccs_expression_t *expression_ret);
// One for each expression type:
extern const int ccs_expression_precedence[];
extern ccs_error_t
ccs_create_greater_than_expression(ccs_datum_t value_left,
ccs_datum_t value_right,
ccs_expression_t *expression_ret);
extern const char *ccs_expression_symbols[];
extern const int ccs_expression_arity[];
// Expressions
extern ccs_error_t
ccs_create_in_expression(size_t num_values,
ccs_datum_t *values,
ccs_expression_t *expression_ret);
extern ccs_error_t
ccs_create_not_expression(ccs_expression_t expression,
ccs_expression_t *expression_ret);
ccs_create_binary_expression(ccs_expression_type_t expresion_type,
ccs_datum_t node_left,
ccs_datum_t node_right,
ccs_expression_t *expression_ret);
extern ccs_error_t
ccs_create_conjunction_expression(ccs_expression_type_t expresion_type,
size_t num_expressions,
ccs_expression_t *expressions,
ccs_expression_t *expressions_ret);
ccs_create_unary_expression(ccs_expression_type_t expression_type,
ccs_datum_t node,
ccs_expression_t *expression_ret);
extern ccs_error_t
ccs_create_and_expression(size_t num_expressions,
ccs_expression_t *expressions,
ccs_expression_t *expressions_ret);
ccs_create_epression(ccs_expression_type_t expression_type,
size_t num_nodes,
ccs_datum_t *nodes,
ccs_expression_t *expression_ret);
extern ccs_error_t
ccs_create_or_expression(size_t num_expressions,
ccs_expression_t *expressions,
ccs_expression_t *expressions_ret);
ccs_eval_expression(ccs_expression_t expression,
ccs_configuration_space_t context,
ccs_datum_t *values,
ccs_datum_t *result);
// Conditions
extern ccs_error_t
......
......@@ -63,6 +63,12 @@ ccs_configuration_space_get_hyperparameter_index_by_name(
const char *name,
size_t *index_ret);
extern ccs_error_t
ccs_configuration_space_get_hyperparameter_index(
ccs_configuration_space_t configuration_space,
ccs_hyperparameter_t hyperparameter,
size_t *index_ret);
extern ccs_error_t
ccs_configuration_space_get_hyperparameters(ccs_configuration_space_t configuration_space,
size_t num_hyperparameters,
......
......@@ -26,6 +26,8 @@ libcconfigspace_la_SOURCES = \
configuration_space.c \
configuration_space_internal.h \
configuration.c \
configuration_internal.h
configuration_internal.h \
condition.c \
condition_internal.h
@VALGRIND_CHECK_RULES@
#include "cconfigspace_internal.h"
#include "condition_internal.h"
#include <string.h>
const int ccs_expression_precedence[] = {
0,
1,
2, 2,
3, 3, 3, 3,
4,
5, 5,
6, 6, 6,
7, 7, 7,
8
};
const char *ccs_expression_symbols[] = {
"||",
"&&",
"==", "!=",
"<", ">", "<=", ">=",
"#",
"+", "-",
"*", "/", "%",
"+", "-", "!",
NULL
};
const int ccs_expression_arity[] = {
2,
2,
2, 2,
2, 2, 2, 2,
2,
2, 2,
2, 2, 2,
1, 1, 1,
-1
};
static inline _ccs_expression_ops_t *
ccs_expression_get_ops(ccs_expression_t expression) {
return (_ccs_expression_ops_t *)expression->obj.ops;
}
static ccs_error_t
_ccs_expression_del(ccs_object_t o) {
ccs_expression_t d = (ccs_expression_t)o;
_ccs_expression_data_t *data = d->data;
for (size_t i = 0; i < data->num_nodes; i++)
if (data->nodes[i].type == CCS_OBJECT)
ccs_release_object(data->nodes[i].value.o);
return CCS_SUCCESS;
}
static inline ccs_error_t
_ccs_expr_datum_eval(ccs_datum_t *d,
ccs_configuration_space_t context,
ccs_datum_t *values,
ccs_datum_t *result) {
ccs_object_type_t t;
size_t index;
ccs_error_t err;
switch (d->type) {
case CCS_NONE:
case CCS_INTEGER:
case CCS_FLOAT:
case CCS_BOOLEAN:
case CCS_STRING:
*result = *d;
break;
case CCS_OBJECT:
err = ccs_object_get_type(d->value.o, &t);
if (err)
return err;
switch (t) {
case CCS_EXPRESSION:
return ccs_eval_expression((ccs_expression_t)(d->value.o),
context, values, result);
break;
case CCS_HYPERPARAMETER:
err = ccs_configuration_space_get_hyperparameter_index(
context, (ccs_hyperparameter_t)(d->value.o), &index);
if (err)
return err;
*result = values[index];
break;
default:
return CCS_INVALID_OBJECT;
}
break;
default:
return CCS_INVALID_VALUE;
}
return CCS_SUCCESS;
}
#define eval_left_right(data, context, values, left, right) { \
ccs_error_t err; \
err = _ccs_expr_datum_eval(data->nodes, context, values, &left); \
if (err) \
return err; \
err = _ccs_expr_datum_eval(data->nodes + 1, context, values, &right); \
if (err) \
return err; \
}
static ccs_error_t
_ccs_expr_or_eval(_ccs_expression_data_t *data,
ccs_configuration_space_t context,
ccs_datum_t *values,
ccs_datum_t *result) {
ccs_datum_t left;
ccs_datum_t right;
eval_left_right(data, context, values, left, right);
if (left.type != CCS_BOOLEAN || right.type != CCS_BOOLEAN)
return -CCS_INVALID_VALUE;
result->type = CCS_BOOLEAN;
result->value.i = (left.value.i || right.value.i) ? CCS_TRUE : CCS_FALSE;
return CCS_SUCCESS;
}
static _ccs_expression_ops_t _ccs_expr_or_ops = {
{ &_ccs_expression_del },
&_ccs_expr_or_eval
};
static ccs_error_t
_ccs_expr_and_eval(_ccs_expression_data_t *data,
ccs_configuration_space_t context,
ccs_datum_t *values,
ccs_datum_t *result) {
ccs_datum_t left;
ccs_datum_t right;
eval_left_right(data, context, values, left, right);
if (left.type != CCS_BOOLEAN || right.type != CCS_BOOLEAN)
return -CCS_INVALID_VALUE;
result->type = CCS_BOOLEAN;
result->value.i = (left.value.i && right.value.i) ? CCS_TRUE : CCS_FALSE;
return CCS_SUCCESS;
}
static _ccs_expression_ops_t _ccs_expr_and_ops = {
{ &_ccs_expression_del },
&_ccs_expr_and_eval
};
static inline _ccs_expression_ops_t *
_ccs_expression_ops_broker(ccs_expression_type_t expression_type) {
switch (expression_type) {
case CCS_OR:
return &_ccs_expr_or_ops;
break;
case CCS_AND:
return &_ccs_expr_and_ops;
break;
default:
return NULL;
}
}
ccs_error_t
ccs_create_epression(ccs_expression_type_t expression_type,
size_t num_nodes,
ccs_datum_t *nodes,
ccs_expression_t *expression_ret) {
if (num_nodes && !nodes)
return -CCS_INVALID_VALUE;
if (!expression_ret)
return -CCS_INVALID_VALUE;
int arity = ccs_expression_arity[expression_type];
if (arity >= 0 && num_nodes != (size_t)arity)
return -CCS_INVALID_VALUE;
ccs_error_t err;
size_t size_strs = 0;
for(size_t i = 0; i < num_nodes; i++)
if (nodes[i].type == CCS_STRING) {
if (!nodes[i].value.s)
return -CCS_INVALID_VALUE;
size_strs += strlen(nodes[i].value.s) + 1;
}
uintptr_t mem = (uintptr_t)calloc(1,
sizeof(struct _ccs_expression_s) +
sizeof(struct _ccs_expression_data_s) +
num_nodes*sizeof(ccs_datum_t) +
size_strs);
if (!mem)
return -CCS_ENOMEM;
for(size_t i = 0; i < num_nodes; i++)
if (nodes[i].type == CCS_OBJECT) {
err = ccs_retain_object(nodes[i].value.o);
if (err) {
free((void *)mem);
return err;
}
}
ccs_expression_t expression = (ccs_expression_t)mem;
_ccs_object_init(&(expression->obj), CCS_EXPRESSION,
(_ccs_object_ops_t*)_ccs_expression_ops_broker(expression_type));
_ccs_expression_data_t *expression_data =
(_ccs_expression_data_t *)(mem + sizeof(struct _ccs_expression_s));
expression_data->type = expression_type;
expression_data->num_nodes = num_nodes;
expression_data->nodes = (ccs_datum_t *)(mem +
sizeof(struct _ccs_expression_s) +
sizeof(struct _ccs_expression_data_s));
char *str_pool = (char *)(mem +
sizeof(struct _ccs_expression_s) +
sizeof(struct _ccs_expression_data_s) +
num_nodes*sizeof(ccs_datum_t));
for (size_t i = 0; i < num_nodes; i++) {
if (nodes[i].type == CCS_STRING) {
expression_data->nodes[i].type = CCS_STRING;
expression_data->nodes[i].value.s = str_pool;
strcpy(str_pool, nodes[i].value.s);
str_pool += strlen(nodes[i].value.s) + 1;
} else {
expression_data->nodes[i] = nodes[i];
}
}
expression->data = expression_data;
*expression_ret = expression;
return CCS_SUCCESS;
}
ccs_error_t
ccs_eval_expression(ccs_expression_t expression,
ccs_configuration_space_t context,
ccs_datum_t *values,
ccs_datum_t *result) {
if (!expression || !expression->data)
return CCS_INVALID_OBJECT;
if (!result)
return CCS_INVALID_VALUE;
_ccs_expression_ops_t *ops = ccs_expression_get_ops(expression);
return ops->eval(expression->data, context, values, result);
}
#ifndef _CONDITION_INTERNAL_H
#define _CONDITION_INTERNAL_H
struct _ccs_expression_data_s;
typedef struct _ccs_expression_data_s _ccs_expression_data_t;
struct _ccs_expression_ops_s {
_ccs_object_ops_t obj_ops;
ccs_error_t (*eval)(
_ccs_expression_data_t *data,
ccs_configuration_space_t context,
ccs_datum_t *values,
ccs_datum_t *result);
};
typedef struct _ccs_expression_ops_s _ccs_expression_ops_t;
struct _ccs_expression_s {
_ccs_object_internal_t obj;
_ccs_expression_data_t *data;
};
struct _ccs_expression_data_s {
ccs_expression_type_t type;
size_t num_nodes;
ccs_datum_t *nodes;
};
#endif //_CONDITION_INTERNAL_H
......@@ -16,6 +16,7 @@ _ccs_configuration_space_del(ccs_object_t object) {
ccs_release_object(wrapper->hyperparameter);
}
HASH_CLEAR(hh_name, configuration_space->data->name_hash);
HASH_CLEAR(hh_handle, configuration_space->data->handle_hash);
utarray_free(array);
_ccs_distribution_wrapper_t *dw;
_ccs_distribution_wrapper_t *tmp;
......@@ -201,7 +202,9 @@ ccs_configuration_space_add_hyperparameter(ccs_configuration_space_t configurati
(_ccs_hyperparameter_wrapper_t*)utarray_eltptr(hyperparameters, index);
HASH_ADD_KEYPTR( hh_name, configuration_space->data->name_hash,
name, sz_name, p_hyper_wrapper );
DL_APPEND(configuration_space->data->distribution_list, distrib_wrapper);
HASH_ADD( hh_handle, configuration_space->data->handle_hash,
hyperparameter, sizeof(ccs_hyperparameter_t), p_hyper_wrapper );
DL_APPEND( configuration_space->data->distribution_list, distrib_wrapper );
return CCS_SUCCESS;
errorutarray:
......@@ -308,6 +311,26 @@ ccs_configuration_space_get_hyperparameter_index_by_name(
return CCS_SUCCESS;
}
ccs_error_t
ccs_configuration_space_get_hyperparameter_index(
ccs_configuration_space_t configuration_space,
ccs_hyperparameter_t hyperparameter,
size_t *index_ret) {
if (!configuration_space || !configuration_space->data)
return -CCS_INVALID_OBJECT;
if (!hyperparameter)
return -CCS_INVALID_HYPERPARAMETER;
if (!index_ret)
return -CCS_INVALID_VALUE;
_ccs_hyperparameter_wrapper_t *wrapper;
HASH_FIND(hh_handle, configuration_space->data->handle_hash,
&hyperparameter, sizeof(ccs_hyperparameter_t), wrapper);
if (!wrapper)
return -CCS_INVALID_HYPERPARAMETER;
*index_ret = wrapper->index;
return CCS_SUCCESS;
}
ccs_error_t
ccs_configuration_space_get_hyperparameters(ccs_configuration_space_t configuration_space,
size_t num_hyperparameters
......
......@@ -13,6 +13,7 @@ struct _ccs_hyperparameter_wrapper_s {
size_t index;
const char *name;
UT_hash_handle hh_name;
UT_hash_handle hh_handle;
size_t distribution_index;
_ccs_distribution_wrapper_t *distribution;
};
......@@ -45,6 +46,7 @@ struct _ccs_configuration_space_data_s {
ccs_rng_t rng;
UT_array *hyperparameters;
_ccs_hyperparameter_wrapper_t *name_hash;
_ccs_hyperparameter_wrapper_t *handle_hash;
_ccs_distribution_wrapper_t *distribution_list;
};
......
......@@ -58,6 +58,7 @@ void check_configuration(ccs_configuration_space_t configuration_space,
ccs_configuration_t configuration;
ccs_error_t err;
size_t sz_ret;
size_t index;
ccs_hyperparameter_t *hyperparameters_ret =
(ccs_hyperparameter_t *)malloc(sizeof(ccs_hyperparameter_t)*(sz+1));
const char *name;
......@@ -73,6 +74,10 @@ void check_configuration(ccs_configuration_space_t configuration_space,
&hyperparameter);
assert( err == CCS_SUCCESS );
assert( hyperparameter == hyperparameters[i] );
err = ccs_configuration_space_get_hyperparameter_index(
configuration_space, hyperparameter, &index);
assert( err == CCS_SUCCESS );
assert( index == i);
}
err = ccs_configuration_space_get_hyperparameters(configuration_space, sz + 1,
hyperparameters_ret, &sz_ret);
......
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