pagerank implementation
This commit is contained in:
		
							
								
								
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										3
									
								
								.gitignore
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,3 @@ | ||||
| *.pdf | ||||
| out/ | ||||
| data/ | ||||
							
								
								
									
										51
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										51
									
								
								Makefile
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,51 @@ | ||||
| # -------------------------------------------------- | ||||
| # Configuration | ||||
| # -------------------------------------------------- | ||||
| CC       := gcc | ||||
| CFLAGS   := -Wall -fopenmp -O3 | ||||
| SRCDIR   := src | ||||
| OBJDIR   := out | ||||
| DATAPATH := data/web-Google/web-Google.mtx | ||||
|  | ||||
| # | ||||
| SRCS     := $(wildcard $(SRCDIR)/*.c) | ||||
| OBJS     := $(patsubst $(SRCDIR)/%.c,$(OBJDIR)/%.o,$(SRCS)) | ||||
|  | ||||
| # -------------------------------------------------- | ||||
| # Phony targets | ||||
| # -------------------------------------------------- | ||||
| .PHONY: all sparse clean | ||||
|  | ||||
| all: sparse | ||||
|  | ||||
| sparse: $(OBJDIR)/sparse | $(OBJDIR) | ||||
| 	@echo "→ Running sparse" | ||||
| 	./$(OBJDIR)/sparse | ||||
|  | ||||
| # -------------------------------------------------- | ||||
| # Link | ||||
| # -------------------------------------------------- | ||||
| $(OBJDIR)/sparse: $(OBJS) $(DATAPATH) | $(OBJDIR) | ||||
| 	@echo "→ Copying input data" | ||||
| 	cp $(DATAPATH) $(OBJDIR)/input.rb | ||||
| 	@echo "→ Linking $@" | ||||
| 	$(CC) $(CFLAGS) -o $@ $(OBJS) | ||||
|  | ||||
| # -------------------------------------------------- | ||||
| # Compile | ||||
| # -------------------------------------------------- | ||||
| $(OBJDIR)/%.o: $(SRCDIR)/%.c | $(OBJDIR) | ||||
| 	@echo "→ Compiling $<" | ||||
| 	$(CC) $(CFLAGS) -c $< -o $@ | ||||
|  | ||||
| # -------------------------------------------------- | ||||
| # Check if output directory exists | ||||
| # -------------------------------------------------- | ||||
| $(OBJDIR): | ||||
| 	mkdir -p $(OBJDIR) | ||||
|  | ||||
| # -------------------------------------------------- | ||||
| # Clean | ||||
| # -------------------------------------------------- | ||||
| clean: | ||||
| 	rm -rf $(OBJDIR)/* | ||||
							
								
								
									
										34
									
								
								src/main.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								src/main.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include "matrix_operation.h" | ||||
| #include "sparse_matrix.h" | ||||
| #include "read_from_rb.h" | ||||
| #include "power_algorithm.h" | ||||
| #include "time_helper.h" | ||||
| #include <sys/time.h> | ||||
|  | ||||
| void test_pagerank(const char *path) { | ||||
|     struct timeval tvstart, tv; | ||||
|     gettimeofday(&tvstart, NULL); | ||||
|  | ||||
|     SparseMatrix *matrix = read_sparse_matrix_from_mtx(path); | ||||
|     convert_to_stochastic(matrix); | ||||
|     // Time 2 | ||||
|     gettimeofday(&tv, NULL); | ||||
|     print_time_diff("read matrix", &tvstart, &tv); | ||||
|     double *result = malloc(matrix->num_nodes * sizeof(double)); | ||||
|     if (result == NULL) { | ||||
|         fprintf(stderr, "Memory allocation failed\n"); | ||||
|         exit(EXIT_FAILURE); | ||||
|     } | ||||
|     result = pagerank(matrix, 1e-10, 0.35); | ||||
|     // Time 3 | ||||
|     gettimeofday(&tv, NULL); | ||||
|     print_time_diff("finish", &tvstart, &tv); | ||||
| } | ||||
|  | ||||
| int main() { | ||||
|     test_pagerank("./out/input.rb"); | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
							
								
								
									
										68
									
								
								src/matrix_operation.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										68
									
								
								src/matrix_operation.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,68 @@ | ||||
| #include "matrix_operation.h" | ||||
| #include "vector.h" | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| void multiply_vector_matrix(const double *vector, const SparseMatrix *matrix, double *result) { | ||||
|     init_vector(result, matrix->num_nodes, 0.0); | ||||
|     for (int i = 0; i < matrix->num_arcs; ++i) { | ||||
|         int origin = matrix->arcs[i].origin; | ||||
|         int dest = matrix->arcs[i].dest; | ||||
|         result[dest] += vector[origin] * matrix->arcs[i].value; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| void multiply_vector_matrix_parallel(const double *vector, const SparseMatrix *matrix, double *result) { | ||||
|     int num_nodes = matrix->num_nodes; | ||||
|     int num_arcs = matrix->num_arcs; | ||||
|     init_vector(result, num_nodes, 0.0); | ||||
|  | ||||
|     #pragma omp parallel | ||||
|     { | ||||
|         double *local_result = (double *)calloc(num_nodes, sizeof(double)); | ||||
|  | ||||
|         // parallelize for loop | ||||
|         #pragma omp for | ||||
|         for (int i = 0; i < num_arcs; ++i) { | ||||
|             int origin = matrix->arcs[i].origin; | ||||
|             int dest = matrix->arcs[i].dest; | ||||
|             local_result[dest] += vector[origin] * matrix->arcs[i].value; | ||||
|         } | ||||
|  | ||||
|         // merge results | ||||
|         for (int j = 0; j < num_nodes; ++j) { | ||||
|             double val = local_result[j]; | ||||
|             if (val != 0.0) { | ||||
|                 #pragma omp atomic | ||||
|                 result[j] += val; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         free(local_result); | ||||
|     } | ||||
| } | ||||
|  | ||||
| void convert_to_stochastic(SparseMatrix *matrix) { | ||||
|     double *non_zero = (double *)calloc(matrix->num_nodes, sizeof(double)); | ||||
|     if (!non_zero) { | ||||
|         fprintf(stderr, "Memory allocation failed\n"); | ||||
|         return; | ||||
|     } | ||||
|  | ||||
|     // count non zero values | ||||
|     for (int i = 0; i < matrix->num_arcs; i++) { | ||||
|         non_zero[matrix->arcs[i].dest] += matrix->arcs[i].value; | ||||
|     } | ||||
|  | ||||
|     // normalize values | ||||
|     for (int i = 0; i < matrix->num_arcs; i++) { | ||||
|         int dest = matrix->arcs[i].dest; | ||||
|         double old_value = matrix->arcs[i].value; | ||||
|         matrix->arcs[i].value = old_value / (double)non_zero[dest]; | ||||
|     } | ||||
|  | ||||
|     free(non_zero); | ||||
| } | ||||
|  | ||||
							
								
								
									
										9
									
								
								src/matrix_operation.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								src/matrix_operation.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| #ifndef MATRIX_OPERATION_H | ||||
| #define MATRIX_OPERATION_H | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| void multiply_vector_matrix(const double *vector, const SparseMatrix *matrix, double *result); | ||||
| void multiply_vector_matrix_parallel(const double *vector, const SparseMatrix *matrix, double *result); | ||||
| void convert_to_stochastic(SparseMatrix *matrix); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										21
									
								
								src/matrix_print.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/matrix_print.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| #include <stdio.h> | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| void print_vector(double *vector, int size) { | ||||
|     for (int i = 0; i < size; ++i) { | ||||
|         printf("%lf ", vector[i]); | ||||
|     } | ||||
|     printf("\n"); | ||||
| } | ||||
|  | ||||
| void print_sparse_matrix(const SparseMatrix *matrix) { | ||||
|     if (matrix) { | ||||
|         printf("%d %d %d\n", matrix->num_nodes, matrix->num_nodes, matrix->num_arcs); | ||||
|         for (int i = 0; i < matrix->num_arcs; ++i) { | ||||
|             printf("%d ", matrix->arcs[i].origin + 1); | ||||
|             printf("%d ", matrix->arcs[i].dest + 1); | ||||
|             printf("%.10f ", matrix->arcs[i].value); | ||||
|             printf("\n"); | ||||
|         } | ||||
|     } | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/matrix_print.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/matrix_print.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #ifndef MATRIX_PRINT_H | ||||
| #define MATRIX_PRINT_H | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| void print_vector(double *vector, int size); | ||||
| void print_sparse_matrix(const SparseMatrix *matrix); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										78
									
								
								src/power_algorithm.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										78
									
								
								src/power_algorithm.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,78 @@ | ||||
| #include <stdlib.h> | ||||
| #include <stdio.h> | ||||
| #include <string.h> | ||||
| #include "sparse_matrix.h" | ||||
| #include "matrix_operation.h" | ||||
| #include "vector.h" | ||||
|  | ||||
| double* power_algorithm_step(const SparseMatrix *matrix, const double *pi) { | ||||
|     double* result = malloc(matrix->num_nodes*sizeof(double)); | ||||
|     multiply_vector_matrix_parallel(pi, matrix, result); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| double* power_algorithm(const SparseMatrix *matrix, double epsilon) { | ||||
|     int N = matrix->num_nodes; | ||||
|     int vecsize = N*sizeof(double); | ||||
|     double* pi = malloc(vecsize); | ||||
|     double* pi2 = malloc(vecsize); | ||||
|     init_vector(pi, N, 1.0/(double)N); | ||||
|     pi2 = power_algorithm_step(matrix, pi); | ||||
|     while (diff_norm_vector(pi, pi2, N)>epsilon) { | ||||
|         printf("step\n"); | ||||
|         memcpy(pi, pi2, vecsize); | ||||
|         pi2 = power_algorithm_step(matrix, pi); | ||||
|     } | ||||
|     return pi2; | ||||
| } | ||||
|  | ||||
| double* pagerank(const SparseMatrix *matrix, double epsilon, double alpha) { | ||||
|     int N = matrix->num_nodes; | ||||
|     size_t vec_size = N * sizeof(double); | ||||
|  | ||||
|     double* pi = malloc(vec_size); | ||||
|     double* pi_new = malloc(vec_size); | ||||
|     double* f = malloc(vec_size); | ||||
|     double right_const = (1.0 - alpha) / N; | ||||
|  | ||||
|     init_vector(pi, N, 1.0 / N); | ||||
|  | ||||
|     generate_f(matrix, f); | ||||
|  | ||||
|     double diff; | ||||
|     int iter = 0; | ||||
|  | ||||
|     do { | ||||
|         // 1. pi * M | ||||
|         double* temp = power_algorithm_step(matrix, pi); | ||||
|  | ||||
|         // 2. alpha/N * (pi * f) | ||||
|         double right_var = (alpha/(double)N) * vec_product(pi, f, N); | ||||
|  | ||||
|         // 3. alpha*(pi*M) + (right_const+alpha/N * (pi * f))*e | ||||
|         for (int i = 0; i < N; i++) { | ||||
|             pi_new[i] = alpha * temp[i] + right_const + right_var; | ||||
|         } | ||||
|  | ||||
|         // 4. Normalize | ||||
|         normalize_vector(pi_new, N); | ||||
|  | ||||
|         // 5. Calculate convergence | ||||
|         diff = diff_norm_vector(pi, pi_new, N); | ||||
|  | ||||
|         // 6. Update for next iteration | ||||
|         free(pi); | ||||
|         pi = pi_new; | ||||
|         pi_new = malloc(vec_size); | ||||
|  | ||||
|         if ((++iter)%1 == 0) { | ||||
|             printf("Iteration %d: diff = %.16f\n", iter, diff); | ||||
|         } | ||||
|         free(temp); | ||||
|     } while (diff > epsilon); | ||||
|  | ||||
|     free(pi_new); | ||||
|     free(f); | ||||
|     return pi; | ||||
| } | ||||
|  | ||||
							
								
								
									
										8
									
								
								src/power_algorithm.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/power_algorithm.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #ifndef POWER_ALGORITHM_H | ||||
| #define POWER_ALGORITHM_H | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| double* power_algorithm(const SparseMatrix *matrix, double epsilon); | ||||
| double* pagerank(const SparseMatrix *matrix, double epsilon, double alpha); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										71
									
								
								src/read_from_mtx.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								src/read_from_mtx.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,71 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| int read_dims_ignore_comment(SparseMatrix *matrix, FILE *file) { | ||||
|     char buffer[1024]; | ||||
|     int read_dims = 0; | ||||
|     while (fgets(buffer, sizeof(buffer), file) != NULL) { | ||||
|         char *line = buffer; | ||||
|         if (*line == '%' || *line == '\n' || *line == '\0') { | ||||
|             continue; | ||||
|         } else { | ||||
|             if (sscanf(line, "%d %d", &matrix->num_nodes, &matrix->num_arcs) != 2) { | ||||
|                 return 1; | ||||
|             } | ||||
|             read_dims = 1; | ||||
|             break; | ||||
|         } | ||||
|     } | ||||
|     return (!read_dims); | ||||
| } | ||||
|  | ||||
| void parse_arcs(SparseMatrix *matrix, FILE *file) { | ||||
|     for (int i = 0; i < matrix->num_arcs; ++i) { | ||||
|         char line[256]; | ||||
|         if (fgets(line, sizeof(line), file) == NULL) { | ||||
|             fprintf(stderr, "Failed to read arc %d\n", i); | ||||
|             exit(5); | ||||
|         } | ||||
|         char *ptr = line; | ||||
|         int origin, dest; | ||||
|         double value = 1.0; | ||||
|         if (sscanf(ptr, "%d %d %lf", &origin, &dest, &value) < 2) { | ||||
|             fprintf(stderr, "Failed to read arc %d\n", i); | ||||
|             exit(5); | ||||
|         } else { | ||||
|             matrix->arcs[i].origin = origin; | ||||
|             matrix->arcs[i].dest = dest; | ||||
|             matrix->arcs[i].value = value; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| SparseMatrix* read_sparse_matrix_from_mtx(const char *filename) { | ||||
|     FILE *file = fopen(filename, "r"); | ||||
|     if (!file) { | ||||
|         fprintf(stderr, "Failed to read file\n"); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     SparseMatrix *matrix = (SparseMatrix*)malloc(sizeof(SparseMatrix)); | ||||
|     if (!matrix) { | ||||
|         fprintf(stderr, "Failed to allocate memory for matrix\n"); | ||||
|         exit(3); | ||||
|     } | ||||
|  | ||||
|     if (read_dims_ignore_comment(matrix, file)) { | ||||
|         fprintf(stderr, "Failed to read matrix dimensions\n"); | ||||
|     } | ||||
|  | ||||
|     matrix->arcs = (Arc*)malloc(matrix->num_arcs * sizeof(Arc)); | ||||
|     if (!matrix->arcs) { | ||||
|         fprintf(stderr, "Failed to allocate memory for arcs\n"); | ||||
|         exit(4); | ||||
|     } | ||||
|  | ||||
|     parse_arcs(matrix, file); | ||||
|  | ||||
|     fclose(file); | ||||
|     return matrix; | ||||
| } | ||||
							
								
								
									
										7
									
								
								src/read_from_mtx.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								src/read_from_mtx.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| #ifndef MATRIX_READ_MTX_H | ||||
| #define MATRIX_READ_MTX_H | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| SparseMatrix* read_sparse_matrix_from_mtx(const char *filename); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										105
									
								
								src/read_from_rb.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										105
									
								
								src/read_from_rb.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,105 @@ | ||||
| #include <stdio.h> | ||||
| #include <stdlib.h> | ||||
| #include "read_from_rb.h" | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| SparseMatrix* read_sparse_matrix_from_rb(const char *filename) { | ||||
|     FILE *file = fopen(filename, "r"); | ||||
|     if (!file) { | ||||
|         fprintf(stderr, "Failed to open file %s\n", filename); | ||||
|         exit(1); | ||||
|     } | ||||
|  | ||||
|     SparseMatrix *matrix = (SparseMatrix*)malloc(sizeof(SparseMatrix)); | ||||
|     if (!matrix) { | ||||
|         fprintf(stderr, "Failed to allocate memory for matrix\n"); | ||||
|         exit(2); | ||||
|     } | ||||
|  | ||||
|     char buffer[256]; | ||||
|     fgets(buffer, sizeof(buffer), file); | ||||
|     fgets(buffer, sizeof(buffer), file); | ||||
|  | ||||
|     fgets(buffer, sizeof(buffer), file); | ||||
|     char type[4]; | ||||
|     int rows, cols, nonzero; | ||||
|     if (sscanf(buffer, "%3s %d %d %d", type, &rows, &cols, &nonzero) != 4) { | ||||
|         fprintf(stderr, "Failed to read matrix metadata\n"); | ||||
|         exit(3); | ||||
|     } | ||||
|  | ||||
|     matrix->num_nodes = rows; | ||||
|     matrix->num_arcs = nonzero; | ||||
|     matrix->arcs = (Arc*)malloc(nonzero * sizeof(Arc)); | ||||
|     if (!matrix->arcs) { | ||||
|         fprintf(stderr, "Failed to allocate memory for arcs\n"); | ||||
|         exit(4); | ||||
|     } | ||||
|  | ||||
|     fgets(buffer, sizeof(buffer), file); | ||||
|  | ||||
|     int *col_ptr = (int*)malloc((cols + 1) * sizeof(int)); | ||||
|     int ptr_index = 0; | ||||
|     while (ptr_index < cols + 1) { | ||||
|         if (fgets(buffer, sizeof(buffer), file) == NULL) { | ||||
|             fprintf(stderr, "Unexpected end of file while reading column pointers\n"); | ||||
|             exit(5); | ||||
|         } | ||||
|         char *ptr = buffer; | ||||
|         int num_read; | ||||
|         while (sscanf(ptr, "%d%n", &col_ptr[ptr_index], &num_read) == 1) { | ||||
|             ptr += num_read; | ||||
|             ptr_index++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     int *row_ind = (int*)malloc(nonzero * sizeof(int)); | ||||
|     int row_index = 0; | ||||
|     while (row_index < nonzero) { | ||||
|         if (fgets(buffer, sizeof(buffer), file) == NULL) { | ||||
|             fprintf(stderr, "Unexpected end of file while reading row indices\n"); | ||||
|             exit(6); | ||||
|         } | ||||
|         char *ptr = buffer; | ||||
|         int num_read; | ||||
|         while (sscanf(ptr, "%d%n", &row_ind[row_index], &num_read) == 1) { | ||||
|             ptr += num_read; | ||||
|             row_index++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     double *values = (double*)malloc(nonzero * sizeof(double)); | ||||
|     int val_index = 0; | ||||
|     while (val_index < nonzero) { | ||||
|         if (fgets(buffer, sizeof(buffer), file) == NULL) { | ||||
|             fprintf(stderr, "Unexpected end of file while reading values\n"); | ||||
|             exit(7); | ||||
|         } | ||||
|         char *ptr = buffer; | ||||
|         int num_read; | ||||
|         double val; | ||||
|         while (sscanf(ptr, "%lf%n", &val, &num_read) == 1) { | ||||
|             values[val_index] = val; | ||||
|             ptr += num_read; | ||||
|             val_index++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     int arc_idx = 0; | ||||
|     for (int j = 0; j < cols; j++) { | ||||
|         int start = col_ptr[j] - 1; | ||||
|         int end = col_ptr[j + 1] - 1; | ||||
|         for (int k = start; k < end; k++) { | ||||
|             matrix->arcs[arc_idx].origin = j; | ||||
|             matrix->arcs[arc_idx].dest = row_ind[k] - 1; | ||||
|             matrix->arcs[arc_idx].value = values[k]; | ||||
|             arc_idx++; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     free(col_ptr); | ||||
|     free(row_ind); | ||||
|     free(values); | ||||
|     fclose(file); | ||||
|     return matrix; | ||||
| } | ||||
							
								
								
									
										8
									
								
								src/read_from_rb.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										8
									
								
								src/read_from_rb.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,8 @@ | ||||
| #ifndef RB_READER_H | ||||
| #define RB_READER_H | ||||
|  | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| SparseMatrix* read_sparse_matrix_from_rb(const char *filename); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										11
									
								
								src/sparse_matrix.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/sparse_matrix.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| #include "sparse_matrix.h" | ||||
| #include <stdlib.h> | ||||
|  | ||||
| void free_sparse_matrix(SparseMatrix *matrix) { | ||||
|     if (matrix) { | ||||
|         free(matrix->arcs); | ||||
|         free(matrix); | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
							
								
								
									
										21
									
								
								src/sparse_matrix.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/sparse_matrix.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | ||||
| #ifndef SPARSE_MATRIX_H | ||||
| #define SPARSE_MATRIX_H | ||||
|  | ||||
| typedef struct { | ||||
|     int origin; | ||||
|     int dest; | ||||
|     double value; | ||||
| } Arc; | ||||
|  | ||||
| typedef struct { | ||||
|     int num_nodes; | ||||
|     int num_arcs; | ||||
|     Arc *arcs; | ||||
| } SparseMatrix; | ||||
|  | ||||
| void free_sparse_matrix(SparseMatrix *matrix); | ||||
| void print_sparse_matrix(const SparseMatrix *matrix); | ||||
| SparseMatrix* read_sparse_matrix_from_mtx(const char *filename); | ||||
| void multiply_vector_matrix(const double *vector, const SparseMatrix *matrix, double *result); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										12
									
								
								src/time_helper.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										12
									
								
								src/time_helper.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,12 @@ | ||||
| #include <sys/time.h> | ||||
| #include <stdio.h> | ||||
|  | ||||
| void print_time_diff(const char* label, struct timeval* start, struct timeval* end) { | ||||
|     long seconds = end->tv_sec - start->tv_sec; | ||||
|     long microseconds = end->tv_usec - start->tv_usec; | ||||
|     if (microseconds < 0) { | ||||
|         seconds -= 1; | ||||
|         microseconds += 1000000; | ||||
|     } | ||||
|     printf("%s: %ld.%ld seconds\n", label, seconds, microseconds); | ||||
| } | ||||
							
								
								
									
										6
									
								
								src/time_helper.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										6
									
								
								src/time_helper.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,6 @@ | ||||
| #ifndef TIME_HELPER_H | ||||
| #define TIME_HELPER_H | ||||
|  | ||||
| void print_time_diff(const char* label, struct timeval* start, struct timeval* end); | ||||
|  | ||||
| #endif | ||||
							
								
								
									
										43
									
								
								src/vector.c
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										43
									
								
								src/vector.c
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,43 @@ | ||||
| #include <math.h> | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| void init_vector(double *vector, int size, double value) { | ||||
|     for (int i = 0; i < size; ++i) { | ||||
|         vector[i] = value; | ||||
|     } | ||||
| } | ||||
|  | ||||
| double diff_norm_vector(double *vector1, double *vector2, int size) { | ||||
|     double res = 0.0; | ||||
|     for (int i = 0; i < size; ++i) { | ||||
|         res += fabs(vector1[i] - vector2[i]); | ||||
|     } | ||||
|     return res; | ||||
| } | ||||
|  | ||||
| void generate_f(const SparseMatrix *matrix, double *res) { | ||||
|     int N = matrix->num_nodes; | ||||
|     init_vector(res, N, 0); | ||||
|     int num_arcs = matrix->num_arcs; | ||||
|     for (int i = 0; i < num_arcs; ++i) { | ||||
|         res[matrix->arcs[i].dest] = 1; | ||||
|     } | ||||
| } | ||||
|  | ||||
| double vec_product(const double* v1, const double* v2, int N) { | ||||
|     double sum = 0.0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sum += v1[i] * v2[i]; | ||||
|     } | ||||
|     return sum; | ||||
| } | ||||
|  | ||||
| void normalize_vector(double* v, int N) { | ||||
|     double sum = 0.0; | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         sum += v[i]; | ||||
|     } | ||||
|     for (int i = 0; i < N; i++) { | ||||
|         v[i] /= sum; | ||||
|     } | ||||
| } | ||||
							
								
								
									
										11
									
								
								src/vector.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										11
									
								
								src/vector.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,11 @@ | ||||
| #ifndef VECTOR_H | ||||
| #define VECTOR_H | ||||
| #include "sparse_matrix.h" | ||||
|  | ||||
| void init_vector(double *vector, int size, double value); | ||||
| double diff_norm_vector(double *vector1, double *vector2, int size); | ||||
| void generate_f(const SparseMatrix *matrix, double *res); | ||||
| void normalize_vector(double* v, int N); | ||||
| double vec_product(const double* v1, const double* v2, int N); | ||||
|  | ||||
| #endif | ||||
		Reference in New Issue
	
	Block a user