Java,使用Jung包读取GraphML数据

最近在做一个Project,跟微博啥的有关,肉壳的工作就是给微博用户打分,看谁最重要,基本上就是简单的修改了一下Page Rank算法和HITS算法。不过第一步就是要把搭档给我的数据读出来。因为都是用户关系用网络表示,为了方便处理,前期操作都是把数据写在GraphML格式文件中。GraphML也是一种标记语言,跟HTML,XML什么的差不多,里面都是一些标签。有兴趣的话,大家自己Google一下就可以了……

搭档们用的都是R和Python,里面有包可以直接读GraphML,但是木讷的我不会用R和Python,只能在Java里找相关的包,结果还真找到一个叫Jung的包。这个包功能非常强大,可以对GraphML增删改查,还可以计算网络的PR,HITS什么的,可谓非常强大……不过今天就讲一些简单的,就是如何将GraphML文件中的数据读出来,就是这么简单……

首先,我们看一下GraphML的文件格式,

<graphml xmlns="http://graphml.graphdrawing.org/xmlns"  xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://graphml.graphdrawing.org/xmlns http://graphml.graphdrawing.org/xmlns/1.0/graphml.xsd">
  <key id="d0" for="node" attr.name="color" attr.type="string">
    <default>yellow</default>
  </key>
  <key id="d1" for="edge" attr.name="weight" attr.type="double">
	<default>0.0</default>
  </key>
  <graph id="G" edgedefault="directed">
    <node id="n0">
      <data key="d0">green</data>
    </node>
    <node id="n1"/>
    <node id="n2">
      <data key="d0">blue</data>
    </node>
    <node id="n3">
      <data key="d0">red</data>
    </node>
    <node id="n4"/>
    <node id="n5">
      <data key="d0">turquoise</data>
    </node>
    <edge id="e0" source="n0" target="n2">
      <data key="d1">1.0</data>
    </edge>
    <edge id="e1" source="n0" target="n1">
      <data key="d1">1.0</data>
    </edge>
    <edge id="e2" source="n1" target="n3">
      <data key="d1">2.0</data>
    </edge>
    <edge id="e3" source="n3" target="n2"/>
    <edge id="e4" source="n2" target="n4"/>
    <edge id="e5" source="n3" target="n5"/>
    <edge id="e6" source="n5" target="n4">
      <data key="d1">1.1</data>
    </edge>
  </graph>
</graphml>

首先,key标签定义了Vertex和Edge的meta信息,以便以后获取到这些信息后将他们读出来。<graph id=”G” edgedefault=”directed”>定义里这个图是个有向图,不过我代码里用的是个无向图(undirected),大家使用的时候需要注意一下。之后运行一下下面的代码就好了。

GraphMLReader<undirectedgraph, Node, Edge> gmlr = new GraphMLReader<undirectedgraph, Node, Edge>(new VertexFactory(), new EdgeFactory()); //创建一个GrahpML的Reader
final UndirectedGraph graph = new UndirectedSparseMultigraph();

gmlr.load(filename, graph); //读取graph,并将内容写进graph对象

BidiMap vertex_ids = gmlr.getVertexIDs(); //获取Vertex的id
<Map> edge_meta = gmlr.getEdgeMetadata(); //获取Edge的内容

//graph对象此时只有Vertex和边的连接关系,我们需要把Vertex和Edge的附加信息写进去
for (Node n : graph.getVertices()) {
	n.setUserID(vertex_ids.get(n));
	n.setPageRank(0.2);
	n.setAuth(1);
	n.setHub(1);
}
for (Edge e : graph.getEdges()) {
	e.setCapacity(Double.parseDouble(edge_meta.get("d1").transformer.transform(e))); //读取的d2信息是在GraphML文件里定义的
}

经过这么一番简单操作,graph对象就已经包含了各个Vertex和Edge的关系了……就是这么简单……Vertex和Edge对象是自己写的,下面再贴个NodeFactory和EdgeFactory的代码。

class VertexFactory implements Factory {
	private int n = 0;

	public Node create() {
		return (new Node(n++));
	}
}

class EdgeFactory implements Factory {
	private int e = 0;

	public Edge create() {
		return (new Edge(e++));
	}
}

需要注意的时候,无向图读取以后,不知道是不是因为我不会用,每条Edge的from和target读不出来,用有向图就能读出来,好奇怪……不过大家到也不用担心,因为graph有个方法叫getEndpoints,可以获取到特定边的两个顶点,然后再操作就可以了……

另外,最近在研究GitHub,虽然早就注册了,但是一直没用过……现在想想,太狗了……