Advertisement
Guest User

Untitled

a guest
Dec 3rd, 2016
70
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 9.47 KB | None | 0 0
  1. /**
  2. * Kostra programu pro 3. projekt IZP 2015/16
  3. *
  4. * Jednoducha shlukova analyza
  5. * Complete linkage
  6. * http://is.muni.cz/th/172767/fi_b/5739129/web/web/clsrov.html
  7. */
  8. #include <stdio.h>
  9. #include <stdlib.h>
  10. #include <assert.h>
  11. #include <math.h> // sqrt
  12. #include <limits.h> // INT_MAX
  13.  
  14. /*****************************************************************
  15. * Ladici makra. Vypnout jejich efekt lze definici makra
  16. * NDEBUG, napr.:
  17. * a) pri prekladu argumentem prekladaci -DNDEBUG
  18. * b) v souboru (na radek pred #include <assert.h>
  19. * #define NDEBUG
  20. */
  21. #ifdef NDEBUG
  22. #define debug(s)
  23. #define dfmt(s, ...)
  24. #define dint(i)
  25. #define dfloat(f)
  26. #else
  27.  
  28. // vypise ladici retezec
  29. #define debug(s) printf("- %s\n", s)
  30.  
  31. // vypise formatovany ladici vystup - pouziti podobne jako printf
  32. #define dfmt(s, ...) printf(" - "__FILE__":%u: "s"\n",__LINE__,__VA_ARGS__)
  33.  
  34. // vypise ladici informaci o promenne - pouziti dint(identifikator_promenne)
  35. #define dint(i) printf(" - " __FILE__ ":%u: " #i " = %d\n", __LINE__, i)
  36.  
  37. // vypise ladici informaci o promenne typu float - pouziti
  38. // dfloat(identifikator_promenne)
  39. #define dfloat(f) printf(" - " __FILE__ ":%u: " #f " = %g\n", __LINE__, f)
  40.  
  41. #endif
  42.  
  43. /*****************************************************************
  44. * Deklarace potrebnych datovych typu:
  45. *
  46. * TYTO DEKLARACE NEMENTE
  47. *
  48. * struct obj_t - struktura objektu: identifikator a souradnice
  49. * struct cluster_t - shluk objektu:
  50. * pocet objektu ve shluku,
  51. * kapacita shluku (pocet objektu, pro ktere je rezervovano
  52. * misto v poli),
  53. * ukazatel na pole shluku.
  54. */
  55.  
  56. struct obj_t {
  57. int id;
  58. float x;
  59. float y;
  60. };
  61.  
  62. struct cluster_t {
  63. int size;
  64. int capacity;
  65. struct obj_t *obj;
  66. };
  67.  
  68. /*****************************************************************
  69. * Deklarace potrebnych funkci.
  70. *
  71. * PROTOTYPY FUNKCI NEMENTE
  72. *
  73. * IMPLEMENTUJTE POUZE FUNKCE NA MISTECH OZNACENYCH 'TODO'
  74. *
  75. */
  76.  
  77. /*
  78. Inicializace shluku 'c'. Alokuje pamet pro cap objektu (kapacitu).
  79. Ukazatel NULL u pole objektu znamena kapacitu 0.
  80. */
  81. void init_cluster(struct cluster_t *c, int cap)
  82. {
  83. assert(c != NULL);
  84. assert(cap >= 0);
  85. c->obj = malloc(sizeof(struct obj_t)*cap);
  86. c->capacity = cap;
  87. c->size = 0;
  88. // TODO
  89.  
  90. }
  91. /*
  92. Odstraneni vsech objektu shluku a inicializace na prazdny shluk.
  93. */
  94. void clear_cluster(struct cluster_t *c)
  95. {
  96. free(c->obj);
  97. c->capacity=0;
  98. c->size=0;
  99. // TODO
  100. }
  101.  
  102. /// Chunk of cluster objects. Value recommended for reallocation.
  103. const int CLUSTER_CHUNK = 10;
  104.  
  105. /*
  106. Zmena kapacity shluku 'c' na kapacitu 'new_cap'.
  107. */
  108. struct cluster_t *resize_cluster(struct cluster_t *c, int new_cap)
  109. {
  110. // TUTO FUNKCI NEMENTE
  111. assert(c);
  112. assert(c->capacity >= 0);
  113. assert(new_cap >= 0);
  114.  
  115. if (c->capacity >= new_cap)
  116. return c;
  117.  
  118. size_t size = sizeof(struct obj_t) * new_cap;
  119. void *arr = realloc(c->obj, size);
  120. if (arr == NULL)
  121. return NULL;
  122.  
  123. c->obj = arr;
  124. c->capacity = new_cap;
  125. return c;
  126. }
  127.  
  128. /*
  129. Prida objekt 'obj' na konec shluku 'c'. Rozsiri shluk, pokud se do nej objekt
  130. nevejde.
  131. */
  132. void append_cluster(struct cluster_t *c, struct obj_t obj)
  133. {
  134. if(c->capacity==c->size)
  135. {
  136. resize_cluster(c,CLUSTER_CHUNK+c->size);
  137. }
  138. c->obj[c->size] = obj;
  139. c->size++;
  140.  
  141. }
  142.  
  143. /*
  144. Seradi objekty ve shluku 'c' vzestupne podle jejich identifikacniho cisla.
  145. */
  146. void sort_cluster(struct cluster_t *c);
  147.  
  148. /*
  149. Do shluku 'c1' prida objekty 'c2'. Shluk 'c1' bude v pripade nutnosti rozsiren.
  150. Objekty ve shluku 'c1' budou serazny vzestupne podle identifikacniho cisla.
  151. Shluk 'c2' bude nezmenen.
  152. */
  153. void merge_clusters(struct cluster_t *c1, struct cluster_t *c2)
  154. {
  155. assert(c1 != NULL);
  156. assert(c2 != NULL);
  157. for(int i=0; i<c2->size; i++)
  158. {
  159. append_cluster(c1,c2->obj[i]);
  160. }
  161. sort_cluster(c1);
  162. }
  163.  
  164. /**********************************************************************/
  165. /* Prace s polem shluku */
  166.  
  167. /*
  168. Odstrani shluk z pole shluku 'carr'. Pole shluku obsahuje 'narr' polozek
  169. (shluku). Shluk pro odstraneni se nachazi na indexu 'idx'. Funkce vraci novy
  170. pocet shluku v poli.
  171. */
  172. int remove_cluster(struct cluster_t *carr, int narr, int idx)
  173. {
  174. assert(idx < narr);
  175. assert(narr > 0);
  176. clear_cluster(&carr[idx]);
  177. // TODO
  178. int i;
  179. for(i=idx;i<=narr;i++)
  180. {
  181. carr[i]=carr[i+1];
  182. }
  183. return narr-1;
  184. }
  185.  
  186. /*
  187. Pocita Euklidovskou vzdalenost mezi dvema objekty.
  188. */
  189. float obj_distance(struct obj_t *o1, struct obj_t *o2)
  190. {
  191. assert(o1 != NULL);
  192. assert(o2 != NULL);
  193. float vzd;
  194. vzd=sqrt(pow((o1->x-o2->x),2)+pow((o1->y-o2->y),2));
  195. return vzd;
  196. // TODO
  197. }
  198.  
  199. /*
  200. Pocita vzdalenost dvou shluku.
  201. */
  202. float cluster_distance(struct cluster_t *c1, struct cluster_t *c2)
  203. {
  204. assert(c1 != NULL);
  205. assert(c1->size > 0);
  206. assert(c2 != NULL);
  207. assert(c2->size > 0);
  208.  
  209. float dis=0;
  210. float fdis=0;
  211. for(int i=0; i<c1->size;i++)
  212. {
  213. for(int j=0; j<c2->size;j++)
  214. {
  215. dis=obj_distance(&c1->obj[i],&c2->obj[j]);
  216. if(dis>fdis)
  217. {
  218. fdis=dis;
  219. }
  220. }
  221. }
  222. return fdis;
  223. // TODO
  224. }
  225.  
  226. /*
  227. Funkce najde dva nejblizsi shluky. V poli shluku 'carr' o velikosti 'narr'
  228. hleda dva nejblizsi shluky. Nalezene shluky identifikuje jejich indexy v poli
  229. 'carr'. Funkce nalezene shluky (indexy do pole 'carr') uklada do pameti na
  230. adresu 'c1' resp. 'c2'.
  231. */
  232. void find_neighbours(struct cluster_t *carr, int narr, int *c1, int *c2)
  233. {
  234. assert(narr > 0);
  235. float dis=10000000;
  236. float fdis=dis;
  237. for(int i=0; i<narr;i++)
  238. {
  239. for(int j=i+1; j<narr;j++)
  240. {
  241. dis=cluster_distance(&carr[i],&carr[j]);
  242. if(dis<fdis)
  243. {
  244. fdis=dis;
  245. *c1=i;
  246. *c2=j;
  247. }
  248. }
  249. }
  250. // TODO
  251. }
  252.  
  253. // pomocna funkce pro razeni shluku
  254. static int obj_sort_compar(const void *a, const void *b)
  255. {
  256. // TUTO FUNKCI NEMENTE
  257. const struct obj_t *o1 = a;
  258. const struct obj_t *o2 = b;
  259. if (o1->id < o2->id) return -1;
  260. if (o1->id > o2->id) return 1;
  261. return 0;
  262. }
  263.  
  264. /*
  265. Razeni objektu ve shluku vzestupne podle jejich identifikatoru.
  266. */
  267. void sort_cluster(struct cluster_t *c)
  268. {
  269. // TUTO FUNKCI NEMENTE
  270. qsort(c->obj, c->size, sizeof(struct obj_t), &obj_sort_compar);
  271. }
  272.  
  273. /*
  274. Tisk shluku 'c' na stdout.
  275. */
  276. void print_cluster(struct cluster_t *c)
  277. {
  278. // TUTO FUNKCI NEMENTE
  279. for (int i = 0; i < c->size; i++)
  280. {
  281. if (i) putchar(' ');
  282. printf("%d[%g,%g]", c->obj[i].id, c->obj[i].x, c->obj[i].y);
  283. }
  284. putchar('\n');
  285. }
  286.  
  287. /*
  288. Ze souboru 'filename' nacte objekty. Pro kazdy objekt vytvori shluk a ulozi
  289. jej do pole shluku. Alokuje prostor pro pole vsech shluku a ukazatel na prvni
  290. polozku pole (ukalazatel na prvni shluk v alokovanem poli) ulozi do pameti,
  291. kam se odkazuje parametr 'arr'. Funkce vraci pocet nactenych objektu (shluku).
  292. V pripade nejake chyby uklada do pameti, kam se odkazuje 'arr', hodnotu NULL.
  293. */
  294. int load_clusters(char *filename, struct cluster_t **arr)
  295. {
  296. assert(arr != NULL);
  297.  
  298. // TODO
  299. FILE *soubor;
  300.  
  301. int pocet = 0;
  302. int id;
  303. float x,y;
  304.  
  305. soubor = fopen(filename, "r");
  306.  
  307. fscanf(soubor, "count=%d",&pocet);
  308. int i = 0;
  309. *arr = malloc(sizeof(struct cluster_t)*pocet); // alokuji si pole clusterù na pozadovanou velikosr
  310.  
  311. for (i=0;i<pocet;i++)
  312. {
  313. init_cluster(&arr[0][i],50); //inicializu si [i]tý cluster o kapacitì max 1.
  314.  
  315. fscanf(soubor, "%d %f %f", &id, &x, &y); // naètu id x y
  316.  
  317. struct obj_t *objekt = malloc(sizeof(struct obj_t)); //vytvoøím si pomocný objekt obj_t a ulozim do nej ukazatele na misto v pameti, kde je na nej misto
  318. objekt->id=id; // priradim do pomocneho objektu ID
  319. objekt->x=x; // priradim do pomocneho objektu X
  320. objekt->y=y; // priradim do pomocneho objektu Y
  321.  
  322. append_cluster(&arr[0][i],*objekt);
  323.  
  324. //arr[0][i].obj = objekt; // pomocny objekt priradim do pole objetù v do clusteru
  325. // arr[0][i].size = 1; // velikost clusteru zmenim na 1
  326.  
  327.  
  328. print_cluster(&arr[0][i]);
  329. }
  330. //print_clusters(&arr[0][0],8);
  331. //print_clusters(&arr[0], 2);
  332. // free(objekt);
  333. //free()
  334. fclose(soubor);
  335. return i;
  336. }
  337.  
  338.  
  339. /*
  340. Tisk pole shluku. Parametr 'carr' je ukazatel na prvni polozku (shluk).
  341. Tiskne se prvnich 'narr' shluku.
  342. */
  343.  
  344. void print_clusters(struct cluster_t *carr, int narr)
  345. {
  346. printf("Clusters:\n");
  347. for (int i = 0; i < narr; i++)
  348. {
  349. printf("cluster %d: ", i);
  350. print_cluster(&carr[i]);
  351. }
  352. }
  353.  
  354. int main(int argc, char *argv[])
  355. {
  356. struct cluster_t *clusters;
  357. int pocetC=1;
  358. if(argc == 3)
  359. {
  360. pocetC=atoi(argv[2]);
  361. }
  362. int c1=0;
  363. int c2=0;
  364. int j=load_clusters(argv[1], &clusters);
  365. while(j>pocetC)
  366. {
  367. find_neighbours(clusters, j,&c1, &c2);
  368. merge_clusters(&clusters[c1],&clusters[c2]);
  369. j=remove_cluster(clusters,j,c2);
  370. }
  371. /*find_neighbours(clusters, j, &c1, &c2);
  372. //printf("%i %i",c1,c2);
  373.  
  374. //printf("%f",cluster_distance(&clusters[0], &clusters[1]));
  375. //merge_clusters(&clusters[0],&clusters[5]);*/
  376. print_clusters(clusters, j);
  377. //j=remove_cluster(clusters,j,3);
  378. //clear_cluster(clusters);
  379. return 0;
  380. // TODO
  381. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement