Skip to content
Extraits de code Groupes Projets
Valider 0b21c98a rédigé par François Michel's avatar François Michel
Parcourir les fichiers

add skeleton

parent
Branches patch-1
Aucune étiquette associée trouvée
Aucune requête de fusion associée trouvée
CC=gcc
CFLAGS=-Wall -Werror -g
LIBS=-lcunit -lpthread
INCLUDE_HEADERS_DIRECTORY=-Iheaders
kmeans: main.c src/distance.o # add your other object files needed to compile your program here. !! The ordering is important !! if file_a.o depends on file_b.o, file_a.o must be placed BEFORE file_b.o in the list !
$(CC) $(INCLUDE_HEADERS_DIRECTORY) $(CFLAGS) -o $@ $^ $(LIBS) # this will run the following command: gcc -Wall -Werror -g -o kmeans src/distance.o other_object_filespresent_above.o ... -lcunit -lpthread
%.o: %.c # if for example you want to compute example.c this will create an object file called example.o in the same directory as example.c. Don't forget to clean it in your "make clean"
$(CC) $(INCLUDE_HEADERS_DIRECTORY) $(CFLAGS) -o $@ -c $<
clean:
rm -f src/*.o
rm -f kmeans
tests: kmeans
echo "TODO !"
# a .PHONY target forces make to execute the command even if the target already exists
.PHONY: clean tests
\ No newline at end of file
#ifndef CLUSTER_H
#define CLUSTER_H
typedef struct {
// TODO
} cluster_t;
#endif //CLUSTER_H
#ifndef DISTANCE_H
#define DISTANCE_H
#include <stdint.h>
#include "point.h"
/**
* This typedef below defines the distance_func_t type, a function pointer type that groups all
* functions with the following signature :
*
* int64_t function_name(const point_t *, const point_t *)
*
* So basically, once you've implemented squared_manhatan_distance and squared_euclidean_distance,
* you can do the following if you want:
*
* squared_distance_func_t generic_func;
* if (some_condition) {
* generic_func = squared_manhattan_distance;
* } else {
* generic_func = squared_euclidean_distance;
* }
* int64_t dist = generic_func(a, b); // computes either the manhattan distance or the euclidean distance depending on the some_condition
*
*/
typedef int64_t (*squared_distance_func_t) (const point_t *, const point_t *);
/**
* @return the squared manhattan distance between 2 points
*/
int64_t squared_manhattan_distance(const point_t *, const point_t *);
/**
* @return the squared euclidean distance between 2 points
*/
int64_t squared_euclidean_distance(const point_t *, const point_t *);
#endif //DISTANCE_H
#ifndef POINT_H
#define POINT_H
typedef struct {
// TODO
} point_t;
#endif //POINT_H
#include <stdio.h>
#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include <getopt.h>
#include <stdlib.h>
#include <errno.h>
#include <inttypes.h>
#include "headers/distance.h"
typedef struct {
FILE *input_stream;
FILE *output_stream;
uint32_t n_threads;
uint32_t k;
uint32_t n_first_initialization_points;
bool quiet;
squared_distance_func_t squared_distance_func;
} args_t;
void usage(char *prog_name) {
fprintf(stderr, "USAGE:\n");
fprintf(stderr, " %s [-p n_combinations_points] [-n n_threads] [input_filename]\n", prog_name);
fprintf(stderr, " -k n_clusters (default value: 2): the number of clusters to compute\n");
fprintf(stderr, " -p n_combinations (default value: equal to k): consider the n_combinations first points present in the input to generate possible initializations for the k-means algorithm\n");
fprintf(stderr, " -n n_threads (default value: 4): sets the number of computing threads that will be used to execute the k-means algorithm\n");
fprintf(stderr, " -f output_file (default value: stdout): sets the filename on which to write the csv result\n");
fprintf(stderr, " -q quiet mode: does not output the clusters content (the \"clusters\" column is simply not present in the csv)\n");
fprintf(stderr, " -d distance (manhattan by default): can be either \"euclidean\" or \"manhattan\". Chooses the distance formula to use by the algorithm to compute the distance between the points\n");
}
int parse_args(args_t *args, int argc, char *argv[]) {
memset(args, 0, sizeof(args_t)); // set everything to 0 by default
// the default values are the following, they will be changed depending on the arguments given to the program
args->k = 2;
args->n_first_initialization_points = args->k;
args->n_threads = 4;
args->output_stream = stdout;
args->quiet = false;
args->squared_distance_func = squared_manhattan_distance;
int opt;
while ((opt = getopt(argc, argv, "n:p:k:f:d:q")) != -1) {
switch (opt)
{
case 'n':
args->n_threads = atoi(optarg);
if (args->n_threads <= 0) {
fprintf(stderr, "Wrong number of threads. Needs a positive integer, received \"%s\"\n", optarg);
return -1;
}
break;
case 'p':
args->n_first_initialization_points = atoi(optarg);
if (args->n_first_initialization_points <= 0) {
fprintf(stderr, "Wrong number of initialization points. Needs a positive integer, received \"%s\"\n", optarg);
return -1;
}
break;
case 'k':
args->k = atoi(optarg);
if (args->k <= 0) {
fprintf(stderr, "Wrong k. Needs a positive integer, received \"%s\"\n", optarg);
return -1;
}
break;
case 'f':
args->output_stream = fopen(optarg, "w");
if (!args->output_stream) {
fprintf(stderr, "could not open output file %s: %s\n", optarg, strerror(errno));
return -1;
}
break;
case 'q':
args->quiet = true;
break;
case 'd':
if (strcmp("euclidean", optarg) == 0) {
args->squared_distance_func = squared_euclidean_distance;
}
break;
case '?':
usage(argv[0]);
return 1;
default:
usage(argv[0]);
}
}
if (optind == argc) {
args->input_stream = stdin;
} else {
args->input_stream = fopen(argv[optind], "r");
if (!args->input_stream) {
fprintf(stderr, "could not open file %s: %s\n", argv[optind], strerror(errno));
return -1;
}
}
return 0;
}
int main(int argc, char *argv[]) {
args_t program_arguments; // allocate the args on the stack
parse_args(&program_arguments, argc, argv);
if (program_arguments.n_first_initialization_points < program_arguments.k) {
fprintf(stderr, "Cannot generate an instance of k-means with less initialization points than needed clusters: %"PRIu32" < %"PRIu32"\n",
program_arguments.n_first_initialization_points, program_arguments.k);
return -1;
}
// the following fprintf (and every code already present in this skeleton) can be removed, it is just an example to show you how to use the program arguments
fprintf(stderr, "\tnumber of threads executing the LLoyd's algoprithm in parallel: %" PRIu32 "\n", program_arguments.n_threads);
fprintf(stderr, "\tnumber of clusters (k): %" PRIu32 "\n", program_arguments.k);
fprintf(stderr, "\twe consider all the combinations of the %" PRIu32 " first points of the input as initializations of the Lloyd's algorithm\n", program_arguments.n_first_initialization_points);
fprintf(stderr, "\tquiet mode: %s\n", program_arguments.quiet ? "enabled" : "disabled");
fprintf(stderr, "\tsquared distance function: %s\n", program_arguments.squared_distance_func == squared_manhattan_distance ? "manhattan" : "euclidean");
// TODO: parse the binary input file, compute the k-means solutions and write the output in a csv
// close the files opened by parse_args
if (program_arguments.input_stream != stdin) {
fclose(program_arguments.input_stream);
}
if (program_arguments.output_stream != stdout) {
fclose(program_arguments.output_stream);
}
return 0;
}
#include "../headers/distance.h"
int64_t squared_manhattan_distance(const point_t *p1, const point_t *p2) {
// TODO
return 42;
}
int64_t squared_euclidean_distance(const point_t *p1, const point_t *p2) {
// TODO
return 42;
}
Fichier ajouté
0% Chargement en cours ou .
You are about to add 0 people to the discussion. Proceed with caution.
Terminez d'abord l'édition de ce message.
Veuillez vous inscrire ou vous pour commenter