gauss seidel

This commit is contained in:
Sam Hadow 2025-05-14 18:39:30 +02:00
parent 106125e049
commit 405552aafa
2 changed files with 115 additions and 7 deletions

88
src/gauss_seidel.c Normal file
View File

@ -0,0 +1,88 @@
/*
* Gauss-Seidel Descendant PageRank Implementation
*/
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "sparse_matrix.h"
#include "vector.h"
double* gauss_seidel_pagerank(const SparseMatrix *matrix, double epsilon, double alpha) {
int N = matrix->num_nodes;
size_t vec_size = N * sizeof(double);
double *x = malloc(vec_size);
double *x_old = malloc(vec_size);
double *f = malloc(vec_size);
double right_const = (1.0 - alpha) / N;
if (!x || !x_old || !f) {
fprintf(stderr, "Memory allocation failed\n");
exit(EXIT_FAILURE);
}
init_vector(x, N, 1.0 / N);
generate_f(matrix, f);
double diff;
int iter = 0;
do {
// 1. store x from previous step
memcpy(x_old, x, vec_size);
// 2. alpha/N * (x * f)
double x_f = vec_product(x_old, f, N);
double right_var = (alpha / (double)N) * x_f;
// 3. alpha*(pi*M) + (right_const+alpha/N * (pi * f))*e
// splitted in 2 parts (2 sums instead of one)
// Can't use previously defined multiply_vector_matrix_parallel function here
//
// sum from 1 to i-1: use old x
// i=j: use value M(i,i)
// sum from i+1 to n: use x
//
// Gauss Seidel descending, so i from n to 0
//
for (int i = N - 1; i >= 0; i--) {
double result_mult = 0.0;
double M_ii = 0.0;
for (int k = matrix->row_ptr[i]; k < matrix->row_ptr[i + 1]; k++) {
int j = matrix->arcs[k].dest;
double value = matrix->arcs[k].value;
if (j == i) {
M_ii = value;
} else if (j > i) {
result_mult += value * x[j];
} else {
result_mult += value * x_old[j];
}
}
double diag_dependant_term = 1.0 - alpha * M_ii;
x[i] = (alpha * result_mult + right_const + right_var) / diag_dependant_term;
}
// 4. renormalization step
normalize_vector(x, N);
// 5. convergence
diff = diff_norm_vector(x, x_old, N);
// if ((++iter) % 10 == 0) {
// printf("Gauss-Seidel Iteration %d: diff = %.16f\n", iter, diff);
// }
++iter;
} while (diff > epsilon);
printf("Gauss-Seidel: %d Iterations\n", iter);
free(x_old);
free(f);
// x ~ pi (convergence)
return x;
}

View File

@ -8,8 +8,9 @@
#include "gauss_seidel.h"
#include "time_helper.h"
#include <sys/time.h>
#include <string.h>
void test_stationary_distribution(const char *path) {
void test_stationary_distribution(const char *path, double epsilon, double alpha) {
struct timeval tvstart, tvend;
gettimeofday(&tvstart, NULL);
@ -18,9 +19,6 @@ void test_stationary_distribution(const char *path) {
gettimeofday(&tvend, NULL);
print_time_diff("Read and convert matrix", &tvstart, &tvend);
double epsilon = 1e-10;
double alpha = 0.8;
gettimeofday(&tvstart, NULL);
double *pi_power = pagerank(matrix, epsilon, alpha);
gettimeofday(&tvend, NULL);
@ -30,7 +28,7 @@ void test_stationary_distribution(const char *path) {
double *pi_new = gauss_seidel_pagerank(matrix, epsilon, alpha);
gettimeofday(&tvend, NULL);
print_time_diff("Gauss-Seidel:", &tvstart, &tvend);
print_time_diff("Gauss-Seidel", &tvstart, &tvend);
double diff = diff_norm_vector(pi_power, pi_new, matrix->num_nodes);
printf("Difference norm Pagerank and Gauss-Seidel: %.16f\n", diff);
@ -40,7 +38,29 @@ void test_stationary_distribution(const char *path) {
free_sparse_matrix(matrix);
}
int main() {
test_stationary_distribution("./out/input.mtx");
int main(int argc, char *argv[]) {
const char *matrix_path = NULL;
double epsilon = -1.0;
double alpha = -1.0;
for (int i = 1; i < argc; i++) {
if ((strcmp(argv[i], "--matrix") == 0 || strcmp(argv[i], "-matrix") == 0) && i + 1 < argc) {
matrix_path = argv[++i];
} else if ((strcmp(argv[i], "--epsilon") == 0 || strcmp(argv[i], "-epsilon") == 0) && i + 1 < argc) {
epsilon = atof(argv[++i]);
} else if ((strcmp(argv[i], "--alpha") == 0 || strcmp(argv[i], "-alpha") == 0) && i + 1 < argc) {
alpha = atof(argv[++i]);
} else {
fprintf(stderr, "Unknown or incomplete argument: %s\n", argv[i]);
return EXIT_FAILURE;
}
}
if (matrix_path == NULL || epsilon <= 0 || alpha < 0 || alpha > 1) {
fprintf(stderr, "Usage: %s --matrix <path> --epsilon <value> --alpha <value>\n", argv[0]);
return EXIT_FAILURE;
}
test_stationary_distribution(matrix_path, epsilon, alpha);
return 0;
}