aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Duncan <pabs@pablotron.org>2019-02-03 21:12:11 -0500
committerPaul Duncan <pabs@pablotron.org>2019-02-03 21:12:11 -0500
commit0f544be878f72b09d516a64c60e3cbd66f7cfd81 (patch)
treeadb9868e1b45494f83abac8420107864b009e271
parent33a722132491ebdd31722f0cada0f81f6b082282 (diff)
downloadkmeans-0f544be878f72b09d516a64c60e3cbd66f7cfd81.tar.bz2
kmeans-0f544be878f72b09d516a64c60e3cbd66f7cfd81.zip
add km_init(), refactor existing init
-rw-r--r--Makefile2
-rw-r--r--km-init-rand.c5
-rw-r--r--km-init-type.c32
-rw-r--r--km-init.c80
-rw-r--r--km.h51
-rw-r--r--main.c16
6 files changed, 112 insertions, 74 deletions
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 <stddef.h> // size_t
-#include <string.h> // 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 <stdbool.h> // bool
+#include <stddef.h> // size_t
+#include <string.h> // 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 <stdint.h> // uint8_t
#include <stdio.h> // 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");
}