From 0f544be878f72b09d516a64c60e3cbd66f7cfd81 Mon Sep 17 00:00:00 2001 From: Paul Duncan Date: Sun, 3 Feb 2019 21:12:11 -0500 Subject: add km_init(), refactor existing init --- Makefile | 2 +- km-init-rand.c | 5 +++- km-init-type.c | 32 ----------------------- km-init.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ km.h | 51 ++++++++++++++++++------------------- main.c | 16 +++--------- 6 files changed, 112 insertions(+), 74 deletions(-) delete mode 100644 km-init-type.c create mode 100644 km-init.c diff --git a/Makefile b/Makefile index f3a71d5..cfb7ae2 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ APP=km-test CFLAGS=-W -Wall -Wextra -Werror -pedantic -std=c11 -O2 OBJS=km-set.o km-draw.o km-load.o km-find.o km-rand.o km-solve.o \ - km-init-type.o km-init-rand.o km-init-forgy.o main.o + km-init-rand.o km-init-forgy.o km-init.o main.o LIBS=-lm .PHONY=all clean diff --git a/km-init-rand.c b/km-init-rand.c index f9d6eb6..c6000bd 100644 --- a/km-init-rand.c +++ b/km-init-rand.c @@ -9,9 +9,12 @@ bool km_init_rand( km_set_t * const cs, const size_t num_clusters, - const size_t num_floats, + const km_set_t * const set, km_rand_t * const rs ) { + // get number of floats from data set + const size_t num_floats = set->shape.num_floats; + // init cluster shape const km_shape_t shape = { .num_floats = num_floats, diff --git a/km-init-type.c b/km-init-type.c deleted file mode 100644 index 27fc1ee..0000000 --- a/km-init-type.c +++ /dev/null @@ -1,32 +0,0 @@ -#include // size_t -#include // strcmp() -#include "km.h" - -static const struct { - const km_init_type_t type; - const char * const name; -} TYPES[] = {{ - .name = "rand", - .type = KM_INIT_TYPE_RAND, -}, { - .name = "forgy", - .type = KM_INIT_TYPE_FORGY, -}}; - -#define NUM_TYPES (sizeof(TYPES) / sizeof(TYPES[0])) - -km_init_type_t -km_get_init_type( - const char * const s -) { - // find init method - for (size_t i = 0; i < NUM_TYPES; i++) { - if (!strcmp(s, TYPES[i].name)) { - // return type - return TYPES[i].type; - } - } - - // return failure - return KM_INIT_TYPE_LAST; -} diff --git a/km-init.c b/km-init.c new file mode 100644 index 0000000..f04fca0 --- /dev/null +++ b/km-init.c @@ -0,0 +1,80 @@ +#include // bool +#include // size_t +#include // strcmp() +#include "util.h" +#include "km.h" + +typedef bool (*km_init_fn_t)( + km_set_t *, + const size_t, + const km_set_t *, + km_rand_t * +); + +bool km_init_rand(km_set_t *, const size_t, const km_set_t *, km_rand_t *); +bool km_init_forgy(km_set_t *, const size_t, const km_set_t *, km_rand_t *); + +static const struct { + const km_init_type_t type; + const char * const name; + const km_init_fn_t init; +} TYPES[] = {{ + .name = "rand", + .type = KM_INIT_TYPE_RAND, + .init = km_init_rand, +}, { + .name = "forgy", + .type = KM_INIT_TYPE_FORGY, + .init = km_init_forgy, +}}; + +#define NUM_TYPES (sizeof(TYPES) / sizeof(TYPES[0])) + +km_init_type_t +km_init_get_type( + const char * const s +) { + // find init method + for (size_t i = 0; i < NUM_TYPES; i++) { + if (!strcmp(s, TYPES[i].name)) { + // return type + return TYPES[i].type; + } + } + + // return failure + return KM_INIT_TYPE_LAST; +} + +static km_init_fn_t +get_init_func( + const km_init_type_t type +) { + // find init method + for (size_t i = 0; i < NUM_TYPES; i++) { + if (type == TYPES[i].type) { + // return init func + return TYPES[i].init; + } + } + + // return failure + return NULL; +} + +bool +km_init( + km_set_t * const cs, + const km_init_type_t init_type, + const size_t num_clusters, + const km_set_t * const set, + km_rand_t * const rs +) { + km_init_fn_t init_fn = get_init_func(init_type); + if (!init_fn) { + die("unknown cluster init method"); + } + + // call init, return result + return init_fn(cs, num_clusters, set, rs); +} diff --git a/km.h b/km.h index 6f09009..866e941 100644 --- a/km.h +++ b/km.h @@ -5,14 +5,6 @@ #include // uint8_t #include // FILE -typedef enum { - KM_INIT_TYPE_RAND, - KM_INIT_TYPE_FORGY, - KM_INIT_TYPE_LAST, -} km_init_type_t; - -km_init_type_t km_get_init_type(const char * const); - // forward typedef for callbacks typedef struct km_rand_t_ km_rand_t; @@ -85,22 +77,6 @@ _Bool km_set_normalize(km_set_t * const); // get pointer to data set row float *km_set_get_row(const km_set_t *, const size_t); -// init cluster set by picking random centroids -_Bool km_init_rand( - km_set_t *, - const size_t, - const size_t, - km_rand_t * -); - -// init cluster set by picking random rows from set -_Bool km_init_forgy( - km_set_t * const, - const size_t, - const km_set_t * const, - km_rand_t * -); - typedef struct { float d2; size_t cluster; @@ -197,7 +173,7 @@ typedef struct { void (*on_error)(const char * const, void *); } km_load_cbs_t; -// load set from file +// load set from file handle _Bool km_load( FILE * const fh, @@ -205,11 +181,32 @@ km_load( void * const cb_data ); -_Bool -km_load_path( +// load set from path +_Bool km_load_path( const char * const path, const km_load_cbs_t * const cbs, void * const cb_data ); +typedef enum { + // init cluster set by picking random centroids + KM_INIT_TYPE_RAND, + + // init cluster set by picking random rows from set + KM_INIT_TYPE_FORGY, + + KM_INIT_TYPE_LAST, +} km_init_type_t; + +km_init_type_t km_init_get_type(const char * const); + +// init cluster set using given method +_Bool km_init( + km_set_t * const, + const km_init_type_t, + const size_t, + const km_set_t * const, + km_rand_t * const +); + #endif /* KM_H */ diff --git a/main.c b/main.c index f071804..6acaf60 100644 --- a/main.c +++ b/main.c @@ -141,17 +141,7 @@ find_on_init( void *cb_data ) { ctx_t * const ctx = cb_data; - km_rand_t * const rs = &(ctx->rs); - - switch(ctx->init_type) { - case KM_INIT_TYPE_RAND: - return km_init_rand(cs, num_clusters, set->shape.num_floats, rs); - case KM_INIT_TYPE_FORGY: - return km_init_forgy(cs, num_clusters, set, rs); - default: - die("unknown cluster init method"); - return false; - } + return km_init(cs, ctx->init_type, num_clusters, set, &(ctx->rs)); } static bool @@ -338,7 +328,7 @@ int main(int argc, char *argv[]) { ctx_t ctx; memset(&ctx, 0, sizeof(ctx_t)); km_rand_init_system(&(ctx.rs)); - ctx.init_type = km_get_init_type(init_type_name); + ctx.init_type = km_init_get_type(init_type_name); // init data set km_set_t set; @@ -346,7 +336,7 @@ int main(int argc, char *argv[]) { die("km_load_path(\"%s\") failed", data_path); } - // init data set + // normalize data set if (!km_set_normalize(&set)) { die("km_set_normalize() failed"); } -- cgit v1.2.3