-
Boris Stefanovic authoredBoris Stefanovic authored
main.c 3.48 KiB
#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();
}
}