我们已经作为一项任务给出了创建map reduce函数的任务,该函数将为google web graph列表中的每个节点n输出您可以从3跳中的节点n开始的节点. (实际数据可在此处找到: http://snap.stanford.edu/data/web-Google.html)
以下是列表中项目的示例:
1 2 
1 3 
2 4 
3 4 
3 5 
4 1 
4 5 
4 6 
5 6

从上面的示例图将是这样的

在上面的简化示例中,例如节点1的路径是
α[1 – > 2 – > 4 – > 1],[1 – > 2 – > 4 – > 5],[1 – > 2 – > 4 – > 6],[1 – > 3 – > 4 – > 1],
[1 – > 3 – > 4 – > 5],[1 – > 3 – > 4 – > 6]και[1 – > 3 – > 5 – > 6]
因此地图缩小将为节点1输出顶点1,5,6(
(a)每个顶点只能计算一次,并且
(b)我们仅在存在长度为3的圆形路径时包括当前顶点,如示例[1 – > 2 – > 4 – > 1]和[1 – > 3 – > 4 – > 1].

我很失落,因为我相信这需要图论和算法的知识,而且我们没有被教过任何与之相关的知识.

如果有人能给我正确的方向开始,我将不胜感激. (我已经研究过最短路径理论,但我不确定它是否会对这个特定的练习有用)

在此先感谢,并有一个愉快的假期.

编辑

我尝试创建adjucency列表,但我希望输出为“vertexID”“node1 node2 node3 node4 …”我看到在输出文件中我的reducer将每个顶点Id的列表拆分为三对.

例如,如果我有一个连接到Z,X,C,V,B,N,M,G,H,J,K,L的顶点A我将它输出为

Z,C

A V,N

A M,H

A J,L

下面是我的mapper和reducer

public class AdjacentsListDriver extends Configured implements Tool {

    @Override
    public int run(String[] args) throws Exception {



        Configuration conf = getConf();
        Job job = Job.getInstance(conf);
        job.setJobName("Test driver");
        job.setJarByClass(AdjacentsListDriver.class);

        String[] arg0 = new GenericoptionsParser(conf,args).getRemainingArgs();
        if (arg0.length != 2) {
            System.err.println("Usage: hadoop jar <my_jar> <input_dir> <output_dir>");
            System.exit(1);
        }

        Path in = new Path(arg0[0]);
        Path out = new Path(arg0[1]);

        FileInputFormat.setInputPaths(job,in);
        FileOutputFormat.setoutputPath(job,out);

        job.setMapperClass(ListMapper.class);
        job.setReducerClass(ListReducer.class);

        job.setInputFormatClass(TextInputFormat.class);
        job.setoutputFormatClass(textoutputFormat.class);

        job.setoutputKeyClass(Text.class);
        job.setoutputValueClass(Text.class);    
        job.waitForCompletion(true);

        return 0;
    }

    public static void main(String[] args) throws Exception {
        int res = ToolRunner.run(new Configuration(),new AdjacentsListDriver(),args);
        System.exit(res);

    }



}





/**
 * @author George
 * Theoretically this takes a key(vertexID) and maps all nodes that are connected to it in one hop....
 *
 */
public class ListMapper extends Mapper<LongWritable,Text,Text> {

    private Text vertexID = new Text();
    //private LongWritable vertice= new LongWritable(0);
    private Text vertice=new Text();

    public void map(LongWritable key,Text value,Context context) throws IOException,InterruptedException {

        String line = value.toString();
        StringTokenizer itr = new StringTokenizer(line,"\n");
        StringTokenizer itrInside;

        //vertice=new LongWritable(Long.valueOf(value.toString()).longValue());


        while (itr.hasMoretokens()) {
            if(itr.countTokens() > 2){

            }//ignore first line ??
            else{
                itrInside=new StringTokenizer(itr.toString());
                vertexID.set(itr.nextToken());

                while(itrInside.hasMoretokens()){               
                    vertice.set(itrInside.nextToken());
                    context.write(vertexID,value);
                }           
            }
        }

    }

}

@override
public class ListReducer extends Reducer<Text,Text>{
    public void reduce(Text key,Iterable<Text> values,InterruptedException {

        String vertices="";

        for (Text value : values) {
            if(vertices=="")
                vertices+=value.toString();
            else
                vertices=vertices+","+value.toString();         
        }

        Text value=new Text();
        value.set(vertices);
        context.write(key,value);

    }

}

解决方法

由于这是你的(家庭作业)任务,我不会包含Java / Hadoop解决方案,但我会尝试使MapReduce的图形计算概念更加清晰,以便您自己实现它.

对于每个顶点,您希望正好是n跳的顶点.在查看最短路径算法时,您在正确的路径上,但通过简单的广度优先搜索可以更轻松地解决它.

但是,在使用MapReduce处理图形时,您需要更深入地了解顶点之间的消息传递.图算法通常用多个作业表示,其中map和reduce阶段具有以下赋值:

> Mapper:向另一个顶点发送消息(通常用于顶点的每个邻居)
> Reducer:对传入的消息进行分组,加入核心图并减少它们,有时会发送更多消息.

每个作业将始终按照上一个作业的输出进行操作,直到您达到结果或放弃为止.

数据准备

在您真正想要运行图算法之前,请确保您的数据采用邻接列表的形式.它将使以下迭代算法更容易实现.

因此,您需要按顶点id对它们进行分组,而不是邻接元组.这是一些伪代码:

map input tuple (X,Y): 
   emit (X,Y)

reduce input (X,Y[]) :
  emit (X,Y[])

基本上你只是按顶点id进行分组,所以你的输入数据是它的邻居的一个键(顶点id)(可以从那个特定的键顶点id到达的顶点id列表).如果要节省资源,可以将reducer用作组合器.

算法

就像我已经提到的那样,你只需要一个广度优先的搜索算法.您将为图中的每个顶点执行广度优先搜索算法,当命中邻居时,您将只增加一个跳数计数器,该计数器告诉我们离开头顶点的距离(这是最短路径算法的最简单情况,即当边缘重量为1)时.

让我向您展示一个简单的图片,用简单的图表描述它.橙色意味着访问,蓝色未访问,绿色是我们的结果.括号中是跳数计数器.

你看,在每次迭代中我们都为每个顶点设置一个hopcounter.如果我们点击一​​个新的顶点,我们只会将它增加一个.如果我们到达第n个顶点,我们将以某种方式将其标记为以后查找.

使用MapReduce进行分发

虽然对每个顶点进行广度优先搜索似乎非常浪费,但我们可以通过并行化来做得更好.消息传递到游戏中.就像上面的图片一样,我们在映射步骤中得到的每个顶点最初都会向包含以下有效负载的邻居发送一条消息:

HopMessage: Origin (VertexID) | HopCounter(Integer)

在第一次迭代中,我们将尝试将消息发送给邻居以启动计算.否则,我们只会代理图表或传入消息.

因此,在数据准备完成后的第一份工作中,map和reduce看起来像这样:

map input (VertexID key,either HopMessage or List<VertexID> adjacents):
  if(iterationNumber == 1): // only in the first iteration to kick off
     for neighbour in adjacents:
        emit (neighbour,new HopMessage(key,0))
  emit (key,adjacents or HopMessage) // for joining in the reducer

reducer现在在图形和消息之间进行简单连接,主要是为了获得顶点的邻居,导致输入(采用我的简单图形):

1 2 // graph 
2 1 // hop message
2 3 // graph
3 1 // hop message
3 4 // graph
4 1 // hop message
4 - // graph

在reducer步骤中,我们将再次将消息转发给邻居,并在递增后检查跳计数器是否已经达到3.

reducer input(VertexID key,List<either HopMessage or List<VertexID> neighbours> values):
 for hopMessage in values:
    hopMessage.counter += 1
    if (hopMessage.counter == 3) 
       emit to some external resource (HopMessage.origin,key)
    else 
       for neighbour in neighbours of key:
          emit (neighbour,hopMessage)
    emit (key,neighbours)

正如您所看到的,它可能会变得非常混乱:您需要管理两种不同类型的消息,然后还要写入一些外部资源,这些资源将跟踪正好3跳的顶点.

只要有要发送的HopMessages,就可以安排迭代的作业.这很容易出现图中循环的问题,因为在这种情况下你将无限增加hopcounter.所以我建议到目前为止发送完整的遍历路径与每条消息(非常浪费)或者只是限制要进行的迭代次数.在n = 3的情况下,不需要超过3个作业迭代.

有很多博客和项目可以为您提供有关如何处理Hadoop中每个问题的示例.至少我在我的博客中写过MapReduce中的图形运算,你可以在我的github上找到一些例子.

清理输出数据

最后,您将拥有一堆包含顶点的文件 – >顶点映射.您可以像在准备中一样减少它们.

使用pregel的Niftier方式

处理图形的一种不那么繁琐的方法是使用表达图形计算的pregel方法. pregel正在使用以顶点为中心的模型,使表达这种广度优先计算变得更加容易.

以下是使用Apache Hama的上述算法的简单示例:

public static class NthHopVertex extends Vertex<Text,NullWritable,HopMessage> {

    @Override
    public void compute(Iterable<HopMessage> messages) throws IOException {
      if (getSuperstepCount() == 0L) {
        HopMessage msg = new HopMessage();
        msg.origin = getVertexID().toString();
        msg.hopCounter = 0;
        sendMessagetoNeighbors(msg);
      } else {
        for (HopMessage message : messages) {
          message.hopCounter += 1;
          if (message.hopCounter == 3) {
            getPeer().write(new Text(message.origin),getVertexID());
            VoteToHalt();
          } else {
            sendMessagetoNeighbors(message);
          }

        }
      }
    }
  }

BTW在您的示例中创建的新图形如下所示:

1=[1,6]
2=[2,3,6]
3=[2,6]
4=[4,5]

以下是完整的Hama Graph实现:

https://github.com/thomasjungblut/tjungblut-graph/blob/master/src/de/jungblut/graph/bsp/NthHop.java

java – Hadoop Map Reduce For Google web graph的更多相关文章

  1. 用Swift实现MD5算法&amp;引入第三方类库MBProgressHUD

    之前项目里面是用objc写的MD5加密算法,最近在用swift重写以前的项目,遇到了这个问题。顺带解决掉的还有如何引入第三方的类库,例如MBProgressHUD等一些特别好的控件解决的方法其实是用objc和swift混合编程的方法,利用Bridging-header文件。你可以简单的理解为在一个用swift语言开发的工程中,引入objective-c文件是需要做的一个串联文件,好比架设了一个桥,让swift中也可以调用objective-c的类库和frame等等。

  2. swift排序算法和数据结构

    vararrayNumber:[Int]=[2,4,216)">6,216)">7,216)">3,216)">8,216)">1]//冒泡排序funcmaopao->[Int]{forvari=0;i

  3. swift - 函数指针的应用 - 避免重复算法

    =nil;})}privatefuncsearch(selector:(Employee->Bool))->[Employee]{varresults=[Employee]();foreinemployees{if(selector(e)){results.append(e);}}returnresults;}}

  4. 如何用 Swift 实现 A* 寻路算法

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  5. swift算法实践1

    在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,所以,这种表示法也称为中缀表示。波兰逻辑学家J.Lukasiewicz于1929年提出了另一种表示表达式的方法。逆波兰表达式,它的语法规定,表达式必须以逆波兰表达式的方式给出。如果,该字符优先关系高于此运算符栈顶的运算符,则将该运算符入栈。倘若不是的话,则将栈顶的运算符从栈中弹出,直到栈顶运算符的优先级低于当前运算符,将该字符入栈。

  6. swift算法实践2

    字符串hash算法Time33在效率和随机性两方面上俱佳。对于一个Hash函数,评价其优劣的标准应为随机性,即对任意一组标本,进入Hash表每一个单元之概率的平均程度,因为这个概率越平均,数据在表中的分布就越平均,表的空间利用率就越高。Times33的算法很简单,就是不断的乘33,见下面算法原型。

  7. swift算法实践3)-KMP算法字符串匹配

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  8. swift算法实践4)-trie自动机

    1、trie自动机是识别字符串的确定性有向无环自动机2、图示3、构造代码F包括了状态q所对应的P中的字符串

  9. Swift 算法实战之路一

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

  10. Swift 算法实战之路二

    本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请发送邮件至dio@foxmail.com举报,一经查实,本站将立刻删除。

随机推荐

  1. 基于EJB技术的商务预订系统的开发

    用EJB结构开发的应用程序是可伸缩的、事务型的、多用户安全的。总的来说,EJB是一个组件事务监控的标准服务器端的组件模型。基于EJB技术的系统结构模型EJB结构是一个服务端组件结构,是一个层次性结构,其结构模型如图1所示。图2:商务预订系统的构架EntityBean是为了现实世界的对象建造的模型,这些对象通常是数据库的一些持久记录。

  2. Java利用POI实现导入导出Excel表格

    这篇文章主要为大家详细介绍了Java利用POI实现导入导出Excel表格,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

  3. Mybatis分页插件PageHelper手写实现示例

    这篇文章主要为大家介绍了Mybatis分页插件PageHelper手写实现示例,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  4. (jsp/html)网页上嵌入播放器(常用播放器代码整理)

    网页上嵌入播放器,只要在HTML上添加以上代码就OK了,下面整理了一些常用的播放器代码,总有一款适合你,感兴趣的朋友可以参考下哈,希望对你有所帮助

  5. Java 阻塞队列BlockingQueue详解

    本文详细介绍了BlockingQueue家庭中的所有成员,包括他们各自的功能以及常见使用场景,通过实例代码介绍了Java 阻塞队列BlockingQueue的相关知识,需要的朋友可以参考下

  6. Java异常Exception详细讲解

    异常就是不正常,比如当我们身体出现了异常我们会根据身体情况选择喝开水、吃药、看病、等 异常处理方法。 java异常处理机制是我们java语言使用异常处理机制为程序提供了错误处理的能力,程序出现的错误,程序可以安全的退出,以保证程序正常的运行等

  7. Java Bean 作用域及它的几种类型介绍

    这篇文章主要介绍了Java Bean作用域及它的几种类型介绍,Spring框架作为一个管理Bean的IoC容器,那么Bean自然是Spring中的重要资源了,那Bean的作用域又是什么,接下来我们一起进入文章详细学习吧

  8. 面试突击之跨域问题的解决方案详解

    跨域问题本质是浏览器的一种保护机制,它的初衷是为了保证用户的安全,防止恶意网站窃取数据。那怎么解决这个问题呢?接下来我们一起来看

  9. Mybatis-Plus接口BaseMapper与Services使用详解

    这篇文章主要为大家介绍了Mybatis-Plus接口BaseMapper与Services使用详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪

  10. mybatis-plus雪花算法增强idworker的实现

    今天聊聊在mybatis-plus中引入分布式ID生成框架idworker,进一步增强实现生成分布式唯一ID,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

返回
顶部