pagerank算法

一、实验内容

  1. 采用基于“抽税”法的PageRank算法分析图1的网页排名;
    这里写图片描述

图1 Web链接实例图

  1. 图1中,若节点①和节点③是主题节点,采用面向主题的PageRank算法重新计算所有节点的PageRank值。

二、实验设计(原理分析及流程)
首先是需要建立一个初始化概率分布向量V0,因为共有6个网页,因此V0的每个分量都是1/6,且V0是一个6维列向量。之后,根据上图的网页链接关系,构造一个网页转移矩阵。
具体是先使用vector来存储初始概率分布向量V0,同时创建结果特征矩阵V2。然后使用一个选择函数Choice来根据用户输入选择合适的向量计算方法(抽税法或面向主题法)。最后,显示surplus以及最终的特征向量。
其中CalResTax 计算特征矩阵左乘概率分布向量,抽税法,参数:上一次左乘结果,这次左乘结果,转移矩阵,抽税常数。CalResThe 计算特征矩阵左乘概率分布向量,面向主题方法,参数:上一次左乘结果,这次左乘结果,主题矩阵,转移矩阵,主题常数。另外,surplus定义为两个向量对应元素差的绝对值之和,使用SurCal函数来实现。

三、代码:

// pagerank.cpp model the google pagerank algorithm
// using taxation or theme oriented
// surplus定义为两个向量对应元素差的绝对值之和

#include <iostream>
#include <vector>
#include <cmath>    // 使用abs()函数 求绝对值
#define PAGENUM  6  // page个数
#define THENUM 2
#define EPS  0.001  // 阈值
#define BETA 0.85   // beta
// 初始化的概率向量v0
std::vector<double> V0 (PAGENUM, (double)1/6);
int ThemeArr[PAGENUM] = { 0.5, 0, 0.5, 0, 0, 0};
std::vector<double> VS0 (ThemeArr, ThemeArr + PAGENUM);
// 手动建立的转移矩阵
double TrMat[PAGENUM][PAGENUM] =
{
    0.0, 0.5, 1.0, 0.0, 0.0, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.0, 0.0,
    1.0, 0.5, 0.0, 0.0, 0.5, 0.0,
    0.0, 0.0, 0.0, 0.0, 0.5, 0.5,
    0.0, 0.0, 0.0, 0.5, 0.0, 0.5,
    0.0, 0.0, 0.0, 0.5, 0.0, 0.0
};

// 网页主题 es
int TheMat[PAGENUM] =
{
    1, 0, 1, 0, 0, 0
};

// 根据用户输入选择抽税还是面向主题的计算pagerank方法
// 输入'T'返回true表明选择抽税方法
char Choice(void)
{
    char UsCho;
    std::cout << "Now choose the calculate function: " << std::endl;
    std::cout << "Enter 'T' for tax, enter 'S' for Theme, enter 'Q' to quit:" << std::endl;
    std::cin >> UsCho;
    return tolower(UsCho);
}

// 计算特征矩阵左乘概率分布向量,抽税法
// 参数:上一次左乘结果, 这次左乘结果, 转移矩阵, 抽税常数
int CalResTax(const std::vector<double> &V1, std::vector<double> &V2,
              const double TrMat[][PAGENUM], const double TAX)
{
    double TemSum = 0.0;
    for(int i = 0; i < PAGENUM; i++)                // 矩阵行变化
    {
        for (int j = 0; j < PAGENUM; j++)           // 矩阵列变化
        {
            TemSum += V1[j] * TrMat[i][j];          // 矩阵列乘以概率列向量
        }
        V2[i] = BETA * TemSum + TAX;                   // 存放左乘后结果 + 税
        TemSum = 0.0;                               // 一行乘以一列的结果重置为0
    }
    return 0;
}

// 计算特征矩阵左乘概率分布向量,面向主题方法
// 参数:上一次左乘结果, 这次左乘结果,主题矩阵, 转移矩阵,主题常数
int CalResThe(const std::vector<double> &V1, std::vector<double> &V2,
              const std::vector<int> &S, const double TrMat[][PAGENUM],const double THEME)
{
    double TemSum = 0.0;
    for(int i = 0; i < PAGENUM; i++)                // 矩阵行变化
    {
        for (int j = 0; j < PAGENUM; j++)           // 矩阵列变化
        {
            TemSum += V1[j] * TrMat[i][j];          // 矩阵列乘以概率列向量
        }
        V2[i] = BETA * TemSum + THEME * S[i];       // 存放左乘后结果 + 主题
        TemSum = 0.0;                               // 一行乘以一列的结果重置为0
    }
    return 0;
}

// 计算surplus,定义见开头注释
// 参数:第一个概率分布向量,第二个概率分布向量
double SurCal(const std::vector<double> &V1, std::vector<double> &V2)
{
    double Sur = 0.0;
    for (int i = 0; i < PAGENUM; i++)
        Sur += fabs(V2[i] - V1[i]);         // 加括号更清晰
    return Sur;
}

int main(void)
{
    // result property matrix
    std::vector<double> V2 (PAGENUM);       // 最新的特征矩阵
    std::vector<int> S(TheMat, TheMat + PAGENUM);       // 主题矩阵

    using std::cout;
    using std::endl;
    double surplus = 1.0;
    const double TAX = (double)(1.0 - BETA) / PAGENUM;    // 循环不变量外提,小优化
    const double THEME = (double)(1.0 - BETA) / THENUM;   // 主题矩阵es
    char cho;
    while (( cho = Choice()) != 'q')
    {
        cout << "cho = " << cho << endl;
        if (cho == 't')
        {
            std::vector<double> V1 (V0);            // 上一个特征矩阵
            while (surplus > EPS)
            {
                CalResTax(V1, V2, TrMat, TAX);
                surplus = SurCal(V1, V2);
                V1.assign(V2.begin(), V2.end());        // 更新V1的内容,注意使用的方法

            }
        }
        else if (cho == 's')
        {
            std::vector<double> V1 (VS0);            // 上一个特征矩阵
            while (surplus > EPS)
            {
                CalResThe(V1, V2, S, TrMat, THEME);
                surplus = SurCal(V1, V2);
                V1.assign(V2.begin(), V2.end());        // 更新V1的内容,注意使用的方法
            }
        }
        else
            continue;
        cout << "surplus: " << surplus << endl;
        cout << "The result vector: " << endl;
        for(auto p : V2)                        // 输出最后的特征矩阵
            cout << p << endl;
        surplus = 1.0;                   // 重置surplus以便其他方法调用
    }
    cout << "Done." << endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值