You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

main.c 4.3KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203
  1. #include <assert.h>
  2. #include <math.h>
  3. #include <stdbool.h>
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <string.h>
  7. #include <time.h>
  8. #include <unistd.h>
  9. #include "benchmark-data.h"
  10. /* TODO: Use typedefs for solution and vector instead of using int (*s)[230]
  11. * and double (*v)[42]. */
  12. /* Functions */
  13. double distance(const double (*u)[42], const double (*v)[42]);
  14. bool trouver_solution_initiale(void);
  15. bool solution_valide(int (*s)[230]);
  16. void print_solution(int (*s)[230], const char *name);
  17. void centre_gravite(int cluster, int (*s)[230], double (*cg)[42]);
  18. int solution_voisine(int (*dest)[230], int (*src)[230]);
  19. int solution[230] = {0};
  20. int new_solution[230] = {0};
  21. int n_clusters = 5;
  22. int n_iterations = 1000;
  23. int main(int argc, char *argv[])
  24. {
  25. int c;
  26. int i;
  27. while ((c = getopt(argc, argv, ":c:i:h")) != -1) {
  28. int k;
  29. switch (c) {
  30. case 'c':
  31. k = atoi(optarg);
  32. if (k > 0)
  33. n_clusters = k;
  34. break;
  35. case 'i':
  36. k = atoi(optarg);
  37. if (k > 0)
  38. n_iterations = k;
  39. break;
  40. case 'h':
  41. printf("Usage: %s [-c N_CLUSTERS] [-i N_ITERATIONS]", argv[0]);
  42. exit(EXIT_SUCCESS);
  43. break;
  44. default:
  45. exit(EXIT_FAILURE);
  46. }
  47. }
  48. printf("Using %d clusters\n", n_clusters);
  49. srand(time(NULL));
  50. /* Solution initiale */
  51. while (!trouver_solution_initiale())
  52. continue; /* do it again */
  53. print_solution(&solution, "initiale");
  54. for (i = 0; i < n_iterations; i++) {
  55. while (!solution_voisine(&new_solution, &solution))
  56. continue; /* do it again */
  57. /* TODO: Calculer les centres de gravités, les distances moyennes inter-/intra-cluster,
  58. * et faire le reste de l'algorithme */
  59. }
  60. exit(EXIT_SUCCESS);
  61. }
  62. double distance(const double (*u)[42], const double (*v)[42])
  63. {
  64. size_t n = sizeof(*v) / sizeof((*v)[0]);
  65. size_t i = 0;
  66. double sum = 0.0;
  67. printf("distance(): n = %zu\n", n);
  68. /* d(u, v) = sqrt( (u1 - v1)^2 + (u2 - v2)^2 + ... + (un - vn)^2 ) */
  69. for (; i < n; i++)
  70. sum += pow((*u)[i] - (*v)[i], 2);
  71. return sqrt(sum);
  72. }
  73. bool trouver_solution_initiale(void)
  74. {
  75. size_t i;
  76. for (i = 0; i < sizeof(solution) / sizeof(solution[0]); i++)
  77. solution[i] = rand() % n_clusters;
  78. return solution_valide(&solution);
  79. }
  80. bool solution_valide(int (*s)[230])
  81. {
  82. /* This function returns true if the solution that it found is "valid",
  83. * i.e., it has at least one element in each cluster. */
  84. bool *cluster_empty = calloc(n_clusters, sizeof *cluster_empty);
  85. bool valid = true;
  86. int i;
  87. for (i = 0; i < n_clusters; i++)
  88. cluster_empty[i] = true;
  89. for (i = 0; (size_t) i < sizeof(*s) / sizeof(*s[0]); i++)
  90. cluster_empty[(*s)[i]] = false;
  91. for (i = 0; valid && i < n_clusters; i++)
  92. valid = (valid && !cluster_empty[i]);
  93. free(cluster_empty);
  94. return valid;
  95. }
  96. void print_solution(int (*s)[230], const char *name)
  97. {
  98. size_t i = 0, n = sizeof(*s) / sizeof((*s)[0]);
  99. printf("Solution%s%s:\n[", name ? " " : "", name ? name : "");
  100. while (i < n) {
  101. const char *end;
  102. if (i + 1 == n)
  103. end = "]\n";
  104. else if (i && i % 20 == 0)
  105. end = ",\n";
  106. else
  107. end = ", ";
  108. printf("%d%s", (*s)[i++], end);
  109. }
  110. }
  111. void centre_gravite(int cluster, int (*s)[230], double (*cg)[42])
  112. {
  113. /* Calculer le centre de gravité pour les vecteurs du cluster cluster selon la solution s */
  114. const size_t n = sizeof(*cg) / sizeof((*cg)[0]); /* nombre d'attributs dans chaque vecteur. n = 42 */
  115. const size_t nv = sizeof(benchmark_data) / sizeof(benchmark_data[0]); /* nombre de vecteurs. nv = 230 */
  116. size_t i = 0;
  117. assert(n == 42);
  118. assert(nv == 230);
  119. /* Initialiser à 0 */
  120. while (i < n)
  121. (*cg)[i++] = 0;
  122. /* Loop over all vectors */
  123. for (i = 0; i < nv; i++) {
  124. size_t j = 0;
  125. if ((*s)[i] != cluster)
  126. /* Vector i is not part of the cluster, skip it */
  127. continue;
  128. while (j < n)
  129. (*cg)[j] += benchmark_data[i][j];
  130. }
  131. for (i = 0; i < n; i++) {
  132. (*cg)[i] /= n;
  133. }
  134. }
  135. int solution_voisine(int (*dest)[230], int (*src)[230])
  136. {
  137. /* This function changes about 10% of the solution randomly */
  138. memcpy(*dest, *src, sizeof(*src));
  139. const size_t n = sizeof(*src) / sizeof((*src)[0]);
  140. size_t i;
  141. const int a = 10000; /* b = 10% of a */
  142. const int b = 1000;
  143. assert(n == 230);
  144. for (i = 0; i < n; i++) {
  145. if (rand() % a < b) {
  146. int new_cluster = rand() % (n_clusters - 1);
  147. /* To avoid the case where the cluster isn't actually changed. */
  148. new_cluster += (new_cluster >= (*src)[i]);
  149. (*dest)[i] = new_cluster;
  150. }
  151. }
  152. return solution_valide(dest);
  153. }