6 * $Date: 2012-07-15 19:26:11 +0200 (So, 15. Jul 2012) $
7 ***************************************************************/
10 * \brief Implementation of basic page rank.
12 * \author Martin Gronemann
15 * This file is part of the Open Graph Drawing Framework (OGDF).
19 * See README.txt in the root directory of the OGDF installation for details.
22 * This program is free software; you can redistribute it and/or
23 * modify it under the terms of the GNU General Public License
24 * Version 2 or 3 as published by the Free Software Foundation;
25 * see the file LICENSE.txt included in the packaging of this file
29 * This program is distributed in the hope that it will be useful,
30 * but WITHOUT ANY WARRANTY; without even the implied warranty of
31 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
32 * GNU General Public License for more details.
35 * You should have received a copy of the GNU General Public
36 * License along with this program; if not, write to the Free
37 * Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
38 * Boston, MA 02110-1301, USA.
40 * \see http://www.gnu.org/copyleft/gpl.html
41 ***************************************************************/
44 #include <ogdf/graphalg/PageRank.h>
49 void BasicPageRank::call(
51 const EdgeArray
<double>& edgeWeight
,
52 NodeArray
<double>& pageRankResult
)
54 const double initialPageRank
= 1.0 / (double)graph
.numberOfNodes();
55 const double maxPageRankDeltaBound
= initialPageRank
* m_threshold
;
57 // the two ping pong buffer
58 NodeArray
<double> pageRankPing(graph
, 0.0);
59 NodeArray
<double> pageRankPong(graph
, 0.0);
61 NodeArray
<double>* pCurrPageRank
= &pageRankPing
;
62 NodeArray
<double>* pNextPageRank
= &pageRankPong
;
64 NodeArray
<double> nodeNorm(graph
);
66 for (node v
= graph
.firstNode(); v
; v
= v
->succ())
69 for (adjEntry adj
= v
->firstAdj(); adj
; adj
= adj
->succ())
71 edge e
= adj
->theEdge();
74 nodeNorm
[v
] = 1.0 / sum
;
77 pCurrPageRank
->init(graph
, initialPageRank
);
79 // main iteration loop
80 int numIterations
= 0;
81 bool converged
= false;
83 while ( !converged
&& (numIterations
< m_maxNumIterations
) )
85 // init the result of this iteration
86 pNextPageRank
->init(graph
, (1.0 - m_dampingFactor
) / (double)graph
.numberOfNodes());
87 // calculate the transfer between each node
88 for (edge e
= graph
.firstEdge(); e
; e
= e
->succ())
93 double vwTransfer
= (edgeWeight
[e
] * nodeNorm
[v
] * (*pCurrPageRank
)[v
]);
94 double wvTransfer
= (edgeWeight
[e
] * nodeNorm
[w
] * (*pCurrPageRank
)[w
]);
95 (*pNextPageRank
)[w
] += vwTransfer
;
96 (*pNextPageRank
)[v
] += wvTransfer
;
99 // damping and calculating change
100 double maxPageRankDelta
= 0.0;
101 for (node v
= graph
.firstNode(); v
; v
= v
->succ())
103 (*pNextPageRank
)[v
] *= m_dampingFactor
;
104 double pageRankDelta
= fabs((*pNextPageRank
)[v
] - (*pCurrPageRank
)[v
]);
105 maxPageRankDelta
= std::max(maxPageRankDelta
, pageRankDelta
);
108 // swap ping and pong, pong ping, ping pong, lalalala
109 std::swap(pNextPageRank
, pCurrPageRank
);
112 // check if the change is small enough
113 converged
= (maxPageRankDelta
< maxPageRankDeltaBound
);
117 double maxPageRank
= (*pCurrPageRank
)[graph
.firstNode()];
118 double minPageRank
= (*pCurrPageRank
)[graph
.firstNode()];
119 for (node v
= graph
.firstNode(); v
; v
= v
->succ())
121 maxPageRank
= std::max(maxPageRank
, (*pCurrPageRank
)[v
]);
122 minPageRank
= std::min(minPageRank
, (*pCurrPageRank
)[v
]);
126 pageRankResult
.init(graph
);
127 for (node v
= graph
.firstNode(); v
; v
= v
->succ())
129 double r
= ((*pCurrPageRank
)[v
] - minPageRank
) / (maxPageRank
- minPageRank
);
130 pageRankResult
[v
] = r
;
132 // result is now between 0 and 1
135 } // end of namespace ogdf