25'ten fazla konu seçemezsiniz Konular bir harf veya rakamla başlamalı, kısa çizgiler ('-') içerebilir ve en fazla 35 karakter uzunluğunda olabilir.

#### 324 satır 6.4 KiB Ham Normal Görünüm Geçmiş Unescape Escape

 ```#include ``` ```#include ``` ```#include ``` ```#include ``` ```#include ``` ```#include ``` ```#include ``` ``` ``` ```#include ``` ``` ``` ```#include "benchmark-data.h" ``` ``` ``` ``` ``` `/* Types */` `typedef int *solution;` ``` ``` ``` ``` `/* Functions */` `double distance(const vector u, const vector v);` `bool trouver_solution_initiale(void);` `bool solution_valide(const solution s);` `void print_solution(const solution s, const char *name);` `vector *centres_gravite(const solution s);` `int solution_voisine(solution *dest, const solution src);` `double fonction_objective(const solution s);` ``` ``` `static double calculer_inter(const vector *cgs);` `static double calculer_intra(const solution s, const vector *cgs);` ``` ``` ``` ``` `/* Variables */` `solution solution_opt;` `solution new_solution;` ``` ``` `int n_clusters = 5;` `int n_iterations = 1000;` ``` ``` ``` ``` `int main(int argc, char *argv[])` `{` ` int c;` ` int i;` ` double f0;` ``` ``` ` while ((c = getopt(argc, argv, ":c:i:h")) != -1) {` ` int k;` ` switch (c) {` ` case 'c':` ` k = atoi(optarg);` ` if (k > 1)` ` n_clusters = k;` ` break;` ` case 'i':` ` k = atoi(optarg);` ` if (k > 0)` ` n_iterations = k;` ` break;` ` case 'h':` ` printf("Usage: %s [-c N_CLUSTERS] [-i N_ITERATIONS]", argv[0]);` ` exit(EXIT_SUCCESS);` ` break;` ` default:` ` exit(EXIT_FAILURE);` ` }` ` }` ``` ``` ` printf("Using %d clusters\n", n_clusters);` ``` ``` ` /* Init benchmark_data */` ` init_benchmark_data();` ``` ``` ` srand(time(NULL));` ``` ``` ` if (!(solution_opt = calloc(N_VECTORS, sizeof(solution_opt[0]))))` ` abort();` ``` ``` ` /* Solution initiale */` ` while (!trouver_solution_initiale())` ` continue; /* do it again */` ``` ``` ` f0 = fonction_objective(solution_opt);` ``` ``` ` print_solution(solution_opt, "initiale");` ` printf("F(solution) = %f\n", f0);` ``` ``` ` for (i = 0; i < n_iterations; i++) {` ` double f1;` ``` ``` ` while (!solution_voisine(&new_solution, solution_opt))` ` continue; /* do it again */` ``` ``` ` if ((f1 = fonction_objective(new_solution)) > f0) {` ` print_solution(new_solution, "optimale trouvée");` ` printf("F(solution) = %f (%f%% improvement)\n", f1, fabs((f1 - f0) / f0 * 100.0));` ` free(solution_opt);` ` solution_opt = new_solution;` ` new_solution = NULL;` ` f0 = f1;` ` }` ` }` ``` ``` ` /* Free solution data */` ` free(solution_opt);` ` free(new_solution);` ``` ``` ``` ``` ` /* Free benchmark data */` ` for (i = 0; i < (int) N_VECTORS; i++)` ` free(benchmark_data[i]);` ` free(benchmark_data);` ``` ``` ` exit(EXIT_SUCCESS);` `}` ``` ``` `double distance(const vector u, const vector v)` `{` ` size_t i = 0;` ` double sum = 0.0;` ``` ``` ` if (!u || !v) {` ` fputs("distance(): u or v is null.\n", stderr);` ` abort();` ` }` ``` ``` ` /* d(u, v) = sqrt( (u1 - v1)^2 + (u2 - v2)^2 + ... + (un - vn)^2 ) */` ``` ``` ` for (; i < VECTOR_SIZE; i++)` ` sum += pow(u[i] - v[i], 2);` ``` ``` ` return sqrt(sum);` `}` ``` ``` `bool trouver_solution_initiale(void)` `{` ` size_t i;` ``` ``` ` for (i = 0; i < N_VECTORS; i++)` ` solution_opt[i] = rand() % n_clusters;` ``` ``` ` return solution_valide(solution_opt);` `}` ``` ``` `bool solution_valide(const solution s)` `{` ``` /* This function returns true if the solution that it found is "valid", ``` ` * i.e., it has at least one element in each cluster. */` ``` ``` ` bool *cluster_empty = calloc(n_clusters, sizeof *cluster_empty);` ` bool valid = true;` ` int i;` ``` ``` ` for (i = 0; i < n_clusters; i++)` ` cluster_empty[i] = true;` ``` ``` ` for (i = 0; (size_t) i < N_VECTORS; i++)` ` cluster_empty[s[i]] = false;` ``` ``` ` for (i = 0; valid && i < n_clusters; i++)` ` valid = (valid && !cluster_empty[i]);` ``` ``` ` free(cluster_empty);` ``` ``` ` return valid;` `}` ``` ``` `void print_solution(const solution s, const char *name)` `{` ` size_t i = 0;` ``` ``` ` printf("Solution%s%s: [\n", name ? " " : "", name ? name : "");` ``` ``` ` while (i < N_VECTORS) {` ` const char *end;` ``` ``` ` if (i + 1 == N_VECTORS)` ` end = "]\n";` ` else if ((i + 1) % 20 == 0)` ` end = ",\n";` ` else` ` end = ", ";` ``` ``` ` printf("%d%s", s[i++], end);` ` }` `}` ``` ``` `vector *centres_gravite(const solution s)` `{` ` /* Calculer le centre de gravité pour les vecteurs du cluster cluster selon la solution s */` ``` ``` ` int cluster;` ` size_t i = 0;` ``` ``` ` /* cgs[n_clusters] est le centre de gravité global */` ` vector *cgs = calloc(n_clusters + 1, sizeof(*cgs));` ``` ``` ` int *vectors_in_cluster = calloc(n_clusters + 1, sizeof(*vectors_in_cluster));` ``` ``` ` if (!cgs || !vectors_in_cluster)` ` abort();` ``` ``` ` for (cluster = 0; cluster < n_clusters + 1; cluster++) {` ` if (!(cgs[cluster] = calloc(VECTOR_SIZE, sizeof(*cgs[cluster]))))` ` abort();` ``` ``` ` /* Initialiser à 0 */` ` while (i < VECTOR_SIZE)` ` cgs[cluster][i++] = 0;` ` if (cluster < n_clusters)` ` vectors_in_cluster[cluster] = 0;` ` }` ``` ``` ` for (i = 0; i < N_VECTORS; i++) {` ` size_t j;` ``` ``` ` cluster = s[i];` ` ++vectors_in_cluster[cluster];` ``` ``` ` for (j = 0; j < VECTOR_SIZE; j++) {` ` cgs[cluster][j] += benchmark_data[i][j];` ` cgs[n_clusters][j] += benchmark_data[i][j];` ` }` ` }` ``` ``` ` vectors_in_cluster[n_clusters] = N_VECTORS;` ``` ``` ` for (cluster = 0; cluster < n_clusters + 1; cluster++)` ` for (i = 0; i < VECTOR_SIZE; i++)` ` cgs[cluster][i] /= (double) vectors_in_cluster[cluster];` ``` ``` ` free(vectors_in_cluster);` ``` ``` ` return cgs;` `}` ``` ``` `int solution_voisine(solution *dest, const solution src)` `{` ` /* This function changes about 10% of the solution randomly */` ``` ``` ` size_t i;` ` const int a = 10000; /* b = 10% of a */` ` const int b = 1000;` ` bool valid;` ``` ``` ` if (!(*dest = calloc(N_VECTORS, sizeof(**dest))))` ` abort();` ``` ``` ` memcpy(*dest, src, N_VECTORS * sizeof(*src));` ``` ``` ` assert(n_clusters > 1);` ``` ``` ` for (i = 0; i < N_VECTORS; i++) {` ` if (rand() % a < b) {` ` int new_cluster = rand() % (n_clusters - 1);` ` /* To avoid the case where the cluster isn't actually changed. */` ` new_cluster += (new_cluster >= src[i]);` ` (*dest)[i] = new_cluster;` ` }` ` }` ``` ``` ` if (!(valid = solution_valide(*dest))) {` ` free(*dest);` ` *dest = NULL;` ` }` ``` ``` ` return valid;` `}` ``` ``` `double fonction_objective(const solution s)` `{` ` int i;` ` double **cgs = centres_gravite(s);` ` double inter;` ` double intra;` ``` ``` ``` ``` ` if (!cgs)` ` abort();` ``` ``` ` inter = calculer_inter(cgs);` ` intra = calculer_intra(s, cgs);` ``` ``` ` for (i = 0; i < n_clusters + 1; i++)` ` free(cgs[i]);` ``` ``` ` free(cgs);` ``` ``` ` return inter - intra;` `}` ``` ``` `static double calculer_inter(const vector *cgs)` `{` ` double inter = 0.0;` ` int cluster;` ``` ``` ` for (cluster = 0; cluster < n_clusters; cluster++)` ` inter += distance(cgs[n_clusters], cgs[cluster]);` ``` ``` ` return inter / (double) n_clusters;` `}` ``` ``` `static double calculer_intra(const solution s, const vector *cgs)` `{` ` double intra = 0.0;` ` int cluster;` ``` ``` ` for (cluster = 0; cluster < n_clusters; cluster++) {` ` double intra_for_this_cluster = 0.0;` ` int vectors_in_this_cluster = 0;` ` size_t i;` ``` ``` ` for (i = 0; i < N_VECTORS; i++) {` ` if (s[i] != cluster)` ` continue;` ``` ``` ` ++vectors_in_this_cluster;` ` intra_for_this_cluster += distance(cgs[cluster], benchmark_data[i]);` ` }` ``` ``` ` intra += intra_for_this_cluster / (double) vectors_in_this_cluster;` ` }` ``` ``` ` return intra / (double) n_clusters;` `}`