Browse Source

Change transition sparse matrix to coordinates wise representation, Add comments, Improve code readability

master
Apostolos Fanakis 6 years ago
parent
commit
eb15bbac5b
No known key found for this signature in database GPG Key ID: 56CE2DEDE9F1FB78
  1. 8
      serial/Makefile
  2. 117
      serial/coo_sparse_matrix.c
  3. 31
      serial/coo_sparse_matrix.h
  4. 76
      serial/lil_sparse_matrix.c
  5. 29
      serial/lil_sparse_matrix.h
  6. 9
      serial/serial_gs_pagerank.c
  7. 229
      serial/serial_gs_pagerank_functions.c
  8. 67
      serial/serial_gs_pagerank_functions.h
  9. 130
      serial/sparse_matrix.c
  10. 30
      serial/sparse_matrix.h

8
serial/Makefile

@ -5,10 +5,10 @@ SHELL := /bin/bash
CC = gcc CC = gcc
RM = rm -f RM = rm -f
CFLAGS_DEBUG=-O0 -g -I. CFLAGS_DEBUG=-O0 -ggdb3 -Wall -I.
CFLAGS=-O3 -I. CFLAGS=-O3 -Wall -I.
OBJ=serial_gs_pagerank.o serial_gs_pagerank_functions.o sparse_matrix.o OBJ=serial_gs_pagerank.o serial_gs_pagerank_functions.o coo_sparse_matrix.o lil_sparse_matrix.o
DEPS=serial_gs_pagerank_functions.h sparse_matrix.h DEPS=serial_gs_pagerank_functions.h coo_sparse_matrix.h lil_sparse_matrix.h
# ========================================== # ==========================================
# TARGETS # TARGETS

117
serial/coo_sparse_matrix.c

@ -0,0 +1,117 @@
#include "coo_sparse_matrix.h"
CooSparseMatrix initCooSparseMatrix() {
CooSparseMatrix sparseMatrix;
sparseMatrix.size = 0;
sparseMatrix.elements = NULL;
return sparseMatrix;
}
void allocMemoryForElements (CooSparseMatrix *sparseMatrix, int elements) {
sparseMatrix->elements = (CooSparseMatrixElement **) malloc(
elements * sizeof(CooSparseMatrixElement *));
}
void addElement(CooSparseMatrix *sparseMatrix, double value, int row, int column) {
// Creates the new element
CooSparseMatrixElement *newElement = (CooSparseMatrixElement *) malloc(
sizeof(CooSparseMatrixElement));
newElement->value = value;
newElement->rowIndex = row;
newElement->columnIndex = column;
sparseMatrix->elements[sparseMatrix->size] = newElement;
sparseMatrix->size = sparseMatrix->size + 1;
}
void zeroOutRow(CooSparseMatrix *sparseMatrix, int row) {
for (int i=0; i<sparseMatrix->size; ++i) {
CooSparseMatrixElement *element = sparseMatrix->elements[i];
if (element->rowIndex == row) {
element->value = 0;
}
}
}
void zeroOutColumn(CooSparseMatrix *sparseMatrix, int column) {
for (int i=0; i<sparseMatrix->size; ++i) {
CooSparseMatrixElement *element = sparseMatrix->elements[i];
if (element->columnIndex == column) {
element->value = 0;
}
}
}
int *getRowIndexes(CooSparseMatrix 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;
}
int *indexes = (int *) malloc((*rowSize) * sizeof(int));
int rowElementIndex = 0;
for (int i=0; i<sparseMatrix.size; ++i) {
if (sparseMatrix.elements[i]->rowIndex == row) {
indexes[rowElementIndex] = i;
++rowElementIndex;
}
}
return indexes;
}
void transposeSparseMatrix(CooSparseMatrix *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;
}
}
void cooSparseMatrixVectorMultiplication(CooSparseMatrix 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];
}
}
void destroyCooSparseMatrix(CooSparseMatrix *sparseMatrix) {
for (int i=0; i<sparseMatrix->size; ++i) {
free(sparseMatrix->elements[i]);
}
free(sparseMatrix->elements);
}
void printCooSparseMatrix(CooSparseMatrix 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);
}
}

31
serial/coo_sparse_matrix.h

@ -0,0 +1,31 @@
#ifndef COO_SPARSE_MATRIX_H /* Include guard */
#define COO_SPARSE_MATRIX_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct cooSparseMatrixElement {
double value;
int rowIndex, columnIndex;
} CooSparseMatrixElement;
typedef struct cooSparseMatrix {
int size;
CooSparseMatrixElement **elements;
} CooSparseMatrix;
CooSparseMatrix initCooSparseMatrix();
void allocMemoryForElements (CooSparseMatrix *sparseMatrix, int elements);
void addElement(CooSparseMatrix *sparseMatrix, double value, int row, int column);
void zeroOutRow(CooSparseMatrix *sparseMatrix, int row);
void zeroOutColumn(CooSparseMatrix *sparseMatrix, int column);
int *getRowIndexes(CooSparseMatrix sparseMatrix, int row, int *rowSize);
void transposeSparseMatrix(CooSparseMatrix *sparseMatrix);
void cooSparseMatrixVectorMultiplication(CooSparseMatrix sparseMatrix, double *vector,
double **product, int vectorSize);
void destroyCooSparseMatrix(CooSparseMatrix *sparseMatrix);
void printCooSparseMatrix(CooSparseMatrix sparseMatrix);
#endif // COO_SPARSE_MATRIX_H

76
serial/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/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

9
serial/serial_gs_pagerank.c

@ -1,19 +1,17 @@
#include <sys/time.h> #include <sys/time.h>
#include "serial_gs_pagerank_functions.h" #include "serial_gs_pagerank_functions.h"
#include "sparse_matrix.h" //#include "coo_sparse_matrix.h"
struct timeval startwtime, endwtime; struct timeval startwtime, endwtime;
double seq_time; double seq_time;
int main(int argc, char **argv) { int main(int argc, char **argv) {
SparseMatrix transitionMatrix; CooSparseMatrix transitionMatrix = initCooSparseMatrix();
double *pagerankVector; double *pagerankVector;
bool convergenceStatus; bool convergenceStatus;
Parameters parameters; Parameters parameters;
transitionMatrix = createSparseMatrix();
parseArguments(argc, argv, &parameters); parseArguments(argc, argv, &parameters);
initialize(&transitionMatrix, &pagerankVector, &parameters); initialize(&transitionMatrix, &pagerankVector, &parameters);
@ -40,4 +38,7 @@ int main(int argc, char **argv) {
endwtime.tv_sec - startwtime.tv_sec); endwtime.tv_sec - startwtime.tv_sec);
printf("%s wall clock time = %f\n","Pagerank (Gauss-Seidel method), serial implementation", printf("%s wall clock time = %f\n","Pagerank (Gauss-Seidel method), serial implementation",
seq_time); seq_time);
free(pagerankVector);
destroyCooSparseMatrix(&transitionMatrix);
} }

229
serial/serial_gs_pagerank_functions.c

@ -1,5 +1,9 @@
/* ===== INCLUDES ===== */
#include "serial_gs_pagerank_functions.h" #include "serial_gs_pagerank_functions.h"
/* ===== CONSTANTS ===== */
const char *ARGUMENT_CONVERGENCE_TOLERANCE = "-c"; const char *ARGUMENT_CONVERGENCE_TOLERANCE = "-c";
const char *ARGUMENT_MAX_ITERATIONS = "-m"; const char *ARGUMENT_MAX_ITERATIONS = "-m";
const char *ARGUMENT_DAMPING_FACTOR = "-a"; const char *ARGUMENT_DAMPING_FACTOR = "-a";
@ -11,106 +15,159 @@ const int NUMERICAL_BASE = 10;
char *DEFAULT_OUTPUT_FILENAME = "pagerank_output"; char *DEFAULT_OUTPUT_FILENAME = "pagerank_output";
const int FILE_READ_BUFFER_SIZE = 4096; const int FILE_READ_BUFFER_SIZE = 4096;
// ==================== PAGERANK ==================== const int CONVERGENCE_CHECK_ITERATION_PERIOD = 3;
const int SPARSITY_INCREASE_ITERATION_PERIOD = 9;
int pagerank(SparseMatrix *transitionMatrix, double **pagerankVector, /* ===== FUNCTIONS ===== */
int pagerank(CooSparseMatrix *transitionMatrix, double **pagerankVector,
bool *convergenceStatus, Parameters parameters) { bool *convergenceStatus, Parameters parameters) {
int iterations = 0; // Variables declaration
double delta, int iterations = 0, numberOfPages = parameters.numberOfPages;
*vectorDifference = (double *) malloc(parameters.numberOfPages * sizeof(double)), double delta, *pagerankDifference, *previousPagerankVector,
*previousPagerankVector = (double *) malloc(parameters.numberOfPages * sizeof(double)), *convergedPagerankVector, *linksFromConvergedPagesPagerankVector;
*convergedPagerankVector = (double *) malloc(parameters.numberOfPages * sizeof(double)), LilSparseMatrix linksFromConvergedPages = createLilSparseMatrix();
*linksFromConvergedPagesPagerankVector = (double *) malloc(parameters.numberOfPages * sizeof(double)); bool *convergenceMatrix;
SparseMatrix linksFromConvergedPages = createSparseMatrix();
bool *converganceMatrix = (bool *) malloc(parameters.numberOfPages * sizeof(bool)); // 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; *convergenceStatus = false;
for (int i=0; i<parameters.numberOfPages; ++i) { // Initialization
for (int i=0; i<numberOfPages; ++i) {
convergedPagerankVector[i] = 0; convergedPagerankVector[i] = 0;
converganceMatrix[i] = false; convergenceMatrix[i] = false;
linksFromConvergedPagesPagerankVector[i] = 0; linksFromConvergedPagesPagerankVector[i] = 0;
} }
}
if (parameters.verbose) { if (parameters.verbose) {
printf(ANSI_COLOR_YELLOW "\n----- Starting iterations -----\n" ANSI_COLOR_RESET); printf(ANSI_COLOR_YELLOW "\n----- Starting iterations -----\n" ANSI_COLOR_RESET);
} }
do { do {
memcpy(previousPagerankVector, *pagerankVector, parameters.numberOfPages * sizeof(double)); // Stores previous pagerank vector
memcpy(previousPagerankVector, *pagerankVector, numberOfPages * sizeof(double));
matrixVectorMultiplication(transitionMatrix, previousPagerankVector,
pagerankVector, parameters.numberOfPages, parameters.dampingFactor);
for (int i=0; i<parameters.numberOfPages; ++i) { // Calculates new pagerank vector
(*pagerankVector)[i] += linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i]; calculateNextPagerank(transitionMatrix, previousPagerankVector,
} pagerankVector, linksFromConvergedPagesPagerankVector,
convergedPagerankVector, numberOfPages,
parameters.dampingFactor);
if (parameters.history) { if (parameters.history) {
// Outputs pagerank vector to file
savePagerankToFile(parameters.outputFilename, iterations != 0, savePagerankToFile(parameters.outputFilename, iterations != 0,
*pagerankVector, parameters.numberOfPages); *pagerankVector, numberOfPages);
} }
for (int i=0; i<parameters.numberOfPages; ++i) { // Periodically checks for convergence
vectorDifference[i] = (*pagerankVector)[i] - previousPagerankVector[i]; if (!(iterations % CONVERGENCE_CHECK_ITERATION_PERIOD)) {
// Builds pagerank vectors difference
for (int i=0; i<numberOfPages; ++i) {
pagerankDifference[i] = (*pagerankVector)[i] - previousPagerankVector[i];
} }
delta = vectorNorm(vectorDifference, parameters.numberOfPages); // Calculates convergence
delta = vectorNorm(pagerankDifference, numberOfPages);
if (delta < parameters.convergenceCriterion) { if (delta < parameters.convergenceCriterion) {
// Converged
*convergenceStatus = true; *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]);
if (iterations && (!iterations % 10)) { newlyConvergedPages[i] = false;
for (int i=0; i<parameters.numberOfPages; ++i) { if (!convergenceMatrix[i] && difference < parameters.convergenceCriterion){
double temp = fabs((*pagerankVector)[i] - previousPagerankVector[i]) / fabs(previousPagerankVector[i]); // Page converged
if (temp < parameters.convergenceCriterion){ newlyConvergedPages[i] = true;
converganceMatrix[i] = true; convergenceMatrix[i] = true;
convergedPagerankVector[i] = (*pagerankVector)[i]; convergedPagerankVector[i] = (*pagerankVector)[i];
} }
} }
for (int i=0; i<parameters.numberOfPages; ++i) { for (int i=0; i<numberOfPages; ++i) {
if (converganceMatrix[i] == true) { if (newlyConvergedPages[i] == true) {
for (int j=0; j<parameters.numberOfPages; ++j){ int rowSize;
if (converganceMatrix[j] == false){ int *rowIndexes = getRowIndexes(*transitionMatrix, i, &rowSize);
SparseMatrixElement *element = getElement(*transitionMatrix, i, j); for (int j=0; j<rowSize; ++j){
if (element != NULL) { CooSparseMatrixElement *element = transitionMatrix->elements[rowIndexes[j]];
apendElement(&linksFromConvergedPages, element->value, i, 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);
} }
} }
deleteElement(transitionMatrix, i, j);
deleteElement(transitionMatrix, j, i);
}
sparseMatrixVectorMultiplication(linksFromConvergedPages, *pagerankVector, // Increases sparsity of the transition matrix by
&linksFromConvergedPagesPagerankVector, parameters.numberOfPages); // 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; ++iterations;
// Outputs information about this iteration
if (iterations%2) { if (iterations%2) {
printf(ANSI_COLOR_BLUE "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, iterations, delta); printf(ANSI_COLOR_BLUE "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, iterations, delta);
} else { } else {
printf(ANSI_COLOR_CYAN "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, iterations, delta); printf(ANSI_COLOR_CYAN "Iteration %d: delta = %f\n" ANSI_COLOR_RESET, iterations, delta);
} }
} while (!*convergenceStatus && } while (!*convergenceStatus && (parameters.maxIterations == 0 ||
(parameters.maxIterations == 0 || iterations < parameters.maxIterations)); iterations < parameters.maxIterations));
if (!parameters.history) { if (!parameters.history) {
// Outputs last pagerank vector to file
savePagerankToFile(parameters.outputFilename, false, *pagerankVector, savePagerankToFile(parameters.outputFilename, false, *pagerankVector,
parameters.numberOfPages); numberOfPages);
} }
// Frees memory
free(pagerankDifference);
free(previousPagerankVector);
free(convergedPagerankVector);
free(linksFromConvergedPagesPagerankVector);
free(convergenceMatrix);
destroyLilSparseMatrix(&linksFromConvergedPages);
return iterations; return iterations;
} }
// ==================== INITIALIZATION ====================
/* /*
* initialize allocates required memory for arrays, reads the web graph from the * initialize allocates required memory for arrays, reads the web graph from the
* from the file and creates the initial transition probability distribution * from the file and creates the initial transition probability distribution
* matrix. * matrix.
*/ */
void initialize(SparseMatrix *transitionMatrix, void initialize(CooSparseMatrix *transitionMatrix,
double **pagerankVector, Parameters *parameters) { double **pagerankVector, Parameters *parameters) {
// Reads web graph from file // Reads web graph from file
@ -148,14 +205,17 @@ void initialize(SparseMatrix *transitionMatrix,
// ==================== MATH UTILS ==================== // ==================== MATH UTILS ====================
/* /*
* matrixVectorMultiplication calculates the product of the multiplication * calculateNextPagerank calculates the product of the multiplication
* between a matrix and the a vector in a cheap way. * between a matrix and the a vector in a cheap way.
*/ */
void matrixVectorMultiplication(SparseMatrix *transitionMatrix, double *previousPagerankVector, void calculateNextPagerank(CooSparseMatrix *transitionMatrix,
double **pagerankVector, int vectorSize, double dampingFactor) { double *previousPagerankVector, double **pagerankVector,
double *linksFromConvergedPagesPagerankVector,
double *convergedPagerankVector, int vectorSize, double dampingFactor) {
// Calculates the web uniform probability once.
double webUniformProbability = 1. / vectorSize; double webUniformProbability = 1. / vectorSize;
sparseMatrixVectorMultiplication(*transitionMatrix, previousPagerankVector, cooSparseMatrixVectorMultiplication(*transitionMatrix, previousPagerankVector,
pagerankVector, vectorSize); pagerankVector, vectorSize);
for (int i=0; i<vectorSize; ++i) { for (int i=0; i<vectorSize; ++i) {
@ -166,7 +226,8 @@ void matrixVectorMultiplication(SparseMatrix *transitionMatrix, double *previous
vectorNorm(*pagerankVector, vectorSize); vectorNorm(*pagerankVector, vectorSize);
for (int i=0; i<vectorSize; ++i) { for (int i=0; i<vectorSize; ++i) {
(*pagerankVector)[i] += normDifference * webUniformProbability; (*pagerankVector)[i] += normDifference * webUniformProbability +
linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i];
} }
} }
@ -258,7 +319,7 @@ void parseArguments(int argumentCount, char **argumentVector, Parameters *parame
* readGraphFromFile loads the file supplied in the command line arguments to an * readGraphFromFile loads the file supplied in the command line arguments to an
* array (directedWebGraph) that represents the graph. * array (directedWebGraph) that represents the graph.
*/ */
void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix, void generateNormalizedTransitionMatrixFromFile(CooSparseMatrix *transitionMatrix,
Parameters *parameters){ Parameters *parameters){
FILE *graphFile; FILE *graphFile;
@ -280,7 +341,7 @@ void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix,
} }
// Third line contains the numbers of nodes and edges // Third line contains the numbers of nodes and edges
int numberOfNodes = 0, numberOfEdges; int numberOfNodes = 0, numberOfEdges = 0;
readResult = fgets(buffer, FILE_READ_BUFFER_SIZE, graphFile); readResult = fgets(buffer, FILE_READ_BUFFER_SIZE, graphFile);
if (readResult == NULL) { if (readResult == NULL) {
@ -324,21 +385,14 @@ void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix,
exit(EXIT_FAILURE); exit(EXIT_FAILURE);
} }
printf("SIZE OF STRUCT = %lu Bytes\n", sizeof(SparseMatrixElement)); int tenPercentIncrements = (int) numberOfEdges/10;
int fivePercentIncrements = (int) numberOfEdges/20;
int maxPageIndex = 0; int maxPageIndex = 0;
fivePercentIncrements = fivePercentIncrements != 0 ? fivePercentIncrements : 1; allocMemoryForElements(transitionMatrix, numberOfEdges);
for (int i=0; i<numberOfEdges; i++) { for (int i=0; i<numberOfEdges; i++) {
if (((*parameters).verbose) && ((i % fivePercentIncrements) == 0)) { if (((*parameters).verbose) && (tenPercentIncrements != 0) && ((i % tenPercentIncrements) == 0)) {
int percentage = (i/fivePercentIncrements)*5; int percentage = (i/tenPercentIncrements)*10;
printf("%d%% done", percentage); printf("%d%% • ", percentage);
if (percentage%20 == 0) {
printf("\n");
} else {
printf(" •••• ");
}
} }
int fileFrom = 0, fileTo = 0; int fileFrom = 0, fileTo = 0;
@ -349,8 +403,12 @@ void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix,
if (fileFrom > maxPageIndex) { if (fileFrom > maxPageIndex) {
maxPageIndex = fileFrom; maxPageIndex = fileFrom;
} }
apendElement(transitionMatrix, 1, fileFrom, fileTo); if (fileTo > maxPageIndex) {
maxPageIndex = fileTo;
} }
addElement(transitionMatrix, 1, fileFrom, fileTo);
}
printf("\n");
if ((*parameters).verbose) { if ((*parameters).verbose) {
printf("Max page index found is: %d\n", maxPageIndex); printf("Max page index found is: %d\n", maxPageIndex);
@ -359,41 +417,26 @@ void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix,
// Calculates the outdegree of each page and assigns the uniform probability // Calculates the outdegree of each page and assigns the uniform probability
// of transition to the elements of the corresponding row // of transition to the elements of the corresponding row
int currentRow = transitionMatrix->firstElement->rowIndex; int currentRow = transitionMatrix->elements[0]->rowIndex, pageOutdegree = 1;
SparseMatrixElement *startElement = transitionMatrix->firstElement; for (int i=1; i<transitionMatrix->size; ++i) {
while(true) { CooSparseMatrixElement *currentElement = transitionMatrix->elements[i];
int pageOutdegree = 1;
SparseMatrixElement *currentElement = startElement->nextElement;
// Calculates current page's outdegree
while (currentElement != NULL) {
if (currentElement->rowIndex == currentRow) { if (currentElement->rowIndex == currentRow) {
++pageOutdegree; ++pageOutdegree;
currentElement = currentElement->nextElement;
} else { } else {
break;
}
}
// Assigns the value 1/outdegree to current page's columns
currentElement = startElement;
double pageUniformProbability = 1. / pageOutdegree; double pageUniformProbability = 1. / pageOutdegree;
for (int i=0; i<pageOutdegree; ++i) { for (int j=i-pageOutdegree; j<i; ++j) {
if (currentElement->rowIndex == currentRow) { transitionMatrix->elements[j]->value = pageUniformProbability;
currentElement->value = pageUniformProbability;
currentElement = currentElement->nextElement;
} else {
break;
}
} }
// Reached the last element; currentRow = currentElement->rowIndex;
if (currentElement == NULL) { pageOutdegree = 1;
break; }
} }
startElement = currentElement; // Does the last row
currentRow = startElement->rowIndex; double pageUniformProbability = 1. / pageOutdegree;
for (int j=transitionMatrix->size-pageOutdegree; j<transitionMatrix->size; ++j) {
transitionMatrix->elements[j]->value = pageUniformProbability;
} }
fclose(graphFile); fclose(graphFile);

67
serial/serial_gs_pagerank_functions.h

@ -1,14 +1,20 @@
#ifndef SERIAL_GS_PAGERANK_FUNCTIONS_H /* Include guard */ #ifndef SERIAL_GS_PAGERANK_FUNCTIONS_H /* Include guard */
#define SERIAL_GS_PAGERANK_FUNCTIONS_H #define SERIAL_GS_PAGERANK_FUNCTIONS_H
/* ===== INCLUDES ===== */
#include <stdbool.h> #include <stdbool.h>
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <math.h> #include <math.h>
#include "sparse_matrix.h" #include "coo_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_RED "\x1B[31m"
#define ANSI_COLOR_GREEN "\x1B[32m" #define ANSI_COLOR_GREEN "\x1B[32m"
#define ANSI_COLOR_YELLOW "\x1B[33m" #define ANSI_COLOR_YELLOW "\x1B[33m"
@ -16,25 +22,25 @@
#define ANSI_COLOR_CYAN "\x1B[36m" #define ANSI_COLOR_CYAN "\x1B[36m"
#define ANSI_COLOR_RESET "\x1B[0m" #define ANSI_COLOR_RESET "\x1B[0m"
/* /* ===== CONSTANTS DEFINITION ===== */
* Constant strings that store the command line options available.
*/ // Constant strings that store the command line options available.
extern const char *ARGUMENT_CONVERGENCE_TOLERANCE; extern const char *ARGUMENT_CONVERGENCE_TOLERANCE;
extern const char *ARGUMENT_MAX_ITERATIONS; extern const char *ARGUMENT_MAX_ITERATIONS;
extern const char *ARGUMENT_DAMPING_FACTOR; extern const char *ARGUMENT_DAMPING_FACTOR;
extern const char *ARGUMENT_VERBAL_OUTPUT; extern const char *ARGUMENT_VERBAL_OUTPUT;
extern const char *ARGUMENT_OUTPUT_HISTORY; extern const char *ARGUMENT_OUTPUT_HISTORY;
extern const char *ARGUMENT_OUTPUT_FILENAME; extern const char *ARGUMENT_OUTPUT_FILENAME;
// The numerical base used when parsing numerical command line arguments.
// This is the numerical base used when parsing the numerical command line
// arguments.
extern const int NUMERICAL_BASE; extern const int NUMERICAL_BASE;
// Default filename used for the output. // Default filename used for the output.
extern char *DEFAULT_OUTPUT_FILENAME; extern char *DEFAULT_OUTPUT_FILENAME;
// The size of the buffer used for reading the graph input file.
extern const int FILE_READ_BUFFER_SIZE;
extern const int MAX_PAGE_LINKS_TEXT_SIZE; /* ===== STRUCTURES ===== */
// Declares a data structure to conveniently hold the algorithm's parameters. // A data structure to conveniently hold the algorithm's parameters.
typedef struct parameters { typedef struct parameters {
int numberOfPages, maxIterations; int numberOfPages, maxIterations;
double convergenceCriterion, dampingFactor; double convergenceCriterion, dampingFactor;
@ -42,8 +48,7 @@ typedef struct parameters {
char *outputFilename, *graphFilename; char *outputFilename, *graphFilename;
} Parameters; } Parameters;
//extern typedef SparseMatrixElement; /* ===== FUNCTION DEFINITIONS ===== */
//extern typedef SparseMatrix;
// Function validUsage outputs the correct way to use the program with command // Function validUsage outputs the correct way to use the program with command
// line arguments. // line arguments.
@ -54,39 +59,41 @@ void validUsage(char *programName);
int checkIncrement(int previousIndex, int maxIndex, char *programName); int checkIncrement(int previousIndex, int maxIndex, char *programName);
// Function parseArguments parses command line arguments. // Function parseArguments parses command line arguments.
void parseArguments(int argumentCount, char **argumentVector, Parameters *parameters); void parseArguments(int argumentCount, char **argumentVector,
Parameters *parameters);
// Function readGraphFromFile loads adjacency matrix, that represents the web // Function generateNormalizedTransitionMatrixFromFile reads through the entries
// graph, stored in the file provided in the command line arguments to the array // of the file specified in the arguments (parameters->graphFilename), using
// directedWebGraph. // them to populate the sparse array (transitionMatrix). The entries of the file
void generateNormalizedTransitionMatrixFromFile(SparseMatrix *transitionMatrix, Parameters *parameters); // represent the edges of the web transition graph. The entries are then
// modified to become the rows of the transition matrix.
void generateNormalizedTransitionMatrixFromFile(CooSparseMatrix *transitionMatrix,
Parameters *parameters);
// Function savePagerankToFile appends or overwrites the pagerank vector // Function savePagerankToFile appends or overwrites the pagerank vector
// "pagerankVector" to the file with the filename supplied in the arguments // "pagerankVector" to the file with the filename supplied in the arguments.
void savePagerankToFile(char *filename, bool append, double *pagerankVector, void savePagerankToFile(char *filename, bool append, double *pagerankVector,
int vectorSize); int vectorSize);
// Function initialize allocates required memory for arrays, reads the dataset // Function initialize allocates memory for the pagerank vector, reads the
// from the file and creates the transition probability distribution matrix. // dataset from the file and creates the transition probability distribution
void initialize( // matrix.
SparseMatrix *transitionMatrix, /*This is matrix A (transition probability distribution matrix)*/ void initialize(CooSparseMatrix *transitionMatrix, double **pagerankVector,
double **pagerankVector, /*This is the resulting pagerank vector*/ Parameters *parameters);
Parameters *parameters
);
// Function vectorNorm calculates the first norm of a vector. // Function vectorNorm calculates the first norm of a vector.
double vectorNorm(double *vector, int vectorSize); double vectorNorm(double *vector, int vectorSize);
// Function matrixVectorMultiplication calculates the product of the // Function calculateNextPagerank calculates the next pagerank vector.
// multiplication between a matrix and the a vector. void calculateNextPagerank(CooSparseMatrix *transitionMatrix,
void matrixVectorMultiplication(SparseMatrix *transitionMatrix, double *previousPagerankVector, double **pagerankVector,
double *previousPagerankVector, double **pagerankVector, int vectorSize, double *linksFromConvergedPagesPagerankVector,
double dampingFactor); double *convergedPagerankVector, int vectorSize, double dampingFactor);
// Function pagerank iteratively calculates the pagerank of each page until // Function pagerank iteratively calculates the pagerank of each page until
// either the convergence criterion is met or the maximum number of iterations // either the convergence criterion is met or the maximum number of iterations
// is reached. // is reached.
int pagerank(SparseMatrix *transitionMatrix, double **pagerankVector, int pagerank(CooSparseMatrix *transitionMatrix, double **pagerankVector,
bool *convergenceStatus, Parameters parameters); bool *convergenceStatus, Parameters parameters);
#endif // SERIAL_GS_PAGERANK_FUNCTIONS_H #endif // SERIAL_GS_PAGERANK_FUNCTIONS_H

130
serial/sparse_matrix.c

@ -1,130 +0,0 @@
#include "sparse_matrix.h"
SparseMatrix createSparseMatrix() {
SparseMatrix sparseMatrix;
sparseMatrix.elements = 0;
sparseMatrix.firstElement = NULL;
sparseMatrix.lastElement = NULL;
return sparseMatrix;
}
void apendElement(SparseMatrix *sparseMatrix, double value, int row, int column) {
// Creates the new element
SparseMatrixElement *newElement = (SparseMatrixElement *) malloc(sizeof(SparseMatrixElement));
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
SparseMatrixElement *lastElement = sparseMatrix->lastElement;
lastElement->nextElement = newElement;
sparseMatrix->lastElement = newElement;
}
sparseMatrix->elements = sparseMatrix->elements + 1;
}
bool deleteElement(SparseMatrix *sparseMatrix, int row, int column) {
if (sparseMatrix->elements == 0) {
// Matrix is empty, nothing can be deleted
return false;
} else if (sparseMatrix->elements == 1) {
// Matrix has one element. Deletes it.
free(sparseMatrix->firstElement);
sparseMatrix->firstElement = NULL;
sparseMatrix->lastElement = NULL;
sparseMatrix->elements = sparseMatrix->elements - 1;
return true;
}
SparseMatrixElement *currentElement = sparseMatrix->firstElement;
if (currentElement->rowIndex == row && currentElement->columnIndex == column) {
sparseMatrix->firstElement = currentElement->nextElement;
free(currentElement);
sparseMatrix->elements = sparseMatrix->elements - 1;
return true;
}
// Matrix has multiple elements. Finds the first element that has the coordinates
// (row,column) and deletes it.
for (int i=0; i<sparseMatrix->elements - 1; ++i) {
SparseMatrixElement *nextElement = currentElement->nextElement;
if (nextElement->rowIndex == row && nextElement->columnIndex == column) {
currentElement->nextElement = nextElement->nextElement;
if (currentElement->nextElement == NULL) {
sparseMatrix->lastElement = currentElement;
}
free(nextElement);
sparseMatrix->elements = sparseMatrix->elements - 1;
return true;
} else {
currentElement = currentElement->nextElement;
}
}
}
SparseMatrixElement *getElement(SparseMatrix sparseMatrix, int row, int column) {
SparseMatrixElement *currentElement = sparseMatrix.firstElement;
do {
if (currentElement->rowIndex == row && currentElement->columnIndex == column) {
return currentElement;
}
currentElement = currentElement->nextElement;
} while (currentElement != NULL);
return NULL;
}
void transposeSparseMatrix(SparseMatrix *sparseMatrix) {
SparseMatrixElement *currentElement = sparseMatrix->firstElement;
for (int i=0; i<sparseMatrix->elements; ++i) {
int temp = currentElement->rowIndex;
currentElement->rowIndex = currentElement->columnIndex;
currentElement->columnIndex = temp;
currentElement = currentElement->nextElement;
}
}
void sparseMatrixVectorMultiplication(SparseMatrix 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;
}
SparseMatrixElement *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 printSparseMatrix(SparseMatrix sparseMatrix) {
if (sparseMatrix.elements == 0) {
return;
}
SparseMatrixElement *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;
}
}

30
serial/sparse_matrix.h

@ -1,30 +0,0 @@
#ifndef SPARSE_MATRIX_H /* Include guard */
#define SPARSE_MATRIX_H
#include <stdbool.h>
#include <stdlib.h>
#include <stdio.h>
#include <stdlib.h>
typedef struct sparseMatrixElement {
double value;
int rowIndex, columnIndex;
struct sparseMatrixElement *nextElement;
} SparseMatrixElement;
typedef struct sparseMatrix {
int elements;
SparseMatrixElement *firstElement;
SparseMatrixElement *lastElement;
} SparseMatrix;
SparseMatrix createSparseMatrix();
void apendElement(SparseMatrix *sparseMatrix, double value, int row, int column);
bool deleteElement(SparseMatrix *sparseMatrix, int row, int column);
SparseMatrixElement *getElement(SparseMatrix sparseMatrix, int row, int column);
void transposeSparseMatrix(SparseMatrix *sparseMatrix);
void sparseMatrixVectorMultiplication(SparseMatrix sparseMatrix, double *vector,
double **product, int vectorSize);
void printSparseMatrix(SparseMatrix sparseMatrix);
#endif // SPARSE_MATRIX_H
Loading…
Cancel
Save