[utils] cartesian product iterator for grid search during model selection

This commit is contained in:
Al
2017-04-03 00:15:31 -04:00
parent 4a72afc712
commit 957aa0c0c9
2 changed files with 114 additions and 0 deletions

91
src/cartesian_product.c Normal file
View File

@@ -0,0 +1,91 @@
#include "cartesian_product.h"
#include <stdarg.h>
cartesian_product_iterator_t *cartesian_product_iterator_new_vargs(size_t n, va_list args) {
cartesian_product_iterator_t *iter = malloc(sizeof(cartesian_product_iterator_t));
if (iter == NULL) return NULL;
iter->lengths = uint32_array_new_size(n);
if (iter->lengths == NULL) {
goto exit_iter_created;
}
size_t remaining = 1;
for (size_t i = 0; i < n; i++) {
uint32_t arg = va_arg(args, uint32_t);
uint32_array_push(iter->lengths, arg);
if (arg > 0) {
remaining *= arg;
}
}
iter->remaining = remaining;
iter->state = uint32_array_new_zeros(n);
if (iter->state == NULL) {
goto exit_iter_created;
}
return iter;
exit_iter_created:
cartesian_product_iterator_destroy(iter);
return NULL;
}
cartesian_product_iterator_t *cartesian_product_iterator_new(size_t n, ...) {
va_list args;
va_start(args, n);
cartesian_product_iterator_t *iter = cartesian_product_iterator_new_vargs(n, args);
va_end(args);
return iter;
}
uint32_t *cartesian_product_iterator_start(cartesian_product_iterator_t *self) {
return self->state->a;
}
bool cartesian_product_iterator_done(cartesian_product_iterator_t *self) {
return self->remaining == 0;
}
uint32_t *cartesian_product_iterator_next(cartesian_product_iterator_t *self) {
if (self == NULL) return NULL;
uint32_t *lengths = self->lengths->a;
uint32_t *state = self->state->a;
if (self->remaining > 0) {
ssize_t i;
ssize_t n = self->lengths->n;
for (i = n - 1; i >= 0; i--) {
state[i]++;
if (state[i] == lengths[i]) {
state[i] = 0;
} else {
self->remaining--;
break;
}
}
if (i < 0) {
self->remaining = 0;
}
} else {
return NULL;
}
return state;
}
void cartesian_product_iterator_destroy(cartesian_product_iterator_t *self) {
if (self == NULL) return;
if (self->lengths != NULL) {
uint32_array_destroy(self->lengths);
}
if (self->state != NULL) {
uint32_array_destroy(self->state);
}
free(self);
}