graphlite同步图之KCore问题

KCore问题
• KCore
一个图GKCore G的子图
这个子图的每个顶点的度K
计算方法
如果顶点的度小于k,从图中删除该顶点,然后给邻居发送消息
顶点收到消息后,得知被删掉的邻居顶点,更新自己的度
输入:无向图 (有成对的有向边)
输出:  KCor 子图中的所有顶点
顶点
顶点

graphlite的安装和配制,其他博客有很好的介绍,这里就不讲了。

本文主要讲Kcore的编程实现。每遍历一次所有结点就是一个超步。

大家直接看代码,我会在关键部分添加注释。在注释中,尽力的表述了每个函数的用途。希望读者可以理解整个过程,而不是简单的照搬抄袭。

/**
 * @file PageRankVertex.cc
 * @author  Songjie Niu, Shimin Chen
 * @version 0.1
 *
 * @section LICENSE 
 * 
 * Copyright 2016 Shimin Chen (chensm@ict.ac.cn) and
 * Songjie Niu (niusongjie@ict.ac.cn)
 * 
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 * 
 * @section DESCRIPTION
 * 
 * This file implements the PageRank algorithm using graphlite API.
 * Modified by Zhengyang Peng to accomplish Homework 2
 */

#include <stdio.h>
#include <string.h>
#include <math.h>

#include "GraphLite.h"

#define VERTEX_CLASS_NAME(name) KCore##name

#define EPS 1e-6
int K = 0;	//初始化K的值,子图中每个点的度必须大于K。

class VERTEX_CLASS_NAME(InputFormatter): public InputFormatter {
public:
    int64_t getVertexNum() {
        unsigned long long n;
        sscanf(m_ptotal_vertex_line, "%lld", &n);
        m_total_vertex= n;
        return m_total_vertex;
    }
    int64_t getEdgeNum() {
        unsigned long long n;
        sscanf(m_ptotal_edge_line, "%lld", &n);
        m_total_edge= n;
        return m_total_edge;
    }
    int getVertexValueSize() {
        m_n_value_size = sizeof(double);
        return m_n_value_size;
    }
    int getEdgeValueSize() {
        m_e_value_size = sizeof(double);
        return m_e_value_size;
    }
    int getMessageValueSize() {
        m_m_value_size = sizeof(double);
        return m_m_value_size;
    }
    void loadGraph() {
        unsigned long long last_vertex;
        unsigned long long from;
        unsigned long long to;
        double weight = 0;
        
        double value = 1;
        int outdegree = 0;
        
        const char *line= getEdgeLine();

        // Note: modify this if an edge weight is to be read
        //       modify the 'weight' variable

        sscanf(line, "%lld %lld", &from, &to);
        addEdge(from, to, &weight);

        last_vertex = from;
        ++outdegree;
        for (int64_t i = 1; i < m_total_edge; ++i) {
            line= getEdgeLine();

            // Note: modify this if an edge weight is to be read
            //       modify the 'weight' variable

            sscanf(line, "%lld %lld", &from, &to);
            if (last_vertex != from) {
		value=outdegree;
                addVertex(last_vertex, &value, outdegree);
                last_vertex = from;
                outdegree = 1;
            } else {
                ++outdegree;
            }
            addEdge(from, to, &weight);
        }
		value=outdegree;
        addVertex(last_vertex, &value, outdegree);		//加载图后,可以传3个参数到函数addVertex中,为了方便,此问题,直接把value的值赋为outdegree。
    }
};

class VERTEX_CLASS_NAME(OutputFormatter): public OutputFormatter {
public:
    void writeResult() {		//此函数为输出结果函数。
        int64_t vid;
        double value;
        char s[1024];

        for (ResultIterator r_iter; ! r_iter.done(); r_iter.next() ) {
            r_iter.getIdValue(vid, &value);
		if(value!=0){				//如果value值不为0,也就是度不为了0,度小于K的,都被赋值为0了。
            int n = sprintf(s, "%lld\n", (unsigned long long)vid);
            writeNextResLine(s, n);}
        }
    }
};

// An aggregator that records a double value tom compute sum
class VERTEX_CLASS_NAME(Aggregator): public Aggregator<double> {
public:
    void init() {
        m_global = 0;
        m_local = 0;
    }
    void* getGlobal() {
        return &m_global;
    }
    void setGlobal(const void* p) {
        m_global = * (double *)p;
    }
    void* getLocal() {
        return &m_local;
    }
    void merge(const void* p) {
        m_global += * (double *)p;
    }
    void accumulate(const void* p) {
        m_local += * (double *)p;
    }
};

class VERTEX_CLASS_NAME(): public Vertex <double, double, double> {
public:
    void compute(MessageIterator* pmsgs) {
        double val;
		printf("%d ",int(getValue()));	//printf可以输出到日志,同学们可以使用printf观察各个变量的变化。
        if (getSuperstep() == 0) {        //每遍历一次所有结点,就是一个超步。
			printf("K=%d ",K);			
        } 
		else 
		{
		if (getSuperstep() > 2 ){
                	double global_val = * (double *)getAggrGlobal(0);
                	if (global_val < 0.00000001) {			//如果此超步结束,总度不再变化,结束超步。
                   	 voteToHalt(); 
					 return;
                	}
            	}
		if (getSuperstep() >= 1&&getValue()!=0){
            double sum = 0;
		    for ( ; ! pmsgs->done(); pmsgs->next() ) {		
		        sum += pmsgs->getValue();					//将邻居结点发送的消息的值相加,结果即所有邻接结点删除后,当前结点总共损失的度。
		    }
		    if(getValue()-sum < K){						//如果更新度后的结点的度小于K。
				sendMessageToAllNeighbors(1);				//向邻居结点广播消息,通知邻居,你们的度需要减少1。
				double acc = fabs(sum);					//acc为此结点的度的变化值。
		    	accumulateAggr(0, &acc);					//此函数记录此超步中每个结点的度的变化的和。
				val=0;							//此结点已被删除,度(value值)变为0。	
				* mutableValue() = val;					//* mutableValue()赋值后,可以改变结点的value值,在此问题中即是出度。
		    }
		    else{								//如果更新度后的结点的度不小于K,则不需要向邻居结点广播消息。
				val = getValue()-sum;						
		    	 double acc = fabs(getValue() - val);
				accumulateAggr(0, &acc);					
				* mutableValue() = val;					//更新自己的出度。
		    }
		}
		}

        
        const int64_t n = getOutEdgeIterator().size();
        
    }
};

class VERTEX_CLASS_NAME(Graph): public Graph {
public:
    VERTEX_CLASS_NAME(Aggregator)* aggregator;

public:
    // argv[0]: KCore.so
    // argv[1]: <input path>
    // argv[2]: <output path>
    // argv[3]: <K>
    void init(int argc, char* argv[]) {

        setNumHosts(5);
        setHost(0, "localhost", 1411);
        setHost(1, "localhost", 1421);
        setHost(2, "localhost", 1431);
        setHost(3, "localhost", 1441);
        setHost(4, "localhost", 1451);

        if (argc <= 3) {
           printf ("Usage: %s <input path> <output path> <K>\n", argv[0]);
           exit(1);
        }

        m_pin_path = argv[1];
        m_pout_path = argv[2];
		K= atoi(argv[3]);		//读取参数K。


        aggregator = new VERTEX_CLASS_NAME(Aggregator)[1];
        regNumAggr(1);
        regAggr(0, &aggregator[0]);
    }

    void term() {
        delete[] aggregator;
    }
};

/* STOP: do not change the code below. */
extern "C" Graph* create_graph() {
    Graph* pgraph = new VERTEX_CLASS_NAME(Graph);

    pgraph->m_pin_formatter = new VERTEX_CLASS_NAME(InputFormatter);
    pgraph->m_pout_formatter = new VERTEX_CLASS_NAME(OutputFormatter);
    pgraph->m_pver_base = new VERTEX_CLASS_NAME();

    return pgraph;
}

extern "C" void destroy_graph(Graph* pobject) {
    delete ( VERTEX_CLASS_NAME()* )(pobject->m_pver_base);
    delete ( VERTEX_CLASS_NAME(OutputFormatter)* )(pobject->m_pout_formatter);
    delete ( VERTEX_CLASS_NAME(InputFormatter)* )(pobject->m_pin_formatter);
    delete ( VERTEX_CLASS_NAME(Graph)* )pobject;
}

  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

果壳三明治

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值