Skip to content
This repository was archived by the owner on May 13, 2024. It is now read-only.

Commit 7ca2557

Browse files
committedAug 9, 2020
Start working on refactoring multiplication to be more efficient
1 parent fa922e1 commit 7ca2557

12 files changed

+212
-265
lines changed
 

‎CMakeLists.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ set(CMAKE_C_STANDARD 90)
55
set(GCC_COVERAGE_COMPILE_FLAGS "-ansi -Wall -Wextra -Werror -pedantic-errors")
66
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}" )
77

8-
add_executable(cluster cluster.c spmat.c matrix.h matrix.c graph.h graph.c LinkedList.h LinkedList.c VerticesGroup.h VerticesGroup.c division.h division.c)
8+
add_executable(cluster cluster.c spmat.c matrix.h matrix.c graph.h graph.c LinkedList.h LinkedList.c VerticesGroup.h VerticesGroup.c division.h division.c defs.h defs.c)

‎VerticesGroup.c

+112-59
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
#include <stdio.h>
22
#include <stdlib.h>
3+
#include <math.h>
34
#include "VerticesGroup.h"
45
#include "matrix.h"
56
#include "spmat.h"
7+
#include "defs.h"
68

79
VerticesGroup *createVerticesGroup() {
810
VerticesGroup *group = malloc(sizeof(VerticesGroup));
911
group->size = 0;
10-
group->edgesMinusBHatSubMatrix = NULL;
1112
group->edgeSubMatrix = NULL;
12-
group->bSubMatrix = NULL;
13-
group->bHatSubMatrix = NULL;
13+
group->modularitySubMatrix = NULL;
14+
group->modularityRowSums = NULL;
15+
group->modularityAbsColSum = NULL;
1416
return group;
1517
}
1618

@@ -24,14 +26,13 @@ void freeVerticesGroup(VerticesGroup *group) {
2426
node = temp;
2527
} while (node != group->first);
2628
}
27-
if (group->bHatSubMatrix != NULL) {
28-
freeMatrix(group->bHatSubMatrix);
29-
}
30-
if (group->edgesMinusBHatSubMatrix != NULL) {
31-
freeMatrix(group->edgesMinusBHatSubMatrix);
32-
}
29+
3330
if (group->edgeSubMatrix != NULL) {
31+
/* the modulary was calculated, so all related data should be freed */
3432
group->edgeSubMatrix->free(group->edgeSubMatrix);
33+
freeMatrix(group->modularitySubMatrix);
34+
free(group->modularityRowSums);
35+
free(group->modularityAbsColSum);
3536
}
3637
}
3738

@@ -53,49 +54,31 @@ VertexNode *addVertexToGroup(VerticesGroup *group, int index) {
5354
return node;
5455
}
5556

56-
void removeVertexFromGroup(VerticesGroup *group, VertexNode *node) {
57-
if (group->first == node) {
58-
if (group->size == 1) {
59-
group->first = NULL;
60-
} else {
61-
group->first = node->next;
62-
}
63-
}
64-
node->prev->next = node->next;
65-
node->next->prev = node->prev;
66-
group->size--;
67-
free(node);
68-
}
69-
7057
/**
71-
* Adds a sequence of indices to the group.
72-
* @param group the group to which nodes are added.
73-
* @param sequence a sequence of integers, representing nodes in a graph.
74-
* @param length the length of the input sequence.
58+
* Get the 1-norm of the modularity matrix
59+
* @param group vertices group
60+
* @return 1-norm
7561
*/
76-
void addSequence(VerticesGroup *group, int *sequence, int length) {
77-
int i;
78-
for (i = 0; i < length; ++i)
79-
addVertexToGroup(group, sequence[i]);
62+
double getModularityMatrixNorm1(VerticesGroup *group) {
63+
return group->modularityAbsColSum[group->highestColSumIndex];
8064
}
8165

8266
/**
83-
* Create sub matrix
84-
* @param A edges matrix
85-
* @param M degrees sum
86-
* @param group
87-
* @return Fills group->bSubMatrix and group->bHatSubMatrix.
67+
* Calculate the modularity sub matrix in the VerticesGroup object
68+
* @param G graph object
69+
* @param group vertices group containing the modularity sub matrix
8870
*/
89-
void calculateSubMatrix(Matrix *A, int M, VerticesGroup *group) {
71+
void calculateModularitySubMatrix(Graph *G, VerticesGroup *group) {
9072
VertexNode *node;
91-
double *row, expectedEdges;
73+
double *row, modularityEntry;
9274
int i = 0, j;
9375
if (group->size != 0) {
94-
group->edgeSubMatrix = spmat_allocate_list(group->size);
95-
group->edgesMinusBHatSubMatrix = createMatrix(group->size);
96-
group->bSubMatrix = createMatrix(group->size);
97-
group->bHatSubMatrix = createMatrix(group->size);
9876
group->verticesArr = malloc(sizeof(int) * group->size);
77+
group->edgeSubMatrix = spmat_allocate_list(group->size);
78+
group->modularitySubMatrix = createMatrix(group->size);
79+
group->modularityRowSums = calloc(group->size, sizeof(double));
80+
group->modularityAbsColSum = calloc(group->size, sizeof(double));
81+
group->highestColSumIndex = 0;
9982
row = malloc(sizeof(double) * group->size);
10083
node = group->first;
10184
do {
@@ -105,41 +88,111 @@ void calculateSubMatrix(Matrix *A, int M, VerticesGroup *group) {
10588
} while (node != group->first);
10689
for (i = 0; i < group->size; i++) {
10790
for (j = 0; j < group->size; j++) {
108-
row[j] = readVal(A, group->verticesArr[i], group->verticesArr[j]);
109-
/* For each vertex v: A[v][0] + ... + A[v][n-1] = deg(v) */
110-
expectedEdges = A->rowSums[group->verticesArr[i]] * A->rowSums[group->verticesArr[j]] / M;
111-
setVal(group->edgesMinusBHatSubMatrix, i, j, -expectedEdges);
112-
setVal(group->bSubMatrix, i, j, row[j] - expectedEdges);
113-
/* the case where delta(i,j)=0 */
91+
row[j] = readVal(G->adjMat, group->verticesArr[i], group->verticesArr[j]);
92+
modularityEntry = row[j] - readVal(G->expectedEdges, i, j);
93+
setVal(group->modularitySubMatrix, i, j, modularityEntry);
94+
group->modularityRowSums[i] += modularityEntry;
11495
if (i != j) {
115-
setVal(group->bHatSubMatrix, i, j, row[j] - expectedEdges);
96+
/* the case of non diagonal values.
97+
* the modularity matrix is symmetric, so we can add row sums instead of columns */
98+
group->modularityAbsColSum[i] += fabs(modularityEntry);
11699
}
117100
}
118-
/* the case where i=j and so delta(i,j)=1. we subtract deg(i) from B[g][i][j]. */
119-
setVal(group->bHatSubMatrix, i, i, readVal(group->bSubMatrix, i, i) - group->bSubMatrix->rowSums[i]);
120-
setVal(group->edgesMinusBHatSubMatrix, i, i,
121-
readVal(group->edgesMinusBHatSubMatrix, i, i) - group->bSubMatrix->rowSums[i]);
101+
/* handle diagonal values */
102+
modularityEntry = readVal(group->modularitySubMatrix, i, i) - group->modularityRowSums[i];
103+
setVal(group->modularitySubMatrix, i, i, modularityEntry);
104+
group->modularityAbsColSum[i] += fabs(modularityEntry);
105+
if (group->modularityAbsColSum[i] >= getModularityMatrixNorm1(group)) {
106+
/* replace highest column absolute sum */
107+
group->highestColSumIndex = i;
108+
}
109+
/* TODO: improve instead of adding row at a time */
122110
group->edgeSubMatrix->add_row(group->edgeSubMatrix, row, i);
123111
}
124112

125113
free(row);
126114
}
127115
}
128116

117+
/**
118+
* Multiply the modularity matrix of a sub group of vertices by an eigenvector: s_t*B*s
119+
* @param group the vertices group of the modularity matrix
120+
* @param s eigenvector to multiply by
121+
* @param res the vector multiplication result, should be allocated
122+
* @param bothSides boolean, if set to 0 will only multiply by s on the right,
123+
* storing the result in res and returning the the norm of res
124+
* @return multiplication result (or the vector's norm if bothSides=0)
125+
*/
126+
double multiplyModularityByVector(Graph *G, VerticesGroup *group, double *s, double *res, int bothSides) {
127+
int i;
128+
double numRes = 0;
129+
/* the common value of all rows of the multiplication of the expectedEdges (K) matrix by s */
130+
double degreesCommon = 0, modularityNorm1 = getModularityMatrixNorm1(group);
131+
group->edgeSubMatrix->mult(group->edgeSubMatrix, s, res);
132+
for (i = 0; i < group->size; i++) {
133+
degreesCommon += G->degrees[i] * s[i];
134+
res[i] += (modularityNorm1 - group->modularityRowSums[i]) * s[i];
135+
}
136+
for (i = 0; i < group->size; i++) {
137+
res[i] -= G->degrees[i] * degreesCommon / G->degreeSum;
138+
if (bothSides) {
139+
numRes += s[i] * res[i];
140+
} else {
141+
numRes += res[i] * res[i];
142+
}
143+
}
144+
if (!bothSides) {
145+
/* if the result is a vector, we return its norm */
146+
numRes = sqrt(numRes);
147+
}
148+
return numRes;
149+
}
150+
129151
/**
130152
* Calculate modularity delta of group's division given by an eigenvector
131153
* @param group
132154
* @param s eigenvector
133-
* @return
155+
* @return modularity
134156
*/
135-
double calculateModularity(VerticesGroup *group, double *s) {
157+
double calculateModularity(Graph *G, VerticesGroup *group, double *s) {
136158
double *res, numRes;
137159
res = malloc(group->size * sizeof(double));
138-
group->edgeSubMatrix->mult(group->edgeSubMatrix, s, res);
139-
numRes = vectorMult(s, res, group->size);
140-
matrixVectorMult(group->edgesMinusBHatSubMatrix, s, res);
141-
numRes -= vectorMult(s, res, group->size);
160+
numRes = multiplyModularityByVector(G, group, s, res, 1);
142161
numRes *= 0.5;
143162
free(res);
144163
return numRes;
145164
}
165+
166+
/**
167+
* Perform the power iteration algorithm
168+
* @param group a vertices group, containing the modularity sub matrix
169+
* @param vector initial vector for the algorithm
170+
* @param vectorResult the eigenvector found by the algorithm, should be allocated
171+
* @return the eigenvalue of the eigenvector 'vectorResult'.
172+
*/
173+
double powerIteration(Graph *G, VerticesGroup *group, double *vector, double *vectorResult) {
174+
int i, con = 1;
175+
double vectorNorm, dif, lambda, x, y;
176+
while (con) {
177+
x = y = 0;
178+
vectorNorm = multiplyModularityByVector(G, group, vector, vectorResult, 0);
179+
con = 0;
180+
/* printf("\n\n\ni\tvectorResult[i]\tvectorResult[i]/vectorSize\tvector[i]\tdiff\tsum\n"); */
181+
for (i = 0; i < group->size; i++) {
182+
/* printf("%d\t%f\t%f\t%f\t%f\t%f\n", i,vectorResult[i], vectorResult[i]/vectorSize,vector[i], fabs(vectorResult[i]/vectorSize - vector[i]), vectorResult[i]/vectorSize + vector[i]); */
183+
x += vector[i] * vectorResult[i];
184+
y += vector[i] * vector[i];
185+
vectorResult[i] /= vectorNorm;
186+
dif = fabs(vectorResult[i] - vector[i]);
187+
if (IS_POSITIVE(dif)) {
188+
con = 1;
189+
}
190+
vector[i] = vectorResult[i];
191+
}
192+
}
193+
194+
/* compute the corresponding eigenvalue (with respect to the un-shifted B_hat) */
195+
lambda = x / y;
196+
lambda -= getModularityMatrixNorm1(group);
197+
return lambda;
198+
}

‎VerticesGroup.h

+12-8
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
#include "matrix.h"
55
#include "spmat.h"
6+
#include "graph.h"
67

78
typedef struct vertexNode {
89
int index;
@@ -17,10 +18,11 @@ typedef struct verticesGroup {
1718
int size;
1819
int *verticesArr;
1920
spmat *edgeSubMatrix;
20-
/*a matrix that equals bHat-A*/
21-
Matrix *edgesMinusBHatSubMatrix;
22-
Matrix *bSubMatrix;
23-
Matrix *bHatSubMatrix;
21+
/* TODO: no need to save the modularitySubMatrix */
22+
Matrix *modularitySubMatrix;
23+
double *modularityRowSums;
24+
double *modularityAbsColSum;
25+
int highestColSumIndex;
2426

2527
} VerticesGroup;
2628

@@ -30,12 +32,14 @@ void freeVerticesGroup(VerticesGroup *group);
3032

3133
VertexNode *addVertexToGroup(VerticesGroup *group, int index);
3234

33-
void removeVertexFromGroup(VerticesGroup *group, VertexNode *node);
35+
void calculateModularitySubMatrix(Graph *G, VerticesGroup *group);
3436

35-
void addSequence(VerticesGroup *group, int *sequence, int length);
37+
double multiplyModularityByVector(Graph *G, VerticesGroup *group, double *s, double *res, int bothSides);
3638

37-
void calculateSubMatrix(Matrix *A, int M, VerticesGroup *group);
39+
double calculateModularity(Graph *G, VerticesGroup *group, double *s);
3840

39-
double calculateModularity(VerticesGroup *group, double *s);
41+
double getModularityMatrixNorm1(VerticesGroup *group);
42+
43+
double powerIteration(Graph *G, VerticesGroup *group, double *vector, double *vectorResult);
4044

4145
#endif

‎cluster.c

+2-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ int main() {
1414
LinkedListNode *node;
1515
VerticesGroup *group;
1616
VertexNode *vNode;
17-
graph *G = constructGraphFromInput("graph.in");
17+
Graph *G = constructGraphFromInput(
18+
"C:\\Users\\royar\\Source\\Workspaces\\Workspace\\C projects\\cproject-cluster\\graph.in");
1819
srand(time(0));
1920
groupsLst = divisionAlgorithm(G);
2021
node = groupsLst->first;

‎defs.c

+2
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
#include <stdio.h>
2+
#include "defs.h"

‎defs.h

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#ifndef CLUSTER_DEFS_H
2+
#define CLUSTER_DEFS_H
3+
4+
#define IS_POSITIVE(X) ((X)>0.0001)
5+
6+
#endif

0 commit comments

Comments
 (0)