Browse Source

Add files via upload

master
mtzikara 6 years ago
committed by GitHub
parent
commit
8dce83172b
No known key found for this signature in database GPG Key ID: 4AEE18F83AFDEB23
  1. 37
      serial_v2/Makefile
  2. BIN
      serial_v2/pagerank.out
  3. 1
      serial_v2/pagerank_output
  4. 33
      serial_v2/serial_gs_pagerank.c
  5. BIN
      serial_v2/serial_gs_pagerank.o
  6. 437
      serial_v2/serial_gs_pagerank_functions.c
  7. 86
      serial_v2/serial_gs_pagerank_functions.h
  8. BIN
      serial_v2/serial_gs_pagerank_functions.o

37
serial_v2/Makefile

@ -0,0 +1,37 @@
SHELL := /bin/bash
# ============================================
# COMMANDS
CC = gcc
RM = rm -f
CFLAGS_DEBUG=-O0 -g -I.
CFLAGS=-std=gnu99 -O3 -I.
OBJ=serial_gs_pagerank.o serial_gs_pagerank_functions.o
DEPS=serial_gs_pagerank_functions.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)

BIN
serial_v2/pagerank.out

Binary file not shown.

1
serial_v2/pagerank_output

File diff suppressed because one or more lines are too long

33
serial_v2/serial_gs_pagerank.c

@ -0,0 +1,33 @@
#include <sys/time.h>
#include "serial_gs_pagerank_functions.h"
struct timeval startwtime, endwtime;
double seq_time;
int main(int argc, char **argv) {
int **directedWebGraph;
int **transitionMatrix;
double *pagerankVector;
Parameters parameters;
parseArguments(argc, argv, &parameters);
initialize(&directedWebGraph, &transitionMatrix, &pagerankVector, &parameters);
// Starts wall-clock timer
gettimeofday (&startwtime, NULL);
int iterations = pagerank(&transitionMatrix, &pagerankVector, parameters);
if (parameters.verbose) {
printf("\n----- Results -----\
\nTotal iterations = %d\n", 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);
}

BIN
serial_v2/serial_gs_pagerank.o

Binary file not shown.

437
serial_v2/serial_gs_pagerank_functions.c

@ -0,0 +1,437 @@
#include "serial_gs_pagerank_functions.h"
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";
// ==================== PAGERANK ====================
int pagerank(int ***transitionMatrix, double **pagerankVector, Parameters parameters) {
int iterations = 0;
double delta,
*vectorDifference = (double *) malloc(parameters.numberOfPages * sizeof(double)),
*previousPagerankVector = (double *) malloc(parameters.numberOfPages * sizeof(double)),
*convergedPagerankVector = (double *) malloc(parameters.numberOfPages * sizeof(double)),
**linksFromConvergedPages = (double **) malloc(parameters.numberOfPages * sizeof(double *)),
*linksFromConvergedPagesPagerankVector = (double *) malloc(parameters.numberOfPages * sizeof(double));
bool *converganceMatrix = (bool *) malloc(parameters.numberOfPages * sizeof(bool));
for (int i=0; i<parameters.numberOfPages; ++i) {
convergedPagerankVector[i] = 0;
converganceMatrix[i] = false;
linksFromConvergedPagesPagerankVector[i] = 0;
linksFromConvergedPages[i] = (double *) malloc(parameters.numberOfPages * sizeof(double));
for (int j=0; j<parameters.numberOfPages; ++j) {
linksFromConvergedPages[i][j] = 0;
}
}
if (parameters.verbose) {
printf("\n----- Starting iterations -----\n");
}
do {
memcpy(previousPagerankVector, *pagerankVector, parameters.numberOfPages * sizeof(double));
matrixVectorMultiplication(*transitionMatrix, previousPagerankVector,
linksFromConvergedPagesPagerankVector, convergedPagerankVector,
pagerankVector, parameters.numberOfPages, parameters.dampingFactor);
if (parameters.history) {
savePagerankToFile(parameters.outputFilename, iterations != 0,
*pagerankVector, parameters.numberOfPages);
}
for (int i=0; i<parameters.numberOfPages; ++i) {
vectorDifference[i] = (*pagerankVector)[i] - previousPagerankVector[i];
}
delta = vectorNorm(vectorDifference, parameters.numberOfPages);
if (!iterations % 10) {
for (int i=0; i<parameters.numberOfPages; ++i) {
double temp = fabs((*pagerankVector)[i] - previousPagerankVector[i]) / fabs(previousPagerankVector[i]);
if (temp < parameters.convergenceCriterion){
converganceMatrix[i] = true;
convergedPagerankVector[i] = (*pagerankVector)[i];
}
}
for (int i=0; i<parameters.numberOfPages; ++i) {
if (converganceMatrix[i] == true) {
for (int j=0; j<parameters.numberOfPages; ++j){
if (converganceMatrix[j] == false){
linksFromConvergedPages[i][j] = (*transitionMatrix)[i][j];
}
// Zeros out CN and CC sub-matrices
(*transitionMatrix)[i][j] = 0;
// Zeros out NC sub-matrix
(*transitionMatrix)[j][i] = 0;
}
double sum = 0;
for (int j=0; j<parameters.numberOfPages; ++j) {
sum += linksFromConvergedPages[i][j] * (*pagerankVector)[j];
}
linksFromConvergedPagesPagerankVector[i] = sum;
}
}
}
++iterations;
printf("Iteration %d: delta = %f\n", iterations, delta);
} while (delta > parameters.convergenceCriterion &&
(parameters.maxIterations == 0 || iterations < parameters.maxIterations));
if (!parameters.history) {
savePagerankToFile(parameters.outputFilename, false, *pagerankVector,
parameters.numberOfPages);
}
return iterations;
}
// ==================== INITIALIZATION ====================
/*
* 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(int ***directedWebGraph, int ***transitionMatrix,
double **pagerankVector, Parameters *parameters) {
// Reads web graph from file
if ((*parameters).verbose) {
printf("----- Reading graph from file -----\n");
}
readGraphFromFile(directedWebGraph, parameters);
// Outputs the algorithm parameters to the console
if ((*parameters).verbose) {
printf("\n----- Running with parameters -----\
\nNumber 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;
}
// Generates the initial transition matrix (matrix P).
generateNormalizedTransitionMatrix(transitionMatrix, *directedWebGraph, *parameters);
// Transposes the transition matrix (P^T).
transposeMatrix(transitionMatrix, (*parameters).numberOfPages, (*parameters).numberOfPages);
}
/*
* generateNormalizedTransitionMatrix generates the normalized transition matrix
* from the graph data (matrix P').
*/
void generateNormalizedTransitionMatrix(int ***transitionMatrix,
int **directedWebGraph, Parameters parameters) {
// Allocates memory for the transitionMatrix rows
(*transitionMatrix) = (int **) malloc(parameters.numberOfPages * sizeof(int *));
for (int i=0; i<parameters.numberOfPages; ++i) {
// Allocates memory for this row's columns
(*transitionMatrix)[i] = (int *) malloc(parameters.numberOfPages * sizeof(int));
/*
// Calculates the outdegree of this page
int pageOutdegree = 0;
for (int j=0; j<parameters.numberOfPages; ++j) {
pageOutdegree += directedWebGraph[i][j];
}
// Populates this row of the transition matrix
if (pageOutdegree != 0) {
// Calculates the uniform probability once.
double pageUniformProbability = 1. / pageOutdegree;
for (int j=0; j<parameters.numberOfPages; ++j) {
if (directedWebGraph[i][j] == 1){
(*transitionMatrix)[i][j] = pageUniformProbability;
} else {
(*transitionMatrix)[i][j] = 0;
}
}
} else {
for (int j=0; j<parameters.numberOfPages; ++j) {
(*transitionMatrix)[i][j] = 0;
}
}
*/
}
for (int i=0; i<parameters.numberOfPages; ++i){
for (int j=0; i<parameters.numberOfPages; ++i){
(*transitionMatrix)[i][j] = directedWebGraph[i][j];
}
}
}
// ==================== MATH UTILS ====================
/*
* matrixVectorMultiplication calculates the product of the multiplication
* between a matrix and the a vector in a cheap way.
*/
void matrixVectorMultiplication(int **transitionMatrix, double *previousPagerankVector,
double *linksFromConvergedPagesPagerankVector, double *convergedPagerankVector,
double **pagerankVector, int vectorSize, double dampingFactor) {
double webUniformProbability = 1. / vectorSize;
for (int i=0; i<vectorSize; ++i) {
double sum1 = 0;
double sum2 = 0;
for (int j=0; j<i; ++j) {
sum1 += transitionMatrix[i][j] * previousPagerankVector[j];
}
for (int j=i; j<vectorSize; ++j) {
sum2 += transitionMatrix[i][j] * (*pagerankVector)[j];
}
(*pagerankVector)[i] = dampingFactor * sum1+dampingFactor * sum2+(1-dampingFactor);
}
//double normDifference = vectorNorm(previousPagerankVector, vectorSize) -
//vectorNorm(*pagerankVector, vectorSize);
for (int i=0; i<vectorSize; ++i) {
//(*pagerankVector)[i] += normDifference * webUniformProbability +
//linksFromConvergedPagesPagerankVector[i] + convergedPagerankVector[i];
(*pagerankVector)[i] += 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;
}
/*
* transposeMatrix transposes the matrix passed (by reference) in the arguments.
*/
void transposeMatrix(int ***matrix, int rows, int columns) {
// Transposes the matrix
// Rows become columns and vice versa
int **tempArray = (int **) malloc(columns * sizeof(int *));
for (int i=0; i<columns; ++i) {
tempArray[i] = malloc(rows * sizeof(int));
for (int j=0; j<rows; ++j) {
tempArray[i][j] = (*matrix)[j][i];
}
}
// TODO free memory
//double **pointerToFreeMemoryLater = *matrix;
*matrix = tempArray;
/*for (int i=0; i<rows; ++i) {
free(pointerToFreeMemoryLater[i]);
}
free(pointerToFreeMemoryLater);*/
}
// ==================== 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 readGraphFromFile(int ***directedWebGraph, Parameters *parameters) {
FILE *graphFile;
// Opens the file for reading
graphFile = fopen((*parameters).graphFilename, "r+");
if (!graphFile) {
printf("Error opening file \n");
exit(EXIT_FAILURE);
}
// Reads the dimensions of the (square) array from the file
int readChar, numberOfLines=0;
while((readChar = fgetc(graphFile))) {
// Breaks if end of file
if (readChar == EOF) break;
// Otherwise, if the character is a break line, adds one to the count of lines
if (readChar == '\n') {
++numberOfLines;
}
}
if ((*parameters).verbose) {
printf("Line count of file is %d \n", numberOfLines + 1);
}
// Each line of the file represents one page of the graph
(*parameters).numberOfPages = numberOfLines + 1;
rewind(graphFile);
// Allocates memory and loads values into directedWebGraph (matrix A)
// Allocates memory for the rows
(*directedWebGraph) = (int **) malloc((*parameters).numberOfPages * sizeof(int *));
for (int i=0; i<(*parameters).numberOfPages; ++i) {
// Allocates memory for the columns of this row
(*directedWebGraph)[i] = (int *) malloc((*parameters).numberOfPages * sizeof(int));
// Reads values from the file
for (int j=0; j<(*parameters).numberOfPages; ++j) {
if (!fscanf(graphFile, "%d ", &(*directedWebGraph)[i][j])) {
break;
}
}
}
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);
}

86
serial_v2/serial_gs_pagerank_functions.h

@ -0,0 +1,86 @@
#ifndef SERIAL_GS_PAGERANK_FUNCTIONS_H /* Include guard */
#define SERIAL_GS_PAGERANK_FUNCTIONS_H
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <math.h>
/*
* 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;
// This is the numerical base used when parsing the numerical command line
// arguments.
extern const int NUMERICAL_BASE;
// Default filename used for the output.
extern char *DEFAULT_OUTPUT_FILENAME;
// Declares 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 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 readGraphFromFile loads adjacency matrix, that represents the web
// graph, stored in the file provided in the command line arguments to the array
// directedWebGraph.
void readGraphFromFile(int ***directedWebGraph, 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 generateNormalizedTransitionMatrix generates the normalized
// transition matrix from the web graph data.
void generateNormalizedTransitionMatrix(int ***transitionMatrix,
int **directedWebGraph, Parameters parameters);
// Function transposeMatrix transposes a matrix.
void transposeMatrix(int ***matrix, int rows, int columns);
// Function initialize allocates required memory for arrays, reads the dataset
// from the file and creates the transition probability distribution matrix.
void initialize(
int ***directedWebGraph, /*This is matrix G (web graph)*/
int ***transitionMatrix, /*This is matrix A (transition probability distribution matrix)*/
double **pagerankVector, /*This is the resulting pagerank vector*/
Parameters *parameters
);
// Function vectorNorm calculates the first norm of a vector.
double vectorNorm(double *vector, int vectorSize);
// Function matrixVectorMultiplication calculates the product of the
// multiplication between a matrix and the a vector.
void matrixVectorMultiplication(int **transitionMatrix, double *previousPagerankVector,
double *linksFromConvergedPagesPagerankVector, double *convergedPagerankVector,
double **pagerankVector, 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(int ***transitionMatrix, double **pagerankVector, Parameters parameters);
#endif // SERIAL_GS_PAGERANK_FUNCTIONS_H

BIN
serial_v2/serial_gs_pagerank_functions.o

Binary file not shown.
Loading…
Cancel
Save