gauss seidel
This commit is contained in:
parent
106125e049
commit
405552aafa
88
src/gauss_seidel.c
Normal file
88
src/gauss_seidel.c
Normal 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;
|
||||
}
|
34
src/main.c
34
src/main.c
@ -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;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user