Browse Source

Add files via upload

master
mtzikara 6 years ago
committed by GitHub
parent
commit
db89249ad6
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      serial_csr/Makefile
  2. 263
      serial_csr/csr_sparse_matrix.c
  3. 31
      serial_csr/csr_sparse_matrix.h
  4. BIN
      serial_csr/csr_sparse_matrix.o
  5. 76
      serial_csr/lil_sparse_matrix.c
  6. 29
      serial_csr/lil_sparse_matrix.h
  7. BIN
      serial_csr/lil_sparse_matrix.o
  8. BIN
      serial_csr/pagerank.out
  9. 1
      serial_csr/pagerank_output
  10. 44
      serial_csr/serial_gs_pagerank.c
  11. BIN
      serial_csr/serial_gs_pagerank.o
  12. 525
      serial_csr/serial_gs_pagerank_functions.c
  13. 99
      serial_csr/serial_gs_pagerank_functions.h
  14. BIN
      serial_csr/serial_gs_pagerank_functions.o

37
serial_csr/Makefile

@ -0,0 +1,37 @@
SHELL := /bin/bash
# ============================================
# COMMANDS
CC = gcc -std=gnu99
RM = rm -f
CFLAGS_DEBUG=-O0 -ggdb3 -Wall -I.
CFLAGS=-O3 -Wall -I.
OBJ=serial_gs_pagerank.o serial_gs_pagerank_functions.o csr_sparse_matrix.o lil_sparse_matrix.o
DEPS=serial_gs_pagerank_functions.h csr_sparse_matrix.h lil_sparse_matrix.h
# ==========================================
# TARGETS
EXECUTABLES = pagerank.out
.PHONY: all clean
all: $(EXECUTABLES)
# ==========================================
# DEPENDENCIES (HEADERS)
%.o: %.c $(DEPS)
$(CC) -c -o $@ $< $(CFLAGS)
.PRECIOUS: $(EXECUTABLES) $(OBJ)
# ==========================================
# EXECUTABLE (MAIN)
$(EXECUTABLES): $(OBJ)
$(CC) -o $@ $^ $(CFLAGS)
clean:
$(RM) *.o *~ $(EXECUTABLES)

263
serial_csr/csr_sparse_matrix.c

@ -0,0 +1,263 @@
#include "csr_sparse_matrix.h"
CsrSparseMatrix initCsrSparseMatrix() {
CsrSparseMatrix sparseMatrix;
sparseMatrix.size = 0;
sparseMatrix.nnz = 0;
sparseMatrix.values = NULL;
sparseMatrix.columnIndexes = NULL;
sparseMatrix.rowaccInd = NULL;
return sparseMatrix;
}
void allocMemoryForElements (CsrSparseMatrix *sparseMatrix, int edges) {
sparseMatrix->values = (double *) malloc(
edges * sizeof(double));
sparseMatrix->columnIndexes = (int *) malloc(
edges * sizeof(int));
sparseMatrix->rowaccInd = (int *) malloc(
edges * sizeof(int));
}
void addElement(CsrSparseMatrix *sparseMatrix, double value, int row, int column) {
for(int i=row+1; i<sparseMatrix->size; ++i){
++sparseMatrix->rowaccInd[i];
}
sparseMatrix->nnz = sparseMatrix->nnz+1;
sparseMatrix->values[sparseMatrix->rowaccInd[row-1]+1] = value;
sparseMatrix->columnIndexes[sparseMatrix->rowaccInd[row-1]+1] = column;
// Creates the new element
/*CsrSparseMatrixElement *newElement = (CsrSparseMatrixElement *) malloc(
sizeof(CsrSparseMatrixElement));
newElement->value = value;
newElement->rowIndex = row;
newElement->columnIndex = column;
sparseMatrix->elements[sparseMatrix->size] = newElement;
sparseMatrix->size = sparseMatrix->size + 1; */
}
void zeroOutRow(CsrSparseMatrix *sparseMatrix, int row) {
int noofnnzinrow;
if(row==0){
noofnnzinrow = sparseMatrix->rowaccInd[row];
}
else{
noofnnzinrow = sparseMatrix->rowaccInd[row]-sparseMatrix->rowaccInd[row-1];
}
int startdeleteInd = sparseMatrix->rowaccInd[row-1]+1;
//delete the values and columnindexes of these rows by moving up the rest
for(int i=0; i<noofnnzinrow; ++i){
sparseMatrix->values[i+startdeleteInd] = sparseMatrix->values[sparseMatrix->nnz-noofnnzinrow+i];
sparseMatrix->values[sparseMatrix->nnz-noofnnzinrow+i] = 0;
sparseMatrix->columnIndexes[i+startdeleteInd] = sparseMatrix->columnIndexes[sparseMatrix->nnz-noofnnzinrow+i];
sparseMatrix->columnIndexes[sparseMatrix->nnz-noofnnzinrow+i] = 0;
}
sparseMatrix->nnz = sparseMatrix->nnz - noofnnzinrow;
//substract from accumulative no. of row nnz elements
for(int i=row; i<sparseMatrix->size ; ++i){
sparseMatrix->rowaccInd[i] -= noofnnzinrow;
}
/*for (int i=0; i<sparseMatrix->size; ++i) {
CooSparseMatrixElement *element = sparseMatrix->elements[i];
if (element->rowIndex == row) {
element->value = 0;
}
}*/
}
void zeroOutColumn(CsrSparseMatrix *sparseMatrix, int column) {
/*for (int i=0; i<sparseMatrix->size; ++i) {
CooSparseMatrixElement *element = sparseMatrix->elements[i];
if (element->columnIndex == column) {
element->value = 0;
}
}
*/
for (int i=0; i<sparseMatrix->nnz; ++i){
if(sparseMatrix->columnIndexes[i] == column){
//delete columns by moving up the rest
for(int j=i; j<sparseMatrix->nnz-1; ++j){
sparseMatrix->columnIndexes[j] = sparseMatrix->columnIndexes[j+1];
sparseMatrix->values[j] = sparseMatrix->values[j+1];
}
int flag = 0;
//adjust rowaccInd
for(int j=0; j<sparseMatrix->size; ++j){
if(sparseMatrix->rowaccInd[j] > i){
flag = 1; //must be substracted since column belonged to this row
}
if(flag){
--sparseMatrix->rowaccInd[j]; //substract till end of rows
}
}
}
}
}
int *getRowIndexes(CsrSparseMatrix sparseMatrix, int row, int *rowSize) {
*rowSize = 0;
/*for (int i=0; i<sparseMatrix.size; ++i) {
if (sparseMatrix.elements[i]->rowIndex == row) {
++(*rowSize);
}
}
if (!(*rowSize)) {
return NULL;
}*/
if((row-1)>0 && (sparseMatrix.rowaccInd[row]-sparseMatrix.rowaccInd[row-1])>0){
(*rowSize) = sparseMatrix.rowaccInd[row]-sparseMatrix.rowaccInd[row-1];
}
else if((sparseMatrix.rowaccInd[row]-sparseMatrix.rowaccInd[row-1])>0){ //if row = 0
(*rowSize) = sparseMatrix.rowaccInd[row];
}
else{
return NULL;
}
int *indexes = (int *) malloc((*rowSize) * sizeof(int));
for (int i=1; i<=(*rowSize); ++i) {
indexes[i-1] = sparseMatrix.rowaccInd[row-1]+i;
}
return indexes;
}
void transposeSparseMatrix(CsrSparseMatrix *sparseMatrix) {
/*for (int i=0; i<sparseMatrix->size; ++i) {
CooSparseMatrixElement *element = sparseMatrix->elements[i];
int tempRow = element->rowIndex;
element->rowIndex = element->columnIndex;
element->columnIndex = tempRow;
}*/
double* values_t = (double *) malloc(
sparseMatrix->size * sizeof(double));
int* rowIndexes = (int *) malloc(
sparseMatrix->size * sizeof(int));
int* colaccInd = (int *) malloc(
sparseMatrix->size * sizeof(int));
int columncount, nnznew = 0;
//for all columns
for(columncount = 0; columncount<sparseMatrix->size; ++columncount){
//index for searching in columnIndexes matrix
for(int i = 0; i<sparseMatrix->nnz;++i){
if(sparseMatrix->columnIndexes[i] == columncount){
//Find which row it belongs to
for(int j=0; j<sparseMatrix->size; ++j){
if(sparseMatrix->rowaccInd[j] == i){
rowIndexes[nnznew] = j-1;
values_t[nnznew] = sparseMatrix->values[i];
for(int k=i; k<sparseMatrix->size; ++k){
++colaccInd[k];
}
++nnznew;
}
}
}
}
}
memcpy(sparseMatrix->values, values_t, sparseMatrix->size*sizeof(double));
memcpy(sparseMatrix->columnIndexes, rowIndexes, sparseMatrix->size*sizeof(int));
memcpy(sparseMatrix->rowaccInd, colaccInd, sparseMatrix->size*sizeof(int) );
sparseMatrix->nnz = nnznew;
}
void csrSparseMatrixVectorMultiplication(CsrSparseMatrix sparseMatrix,
double *vector, double **product, int vectorSize) {
// Initializes the elements of the product vector to zero
for (int i=0; i<vectorSize; ++i) {
(*product)[i] = 0;
}
/*CooSparseMatrixElement *element;
for (int i=0; i<sparseMatrix.size; ++i) {
element = sparseMatrix.elements[i];
int row = element->rowIndex, column = element->columnIndex;
if (row >= vectorSize) {
printf("Error at sparseMatrixVectorMultiplication. Matrix has more rows than vector!\n");
printf("row = %d\n", row);
exit(EXIT_FAILURE);
}
(*product)[row] = (*product)[row] + element->value * vector[column];
}*/
int t;
//for every row
for (int i=0; i<sparseMatrix.size; ++i) {
if(i==0){
t = sparseMatrix.rowaccInd[0];
}
else{
t = sparseMatrix.rowaccInd[i]-sparseMatrix.rowaccInd[i-1];
}
for(int j=0; j<t; ++j){
for(int k=0; k<vectorSize; ++k){
if(sparseMatrix.columnIndexes[sparseMatrix.rowaccInd[i]+t]==k){
(*product)[k] += sparseMatrix.values[sparseMatrix.rowaccInd[i]+t]*vector[k];
}
else if(sparseMatrix.columnIndexes[sparseMatrix.rowaccInd[i]+t]>k){
printf("Error at sparseMatrixVectorMultiplication. Matrix has more columns than vector rows!\n");
exit(EXIT_FAILURE);
}
}
}
}
}
void destroyCsrSparseMatrix(CsrSparseMatrix *sparseMatrix) {
/*for (int i=0; i<sparseMatrix->size; ++i) {
free(sparseMatrix->elements[i]);
}*/
free(sparseMatrix->values);
free(sparseMatrix->rowaccInd);
free(sparseMatrix->columnIndexes);
}
void printCsrSparseMatrix(CsrSparseMatrix sparseMatrix) {
if (sparseMatrix.size == 0) {
return;
}
/*
CooSparseMatrixElement *element;
for (int i=0; i<sparseMatrix.size; ++i) {
element = sparseMatrix.elements[i];
printf("[%d,%d] = %f\n", element->rowIndex, element->columnIndex,
element->value);
}*/
int t;
for (int i=0; i<sparseMatrix.size; ++i){
if(i==0){
t = sparseMatrix.rowaccInd[i];
}
else{
t = sparseMatrix.rowaccInd[i]-sparseMatrix.rowaccInd[i-1];
}
for(int j=0; j<t ; ++j){
printf("Row [%d] has [%d] nz elements: \n at column[%d] is value = %f \n",
i, t, sparseMatrix.columnIndexes[sparseMatrix.rowaccInd[i]+j], sparseMatrix.values[sparseMatrix.rowaccInd[i]+j]);
}
}
}

31
serial_csr/csr_sparse_matrix.h

@ -0,0 +1,31 @@
#ifndef CSR_SPARSE_MATRIX_H /* Include guard */
#define CSR_SPARSE_MATRIX_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
typedef struct csrSparseMatrix {
double* values;
int* rowaccInd; //without the first cell, always 0
int* columnIndexes;
int size; //no. of rows
int nnz; //no. of non zero elements
} CsrSparseMatrix;
CsrSparseMatrix initCsrSparseMatrix();
void allocMemoryForElements (CsrSparseMatrix *sparseMatrix, int edges);
void addElement(CsrSparseMatrix *sparseMatrix, double value, int row, int column);
void zeroOutRow(CsrSparseMatrix *sparseMatrix, int row);
void zeroOutColumn(CsrSparseMatrix *sparseMatrix, int column);
int *getRowIndexes(CsrSparseMatrix sparseMatrix, int row, int *rowSize);
void transposeSparseMatrix(CsrSparseMatrix *sparseMatrix);
void csrSparseMatrixVectorMultiplication(CsrSparseMatrix sparseMatrix, double *vector,
double **product, int vectorSize);
void destroyCsrSparseMatrix(CsrSparseMatrix *sparseMatrix);
void printCsrSparseMatrix(CsrSparseMatrix sparseMatrix);
#endif // CSR_SPARSE_MATRIX_H

BIN
serial_csr/csr_sparse_matrix.o

Binary file not shown.

76
serial_csr/lil_sparse_matrix.c

@ -0,0 +1,76 @@
#include "lil_sparse_matrix.h"
LilSparseMatrix createLilSparseMatrix() {
LilSparseMatrix sparseMatrix;
sparseMatrix.elements = 0;
sparseMatrix.firstElement = NULL;
sparseMatrix.lastElement = NULL;
return sparseMatrix;
}
void apendElement(LilSparseMatrix *sparseMatrix, double value, int row, int column) {
// Creates the new element
LilSparseMatrixElement *newElement = (LilSparseMatrixElement *) malloc(sizeof(LilSparseMatrixElement));
newElement->value = value;
newElement->rowIndex = row;
newElement->columnIndex = column;
newElement->nextElement = NULL;
if (sparseMatrix->firstElement == NULL) {
// Sparse matrix is empty, this is the first element
sparseMatrix->firstElement = newElement;
sparseMatrix->lastElement = newElement;
} else {
//Gets last element of the matrix
LilSparseMatrixElement *lastElement = sparseMatrix->lastElement;
lastElement->nextElement = newElement;
sparseMatrix->lastElement = newElement;
}
sparseMatrix->elements = sparseMatrix->elements + 1;
}
void lilSparseMatrixVectorMultiplication(LilSparseMatrix sparseMatrix,
double *vector, double **product, int vectorSize) {
// Initializes the elements of the product vector to zero
for (int i=0; i<vectorSize; ++i) {
(*product)[i] = 0;
}
LilSparseMatrixElement *element = sparseMatrix.firstElement;
for (int i=0; i<sparseMatrix.elements; ++i) {
int row = element->rowIndex, column = element->columnIndex;
if (row >= vectorSize) {
printf("Error at sparseMatrixVectorMultiplication. Matrix has more rows than vector!\n");
printf("row = %d\n", row);
exit(EXIT_FAILURE);
}
(*product)[row] = (*product)[row] + element->value * vector[column];
element = element->nextElement;
}
}
void destroyLilSparseMatrix(LilSparseMatrix *sparseMatrix) {
LilSparseMatrixElement *currentElement = sparseMatrix->firstElement;
while (currentElement != NULL) {
LilSparseMatrixElement *toDelete = currentElement;
currentElement = currentElement->nextElement;
free(toDelete);
}
}
void printLilSparseMatrix(LilSparseMatrix sparseMatrix) {
if (sparseMatrix.elements == 0) {
return;
}
LilSparseMatrixElement *currentElement = sparseMatrix.firstElement;
for (int i=0; i<sparseMatrix.elements; ++i) {
printf("[%d,%d] = %f\n", currentElement->rowIndex,
currentElement->columnIndex, currentElement->value);
currentElement = currentElement->nextElement;
}
}

29
serial_csr/lil_sparse_matrix.h

@ -0,0 +1,29 @@
#ifndef LIL_SPARSE_MATRIX_H /* Include guard */
#define LIL_SPARSE_MATRIX_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct lilSparseMatrixElement {
double value;
int rowIndex, columnIndex;
struct lilSparseMatrixElement *nextElement;
} LilSparseMatrixElement;
typedef struct lilSparseMatrix {
int elements;
LilSparseMatrixElement *firstElement;
LilSparseMatrixElement *lastElement;
} LilSparseMatrix;
LilSparseMatrix createLilSparseMatrix();
void apendElement(LilSparseMatrix *sparseMatrix, double value, int row,
int column);
void lilSparseMatrixVectorMultiplication(LilSparseMatrix sparseMatrix,
double *vector, double **product, int vectorSize);
void destroyLilSparseMatrix(LilSparseMatrix *sparseMatrix);
void printLilSparseMatrix(LilSparseMatrix sparseMatrix);
#endif // LIL_SPARSE_MATRIX_H

BIN
serial_csr/lil_sparse_matrix.o

Binary file not shown.

BIN
serial_csr/pagerank.out

Binary file not shown.

1
serial_csr/pagerank_output

File diff suppressed because one or more lines are too long

44
serial_csr/serial_gs_pagerank.c

@ -0,0 +1,44 @@
#include <sys/time.h>
#include "serial_gs_pagerank_functions.h"
//#include "coo_sparse_matrix.h"
struct timeval startwtime, endwtime;
double seq_time;
int main(int argc, char **argv) {
CsrSparseMatrix transitionMatrix = initCsrSparseMatrix();
double *pagerankVector;
bool convergenceStatus;
Parameters parameters;
parseArguments(argc, argv, &parameters);
initialize(&transitionMatrix, &pagerankVector, &parameters);
// Starts wall-clock timer
gettimeofday (&startwtime, NULL);
int iterations = pagerank(&transitionMatrix, &pagerankVector,
&convergenceStatus, parameters);
if (parameters.verbose) {
printf(ANSI_COLOR_YELLOW "\n----- RESULTS -----\n" ANSI_COLOR_RESET);
if (convergenceStatus) {
printf(ANSI_COLOR_GREEN "Pagerank converged after %d iterations!\n" \
ANSI_COLOR_RESET, iterations);
} else {
printf(ANSI_COLOR_RED "Pagerank did not converge after max number of" \
" iterations (%d) was reached!\n" ANSI_COLOR_RESET, iterations);
}
}
// Stops wall-clock timer
gettimeofday (&endwtime, NULL);
double seq_time = (double)((endwtime.tv_usec - startwtime.tv_usec)/1.0e6 +
endwtime.tv_sec - startwtime.tv_sec);
printf("%s wall clock time = %f\n","Pagerank (Gauss-Seidel method), serial implementation",
seq_time);
free(pagerankVector);
destroyCsrSparseMatrix(&transitionMatrix);
}

BIN
serial_csr/serial_gs_pagerank.o

Binary file not shown.

525
serial_csr/serial_gs_pagerank_functions.c

@ -0,0 +1,525 @@
/* ===== INCLUDES ===== */
#include "serial_gs_pagerank_functions.h"
/* ===== CONSTANTS ===== */
const char *ARGUMENT_CONVERGENCE_TOLERANCE = "-c";
const char *ARGUMENT_MAX_ITERATIONS = "-m";
const char *ARGUMENT_DAMPING_FACTOR = "-a";
const char *ARGUMENT_VERBAL_OUTPUT = "-v";
const char *ARGUMENT_OUTPUT_HISTORY = "-h";
const char *ARGUMENT_OUTPUT_FILENAME = "-o";
const int NUMERICAL_BASE = 10;
char *DEFAULT_OUTPUT_FILENAME = "pagerank_output";
const int FILE_READ_BUFFER_SIZE = 4096;
const int CONVERGENCE_CHECK_ITERATION_PERIOD = 3;
const int SPARSITY_INCREASE_ITERATION_PERIOD = 9;
/* ===== FUNCTIONS ===== */
int pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
bool *convergenceStatus, Parameters parameters) {
// Variables declaration
int iterations = 0, numberOfPages = parameters.numberOfPages;
double delta, *pagerankDifference, *previousPagerankVector,
*convergedPagerankVector, *linksFromConvergedPagesPagerankVector;
LilSparseMatrix linksFromConvergedPages = createLilSparseMatrix();
bool *convergenceMatrix;
// Space allocation
{
size_t sizeofDouble = sizeof(double);
// pagerankDifference used to calculate delta
pagerankDifference = (double *) malloc(numberOfPages * sizeofDouble);
// previousPagerankVector holds last iteration's pagerank vector
previousPagerankVector = (double *) malloc(numberOfPages * sizeofDouble);
// convergedPagerankVector is the pagerank vector of converged pages only
convergedPagerankVector = (double *) malloc(numberOfPages * sizeofDouble);
// linksFromConvergedPagesPagerankVector holds the partial sum of the
// pagerank vector, that describes effect of the links from converged
// pages to non converged pages
linksFromConvergedPagesPagerankVector = (double *) malloc(numberOfPages * sizeofDouble);
// convergenceMatrix indicates which pages have converged
convergenceMatrix = (bool *) malloc(numberOfPages * sizeof(bool));
*convergenceStatus = false;
// Initialization
for (int i=0; i<numberOfPages; ++i) {
convergedPagerankVector[i] = 0;
convergenceMatrix[i] = false;
linksFromConvergedPagesPagerankVector[i] = 0;
}
}
if (parameters.verbose) {
printf(ANSI_COLOR_YELLOW "\n----- Starting iterations -----\n" ANSI_COLOR_RESET);
}
do {
// Stores previous pagerank vector
memcpy(previousPagerankVector, *pagerankVector, numberOfPages * sizeof(double));
// Calculates new pagerank vector
calculateNextPagerank(transitionMatrix, previousPagerankVector,
pagerankVector, linksFromConvergedPagesPagerankVector,
convergedPagerankVector, numberOfPages,
parameters.dampingFactor);
if (parameters.history) {
// Outputs pagerank vector to file
savePagerankToFile(parameters.outputFilename, iterations != 0,
*pagerankVector, numberOfPages);
}
// Periodically checks for convergence
if (!(iterations % CONVERGENCE_CHECK_ITERATION_PERIOD)) {
// Builds pagerank vectors difference
for (int i=0; i<numberOfPages; ++i) {
pagerankDifference[i] = (*pagerankVector)[i] - previousPagerankVector[i];
}
// Calculates convergence
delta = vectorNorm(pagerankDifference, numberOfPages);
if (delta < parameters.convergenceCriterion) {
// Converged
*convergenceStatus = true;
}
}
// Periodically increases sparsity
if (iterations && !(iterations % SPARSITY_INCREASE_ITERATION_PERIOD)) {
bool *newlyConvergedPages = (bool *) malloc(numberOfPages * sizeof(bool));
// Checks each individual page for convergence
for (int i=0; i<numberOfPages; ++i) {
double difference = fabs((*pagerankVector)[i] -
previousPagerankVector[i]) / fabs(previousPagerankVector[i]);
newlyConvergedPages[i] = false;
if (!convergenceMatrix[i] && difference < parameters.convergenceCriterion){
// Page converged
newlyConvergedPages[i] = true;
convergenceMatrix[i] = true;
convergedPagerankVector[i] = (*pagerankVector)[i];
}
}
for (int i=0; i<numberOfPages; ++i) {
if (newlyConvergedPages[i] == true) {
int rowSize;
int *rowIndexes = getRowIndexes(*transitionMatrix, i, &rowSize);
for (int j=0; j<rowSize; ++j){
/*CooSparseMatrixElement *element = transitionMatrix->elements[rowIndexes[j]];
// Checks for links from converged pages to non converged
int pageLinksTo = element->columnIndex;
if (convergenceMatrix[pageLinksTo] == false){
// Link exists, adds element to the vector
apendElement(&linksFromConvergedPages,
element->value, i, pageLinksTo);
}*/
int pageLinksTo = transitionMatrix->columnIndexes[rowIndexes[j]];
if (convergenceMatrix[pageLinksTo] == false){
// Link exists, adds element to the vector
apendElement(&linksFromConvergedPages,
transitionMatrix->values[rowIndexes[j]], i, pageLinksTo);
}
}
// Increases sparsity of the transition matrix by
// deleting elements that correspond to converged pages
zeroOutRow(transitionMatrix, i);
zeroOutColumn(transitionMatrix, i);
// Builds the new linksFromConvergedPagesPagerankVector
lilSparseMatrixVectorMultiplication(linksFromConvergedPages,
*pagerankVector, &linksFromConvergedPagesPagerankVector,
numberOfPages);
}
}
free(newlyConvergedPages);
}
++iterations;
// Outputs information about this iteration
if (iterations%2) {
printf(ANSI_COLOR_BLUE "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, iterations, delta);
} else {
printf(ANSI_COLOR_CYAN "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, iterations, delta);
}
} while (!*convergenceStatus && (parameters.maxIterations == 0 ||
iterations < parameters.maxIterations));
if (!parameters.history) {
// Outputs last pagerank vector to file
savePagerankToFile(parameters.outputFilename, false, *pagerankVector, numberOfPages);
}
// Frees memory
free(pagerankDifference);
free(previousPagerankVector);
free(convergedPagerankVector);
free(linksFromConvergedPagesPagerankVector);
free(convergenceMatrix);
destroyLilSparseMatrix(&linksFromConvergedPages);
return iterations;
}
/*
* initialize allocates required memory for arrays, reads the web graph from the
* from the file and creates the initial transition probability distribution
* matrix.
*/
void initialize(CsrSparseMatrix *transitionMatrix,
double **pagerankVector, Parameters *parameters) {
// Reads web graph from file
if ((*parameters).verbose) {
printf(ANSI_COLOR_YELLOW "----- Reading graph from file -----\n" ANSI_COLOR_RESET);
}
generateNormalizedTransitionMatrixFromFile(transitionMatrix, parameters);
// Outputs the algorithm parameters to the console
if ((*parameters).verbose) {
printf(ANSI_COLOR_YELLOW "\n----- Running with parameters -----\n" ANSI_COLOR_RESET\
"Number of pages: %d", (*parameters).numberOfPages);
if (!(*parameters).maxIterations) {
printf("\nMaximum number of iterations: inf");
} else {
printf("\nMaximum number of iterations: %d", (*parameters).maxIterations);
}
printf("\nConvergence criterion: %f" \
"\nDamping factor: %f" \
"\nGraph filename: %s\n", (*parameters).convergenceCriterion,
(*parameters).dampingFactor, (*parameters).graphFilename);
}
// Allocates memory for the pagerank vector
(*pagerankVector) = (double *) malloc((*parameters).numberOfPages * sizeof(double));
double webUniformProbability = 1. / (*parameters).numberOfPages;
for (int i=0; i<(*parameters).numberOfPages; ++i) {
(*pagerankVector)[i] = webUniformProbability;
}
// Transposes the transition matrix (P^T).
transposeSparseMatrix(transitionMatrix);
}
// ==================== MATH UTILS ====================
/*
* calculateNextPagerank calculates the product of the multiplication
* between a matrix and the a vector in a cheap way.
*/
void calculateNextPagerank(CsrSparseMatrix *transitionMatrix,
double *previousPagerankVector, double **pagerankVector,
double *linksFromConvergedPagesPagerankVector,
double *convergedPagerankVector, int vectorSize, double dampingFactor) {
// Calculates the web uniform probability once.
double webUniformProbability = 1. / vectorSize;
csrSparseMatrixVectorMultiplication(*transitionMatrix, previousPagerankVector,
pagerankVector, vectorSize);
for (int i=0; i<vectorSize; ++i) {
(*pagerankVector)[i] = dampingFactor * (*pagerankVector)[i];
}
double normDifference = vectorNorm(previousPagerankVector, vectorSize) -
vectorNorm(*pagerankVector, vectorSize);
for (int i=0; i<vectorSize; ++i) {
(*pagerankVector)[i] += normDifference * webUniformProbability +
linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i];
}
}
/*
* vectorNorm calculates the first norm of a vector.
*/
double vectorNorm(double *vector, int vectorSize) {
double norm = 0.;
for (int i=0; i<vectorSize; ++i) {
norm += fabs(vector[i]);
}
return norm;
}
// ==================== PROGRAM INPUT AND OUTPUT UTILS ====================
/*
* parseArguments parses the command line arguments given by the user.
*/
void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters) {
if (argumentCount < 2 || argumentCount > 10) {
validUsage(argumentVector[0]);
}
(*parameters).numberOfPages = 0;
(*parameters).maxIterations = 0;
(*parameters).convergenceCriterion = 1;
(*parameters).dampingFactor = 0.85;
(*parameters).verbose = false;
(*parameters).history = false;
(*parameters).outputFilename = DEFAULT_OUTPUT_FILENAME;
char *endPointer;
int argumentIndex = 1;
while (argumentIndex < argumentCount) {
if (!strcmp(argumentVector[argumentIndex], ARGUMENT_CONVERGENCE_TOLERANCE)) {
argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]);
double convergenceInput = strtod(argumentVector[argumentIndex], &endPointer);
if (convergenceInput == 0) {
printf("Invalid convergence argument\n");
exit(EXIT_FAILURE);
}
(*parameters).convergenceCriterion = convergenceInput;
} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_MAX_ITERATIONS)) {
argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]);
size_t iterationsInput = strtol(argumentVector[argumentIndex], &endPointer, NUMERICAL_BASE);
if (iterationsInput == 0 && endPointer) {
printf("Invalid iterations argument\n");
exit(EXIT_FAILURE);
}
(*parameters).maxIterations = iterationsInput;
} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_DAMPING_FACTOR)) {
argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]);
double alphaInput = strtod(argumentVector[argumentIndex], &endPointer);
if ((alphaInput == 0 || alphaInput > 1) && endPointer) {
printf("Invalid alpha argument\n");
exit(EXIT_FAILURE);
}
(*parameters).dampingFactor = alphaInput;
} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_VERBAL_OUTPUT)) {
(*parameters).verbose = true;
} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_OUTPUT_HISTORY)) {
(*parameters).history = true;
} else if (!strcmp(argumentVector[argumentIndex], ARGUMENT_OUTPUT_FILENAME)) {
argumentIndex = checkIncrement(argumentIndex, argumentCount, argumentVector[0]);
if (fopen(argumentVector[argumentIndex], "w") == NULL) {
printf("Invalid output filename. Reverting to default.\n");
continue;
}
(*parameters).outputFilename = argumentVector[argumentIndex];
} else if (argumentIndex == argumentCount - 1) {
(*parameters).graphFilename = argumentVector[argumentIndex];
} else {
validUsage(argumentVector[0]);
exit(EXIT_FAILURE);
}
++argumentIndex;
}
}
/*
* readGraphFromFile loads the file supplied in the command line arguments to an
* array (directedWebGraph) that represents the graph.
*/
void generateNormalizedTransitionMatrixFromFile(CsrSparseMatrix *transitionMatrix,
Parameters *parameters){
FILE *graphFile;
// Opens the file for reading
graphFile = fopen((*parameters).graphFilename, "r+");
if (!graphFile) {
printf("Error opening file \n");
exit(EXIT_FAILURE);
}
char buffer[FILE_READ_BUFFER_SIZE];
char *readResult;
// Skips the first two lines
readResult = fgets(buffer, FILE_READ_BUFFER_SIZE, graphFile);
readResult = fgets(buffer, FILE_READ_BUFFER_SIZE, graphFile);
if (readResult == NULL) {
printf("Error while reading from the file. Does the file have the correct format?\n");
exit(EXIT_FAILURE);
}
// Third line contains the numbers of nodes and edges
int numberOfNodes = 0, numberOfEdges = 0;
readResult = fgets(buffer, FILE_READ_BUFFER_SIZE, graphFile);
if (readResult == NULL) {
printf("Error while reading from the file. Does the file have the correct format?\n");
exit(EXIT_FAILURE);
}
// Parses the number of nodes and number of edges
{
// Splits string to whitespace
char *token = strtok(buffer, " ");
bool nextIsNodes = false, nextIsEdges = false;
while (token != NULL) {
if (strcmp(token, "Nodes:") == 0) {
nextIsNodes = true;
} else if (nextIsNodes) {
numberOfNodes = atoi(token);
nextIsNodes = false;
} else if (strcmp(token, "Edges:") == 0) {
nextIsEdges = true;
} else if (nextIsEdges) {
numberOfEdges = atoi(token);
break;
}
// Gets next string token
token = strtok (NULL, " ,.-");
}
}
if ((*parameters).verbose) {
printf("File claims number of pages is: %d\nThe number of edges is: %d\n",
numberOfNodes, numberOfEdges);
}
// Skips the fourth line
readResult = fgets(buffer, 512, graphFile);
if (readResult == NULL) {
printf("Error while reading from the file. Does the file have the correct format?\n");
exit(EXIT_FAILURE);
}
int tenPercentIncrements = (int) numberOfEdges/10;
int maxPageIndex = 0;
allocMemoryForElements(transitionMatrix, numberOfEdges);
for (int i=0; i<numberOfEdges; i++) {
if (((*parameters).verbose) && (tenPercentIncrements != 0) && ((i % tenPercentIncrements) == 0)) {
int percentage = (i/tenPercentIncrements)*10;
printf("%d%% • ", percentage);
}
int fileFrom = 0, fileTo = 0;
if (!fscanf(graphFile, "%d %d", &fileFrom, &fileTo)) {
break;
}
if (fileFrom > maxPageIndex) {
maxPageIndex = fileFrom;
}
if (fileTo > maxPageIndex) {
maxPageIndex = fileTo;
}
addElement(transitionMatrix, 1, fileFrom, fileTo);
}
printf("\n");
if ((*parameters).verbose) {
printf("Max page index found is: %d\n", maxPageIndex);
}
(*parameters).numberOfPages = maxPageIndex + 1;
// Calculates the outdegree of each page and assigns the uniform probability
// of transition to the elements of the corresponding row
//int currentRow = transitionMatrix->elements[0]->rowIndex;
int pageOutdegree = 1;
/*for (int i=1; i<transitionMatrix->size; ++i) {
CooSparseMatrixElement *currentElement = transitionMatrix->elements[i];
if (currentElement->rowIndex == currentRow) {
++pageOutdegree;
} else {
double pageUniformProbability = 1. / pageOutdegree;
for (int j=i-pageOutdegree; j<i; ++j) { //gia ola ta rows mexri to twrino apo to twrino-pageOutdegree
transitionMatrix->elements[j]->value = pageUniformProbability;
}
currentRow = currentElement->rowIndex;
pageOutdegree = 1;
}
}*/
for(int i=0; i<transitionMatrix->size; ++i){
if((i==0) && (transitionMatrix->rowaccInd[i]>0)){
pageOutdegree+=transitionMatrix->rowaccInd[i];
}
else if((i!=0)&&(transitionMatrix->rowaccInd[i]-transitionMatrix->rowaccInd[i-1]>0)){
pageOutdegree+=transitionMatrix->rowaccInd[i]-transitionMatrix->rowaccInd[i-1]
}
else{
//no connections from that row
double pageUniformProbability = 1. / pageOutdegree;
for (int j = i-pageOutdegree; j<i ; ++j){ //gia auta ta rows
transitionMatrix->values[transitionMatrix->rowaccInd[j-1]+1] = pageUniformProbability; ///???
}
pageOutdegree = 1;
}
}
// Does the last row
/*double pageUniformProbability = 1. / pageOutdegree;
for (int j=transitionMatrix->size-pageOutdegree; j<transitionMatrix->size; ++j) {
transitionMatrix->elements[j]->value = pageUniformProbability;
}*/
double pageUniformProbability = 1. / pageOutdegree;
for (int j=transitionMatrix->size-pageOutdegree; j<transitionMatrix->size; ++j) {
transitionMatrix->values[transitionMatrix->rowaccInd[j-1]+1] = pageUniformProbability;
}
fclose(graphFile);
}
/*
* validUsage outputs a message to the console that informs the user of the
* correct (valid) way to use the program.
*/
void validUsage(char *programName) {
printf("%s [-c convergence_criterion] [-m max_iterations] [-a alpha] [-v] [-h] [-o output_filename] <graph_file>" \
"\n-c convergence_criterion" \
"\n\tthe convergence tolerance criterion" \
"\n-m max_iterations" \
"\n\tmaximum number of iterations to perform" \
"\n-a alpha" \
"\n\tthe damping factor" \
"\n-v enable verbal output" \
"\n-h enable history output to file" \
"\n-o output_filename" \
"\n\tfilename and path for the output" \
"\n", programName);
exit(EXIT_FAILURE);
}
/*
* checkIncrement is a helper function for parseArguments function.
*/
int checkIncrement(int previousIndex, int maxIndex, char *programName) {
if (previousIndex == maxIndex) {
validUsage(programName);
exit(EXIT_FAILURE);
}
return ++previousIndex;
}
void savePagerankToFile(char *filename, bool append, double *pagerankVector, int vectorSize) {
FILE *outputFile;
if (append) {
outputFile = fopen(filename, "a");
} else {
outputFile = fopen(filename, "w");
}
if (outputFile == NULL) {
printf("Error while opening the output file.\n");
return;
}
for (int i=0; i<vectorSize; ++i) {
fprintf(outputFile, "%f ", pagerankVector[i]);
}
fprintf(outputFile, "\n");
fclose(outputFile);
}

99
serial_csr/serial_gs_pagerank_functions.h

@ -0,0 +1,99 @@
#ifndef SERIAL_GS_PAGERANK_FUNCTIONS_H /* Include guard */
#define SERIAL_GS_PAGERANK_FUNCTIONS_H
/* ===== INCLUDES ===== */
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
#include "csr_sparse_matrix.h"
#include "lil_sparse_matrix.h"
/* ===== DEFINITIONS ===== */
//Colors used for better console output formating.
#define ANSI_COLOR_RED "\x1B[31m"
#define ANSI_COLOR_GREEN "\x1B[32m"
#define ANSI_COLOR_YELLOW "\x1B[33m"
#define ANSI_COLOR_BLUE "\x1B[34m"
#define ANSI_COLOR_CYAN "\x1B[36m"
#define ANSI_COLOR_RESET "\x1B[0m"
/* ===== CONSTANTS DEFINITION ===== */
// Constant strings that store the command line options available.
extern const char *ARGUMENT_CONVERGENCE_TOLERANCE;
extern const char *ARGUMENT_MAX_ITERATIONS;
extern const char *ARGUMENT_DAMPING_FACTOR;
extern const char *ARGUMENT_VERBAL_OUTPUT;
extern const char *ARGUMENT_OUTPUT_HISTORY;
extern const char *ARGUMENT_OUTPUT_FILENAME;
// The numerical base used when parsing numerical command line arguments.
extern const int NUMERICAL_BASE;
// Default filename used for the output.
extern char *DEFAULT_OUTPUT_FILENAME;
// The size of the buffer used for reading the graph input file.
extern const int FILE_READ_BUFFER_SIZE;
/* ===== STRUCTURES ===== */
// A data structure to conveniently hold the algorithm's parameters.
typedef struct parameters {
int numberOfPages, maxIterations;
double convergenceCriterion, dampingFactor;
bool verbose, history;
char *outputFilename, *graphFilename;
} Parameters;
/* ===== FUNCTION DEFINITIONS ===== */
// Function validUsage outputs the correct way to use the program with command
// line arguments.
void validUsage(char *programName);
// Function checkIncrement is a helper function used in parseArguments (see
// bellow).
int checkIncrement(int previousIndex, int maxIndex, char *programName);
// Function parseArguments parses command line arguments.
void parseArguments(int argumentCount, char **argumentVector,
Parameters *parameters);
// Function generateNormalizedTransitionMatrixFromFile reads through the entries
// of the file specified in the arguments (parameters->graphFilename), using
// them to populate the sparse array (transitionMatrix). The entries of the file
// represent the edges of the web transition graph. The entries are then
// modified to become the rows of the transition matrix.
void generateNormalizedTransitionMatrixFromFile(CsrSparseMatrix *transitionMatrix,
Parameters *parameters);
// Function savePagerankToFile appends or overwrites the pagerank vector
// "pagerankVector" to the file with the filename supplied in the arguments.
void savePagerankToFile(char *filename, bool append, double *pagerankVector,
int vectorSize);
// Function initialize allocates memory for the pagerank vector, reads the
// dataset from the file and creates the transition probability distribution
// matrix.
void initialize(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
Parameters *parameters);
// Function vectorNorm calculates the first norm of a vector.
double vectorNorm(double *vector, int vectorSize);
// Function calculateNextPagerank calculates the next pagerank vector.
void calculateNextPagerank(CsrSparseMatrix *transitionMatrix,
double *previousPagerankVector, double **pagerankVector,
double *linksFromConvergedPagesPagerankVector,
double *convergedPagerankVector, int vectorSize, double dampingFactor);
// Function pagerank iteratively calculates the pagerank of each page until
// either the convergence criterion is met or the maximum number of iterations
// is reached.
int pagerank(CsrSparseMatrix *transitionMatrix, double **pagerankVector,
bool *convergenceStatus, Parameters parameters);
#endif // SERIAL_GS_PAGERANK_FUNCTIONS_H

BIN
serial_csr/serial_gs_pagerank_functions.o

Binary file not shown.
Loading…
Cancel
Save