#include <getopt.h> #include <stdbool.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include "distance.h" #include "io.h" #include "kmeans.h" #include "linkedlist.h" #include "vector.h" enum DistanceFunctionType { EUCLID = 0, MANHATTAN = 1, CHEBYSHEV = 2 }; enum DataType { FLOAT = 0, INT = 1 }; fpt_t (* const DIST_FUNC_INT[])(const vector_int_t*, const vector_int_t*) = { distance_euclid_int, distance_manhattan_int, distance_chebyshev_int}; fpt_t (* const DIST_FUNC_FPT[])(const vector_fpt_t*, const vector_fpt_t*) = { distance_euclid_fpt, distance_manhattan_fpt, distance_chebyshev_fpt}; void help(const char* callname) { fprintf(stderr, "\nUSAGE: %s -i INPUT_FILE -o OUTPUT_FILE -d [euclid,manhattan,chebyshev] -t [fpt,int]\n", callname); } void parse_args(int argc, char** argv, char** ipath, char** opath, enum DistanceFunctionType* df, enum DataType* type) { int opt; while ((opt = getopt(argc, argv, "i:o:d:t:h")) != -1) { switch (opt) { case 'h': help(argv[0]); exit(EXIT_FAILURE); case 'i': *ipath = optarg; break; case 'o': *opath = optarg; break; case 'd': if (strcmp(optarg, "euclid") == 0) *df = EUCLID; else if (strcmp(optarg, "manhattan") == 0) *df = MANHATTAN; else if (strcmp(optarg, "chebyshev") == 0) *df = CHEBYSHEV; break; case 't': if (strcmp(optarg, "fpt") == 0) *type = FLOAT; else if (strcmp(optarg, "int") == 0) *type = INT; break; case '?': fprintf(stderr, "UNKNOWN OPTION : %c", opt); break; default: // https://www.gnu.org/software/libc/manual/html_node/Example-of-Getopt.html abort(); } } } int main_int(const char* ipath, const char* opath, const enum DistanceFunctionType dist_func_type) { //TODO return EXIT_FAILURE; } int main_fpt(const char* ipath, const char* opath, const enum DistanceFunctionType dist_func_type) { // READ FILE* ifile = ipath != NULL ? fopen(ipath, "r") : stdin; const size_t dim = io_read_int(ifile); const size_t nb_clusters = io_read_int(ifile); if (0 == dim) { printf("DIMENSION MUST BE STRICTLY POSITIVE !\n"); fclose(ifile); return EXIT_FAILURE; } if (0 == nb_clusters) { printf("NUMBER OF CLUSTERS MUST BE STRICTLY POSITIVE !\n"); fclose(ifile); return EXIT_FAILURE; } list_points_fpt_t* list = io_get_vector_list_fpt(ifile, dim); fclose(ifile); ifile = NULL; const size_t point_count = list->size; vector_fpt_t** points = list_points_to_array_fpt(list); list_points_destroy_fpt(list, false); list = NULL; // ALGORITHM printf("INIT: ... "); cluster_fpt_t** clusters = kmeans_init_clusters_fpt((const vector_fpt_t**) points, point_count, nb_clusters); printf("DONE\n"); printf("STARTING KMEANS ALGORITHM: ...\n"); kmeans_fpt(points, point_count, clusters, nb_clusters, DIST_FUNC_FPT[dist_func_type]); printf("KMEANS DONE !\n"); // WRITE FILE* ofile = opath != NULL ? fopen(opath, "w") : stdout; fprintf(ofile, "%lud\n%lud\n", dim, nb_clusters); io_write_clusters_to_file_fpt(ofile, clusters, nb_clusters); fclose(ofile); return EXIT_SUCCESS; } int main(int argc, char** argv) { // init defaults char (* ipath) = NULL, (* opath) = NULL; enum DistanceFunctionType disttype = EUCLID; enum DataType datatype = FLOAT; // parse args parse_args(argc, argv, &ipath, &opath, &disttype, &datatype); switch (datatype) { case FLOAT: printf("FLOAT\n"); return main_fpt(ipath, opath, disttype); case INT: printf("INT\n"); return main_int(ipath, opath, disttype); default: abort(); } }