diff --git a/src/func.c b/src/func.c new file mode 100644 index 0000000000000000000000000000000000000000..e2aa5e5ff85893016961ea4b55c570c989a6fe36 --- /dev/null +++ b/src/func.c @@ -0,0 +1,206 @@ +#include <stdio.h> +#include <stdlib.h> +#include </usr/include/mpi/mpi.h> +#include <time.h> +#include "func.h" +#define INFINITY 1000000 + +/* + Fungsi untuk membaca n (jumlah node yang akan digunakan) + */ +int Read_n(int rank, MPI_Comm com) { + int n; + if (rank == 0){ + scanf("%d", &n); + } + + MPI_Bcast(&n, 1, MPI_INT, 0, com); + return n; +} + +/* + Membuat MPI_Datatype yang merepresentasikan matriks + */ +MPI_Datatype Build_blk_col_type(int n_local, int n) { + MPI_Datatype first_bc_mpi_t; + MPI_Datatype block_mpi_t; + MPI_Datatype blk_col_mpi_t; + MPI_Aint lb, extent; + + MPI_Type_contiguous(n_local, MPI_INT, &block_mpi_t); + MPI_Type_get_extent(block_mpi_t, &lb, &extent); + + MPI_Type_vector(n, n_local, n, MPI_INT, &first_bc_mpi_t); + + MPI_Type_create_resized(first_bc_mpi_t, lb, extent, &blk_col_mpi_t); + + MPI_Type_commit(&blk_col_mpi_t); + + MPI_Type_free(&block_mpi_t); + MPI_Type_free(&first_bc_mpi_t); + + return blk_col_mpi_t; +} + +/* + Membuat sebuah matriks nxn yang mewakili graf. + Nilai M[i][j] = jarak dari node i ke j. + Jarak diinisialisasi dengan nilai random yang memiliki seed = 13517111. + */ +void Make_matrix(int tab_local[], int n_local, int n, + MPI_Datatype blk_col_mpi_t, int rank, MPI_Comm com) { + int upper = 1000; + int lower = 0; + int *mat = NULL, i, j; + + srand(13517111); + + if (rank == 0) { + mat = malloc(n * n * sizeof(int)); + for (i = 0; i < n; i++) { + for (j = 0; j < n; j++) { + if(j==i) { + mat[i * n + j] = 0; + } + else if (j>i){ + int x = (rand() % (upper - lower + 1)) + lower; + mat[i * n + j] = x; + mat[i + j * n] = x; + } + } + } + } + + MPI_Scatter(mat, 1, blk_col_mpi_t, tab_local, n * n_local, MPI_INT, 0, com); + + if (rank == 0) free(mat); +} + +/* + Mencari jarak minimum lokal dari titik 0 ke sebuah simpul + */ +int Find_jarak_min(int jarak_local[], int known_local[], int n_local) { + int jarak_terpendek = INFINITY; + int v_local; + int u_local = -1; + + for (v_local = 0; v_local < n_local; v_local++) { + if (!known_local[v_local]) { + if (jarak_local[v_local] < jarak_terpendek) { + jarak_terpendek = jarak_local[v_local]; + u_local = v_local; + } + } + } + return u_local; +} + +/* + Menuliskan setiap jarak dari titik 0 ke setiap simpul ke out.txt + */ +void Print_jarak(int jarak_global[], int n) { + int v; + FILE *fptr; + fptr = fopen("out.txt","w"); + if(fptr == NULL){ + printf("Error!"); + exit(1); + } + + fprintf(fptr," v dist 0->v\n"); + fprintf(fptr,"---- ---------\n"); + + for (v = 1; v < n; v++) { + if (jarak_global[v] != INFINITY) { + fprintf(fptr,"%3d %4d\n", v, jarak_global[v]); + } + else + fprintf(fptr,"%3d %5s\n", v, "inf"); + } + fprintf(fptr,"\n"); + fclose(fptr); +} + + +/* + Menginisialisasi setiap matriks yang ada pada nodes agar algoritmanya bisa berjalan. + */ +void Dijkstra_Init(int tab_local[], int pred_local[], int jarak_local[], int known_local[], + int rank, int n_local) { + int loc_v; + + if (rank == 0) + known_local[0] = 1; + else + known_local[0] = 0; + + for (loc_v = 1; loc_v < n_local; loc_v++) + known_local[loc_v] = 0; + + for (loc_v = 0; loc_v < n_local; loc_v++) { + jarak_local[loc_v] = tab_local[0 * n_local + loc_v]; + pred_local[loc_v] = 0; + } +} + +/* + Algoritma dijkstra untuk menghitung jarak terpendek dari simpul 0 ke setiap simpul lainnya. + */ +void Dijkstra(int tab_local[], int jarak_local[], int pred_local[], int n_local, int n, + MPI_Comm com) { + + int i, jarak_baru, rank, v_local, u_local, global_u, jarak_global_u; + int *known_local; + int min_global[2]; + int min[2]; + + MPI_Comm_rank(com, &rank); + known_local = malloc(n_local * sizeof(int)); + + Dijkstra_Init(tab_local, pred_local, jarak_local, known_local, rank, n_local); + + /* + Membuat loop sebanyak n-1 kali karena jarak terpendek node 0 ke 0 adalah 0 + */ + for (i = 0; i < n - 1; i++) { + u_local = Find_jarak_min(jarak_local, known_local, n_local); + + if (u_local == -1) { + min[0] = INFINITY; + min[1] = -1; + } + else { + min[0] = jarak_local[u_local]; + min[1] = u_local + rank * n_local; + } + + /* + Menyimpan jarak terpendek global dan nodenya dalam min_global + */ + MPI_Allreduce(min, min_global, 1, MPI_2INT, MPI_MINLOC, com); + + jarak_global_u = min_global[0]; + global_u = min_global[1]; + + if (global_u == -1) + break; + + if ((global_u / n_local) == rank) { + u_local = global_u % n_local; + known_local[u_local] = 1; + } + + for (v_local = 0; v_local < n_local; v_local++) { + if (!known_local[v_local]) { + jarak_baru = jarak_global_u + tab_local[global_u * n_local + v_local]; + if (jarak_baru < jarak_local[v_local]) { + pred_local[v_local] = global_u; + jarak_local[v_local] = jarak_baru; + } + } + } + } + free(known_local); +} + + diff --git a/src/func.h b/src/func.h new file mode 100644 index 0000000000000000000000000000000000000000..b049ea796685d2298ebd1752ae45dbf02f6751cb --- /dev/null +++ b/src/func.h @@ -0,0 +1,20 @@ +#include <stdio.h> +#include <stdlib.h> +#include </usr/include/mpi/mpi.h> +#include <time.h> + +#ifndef FUNC_H +#define FUNC_H + +int Read_n(int rank, MPI_Comm com); +MPI_Datatype Build_blk_col_type(int n_local, int n); +void Make_matrix(int tab_local[], int n_local, int n, MPI_Datatype blk_col_mpi_t, + int rank, MPI_Comm com); +int Find_jarak_min(int jarak_local[], int known_local[], int n_local); +void Print_jarak(int n, int jarak_global[]); +void Dijkstra_Init(int tab_local[], int pred_local[], int jarak_local[], int known_local[], + int rank, int n_local); +void Dijkstra(int tab_local[], int jarak_local[], int pred_local[], int n_local, int n, + MPI_Comm com); + +#endif \ No newline at end of file