谁能解释Boost使用的GraphML格式?它包括其他GraphML编写者不使用的间接级别。我包括了来自2个源的GraphML输出,这两个源均来自相同的输入数据。我不明白为什么Boost会在'key [0-N]'关键字中使用额外级别的间接访问。任何令人信服的解释都将受到赞赏。
我正在寻找一种配置Boost的方式来产生与Java / Tinkerpop产生的输出相似或相同的输出,如下面的第一个示例所示。我想消除'key [0-N]'间接。
首先,这是使用TinkerPop图形库的Java程序产生的输出:
<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.1/graphml.xsd">
<key id="UnitName" for="node" attr.name="UnitName" attr.type="string" />
<key id="id" for="node" attr.name="id" attr.type="int" />
<key id="labelV" for="node" attr.name="labelV" attr.type="string" />
<key id="EdgeName" for="edge" attr.name="EdgeName" attr.type="string" />
<key id="labelE" for="edge" attr.name="labelE" attr.type="string" />
<key id="length" for="edge" attr.name="length" attr.type="long" />
<key id="sourceport" for="edge" attr.name="sourceport" attr.type="string" />
<key id="targetport" for="edge" attr.name="targetport" attr.type="string" />
<graph id="G" edgedefault="directed">
<node id="n0">
<data key="labelV">vertex</data>
<data key="UnitName">Div:101</data>
<data key="id">101</data>
</node>
<node id="n1">
<data key="labelV">vertex</data>
<data key="UnitName">Blow:1</data>
<data key="id">1</data>
</node>
<node id="n2">
<data key="labelV">vertex</data>
<data key="UnitName">Div:201</data>
<data key="id">201</data>
</node>
<node id="n3">
<data key="labelV">vertex</data>
<data key="UnitName">Blow:2</data>
<data key="id">2</data>
</node>
<node id="n4">
<data key="labelV">vertex</data>
<data key="UnitName">Sta:10 Sta10</data>
<data key="id">10</data>
</node>
<node id="n5">
<data key="labelV">vertex</data>
<data key="UnitName">Sta:11 Sta11</data>
<data key="id">11</data>
</node>
<node id="n6">
<data key="labelV">vertex</data>
<data key="UnitName">IZ:1002</data>
<data key="id">1002</data>
</node>
<node id="n7">
<data key="labelV">vertex</data>
<data key="UnitName">Sta:20</data>
<data key="id">20</data>
</node>
<node id="n8">
<data key="labelV">vertex</data>
<data key="UnitName">Sta:21</data>
<data key="id">21</data>
</node>
<edge id="e0" source="n0" target="n4">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Div:101 to Sta:10 Sta10</data>
<data key="length">80</data>
<data key="sourceport">0</data>
<data key="targetport"></data>
</edge>
<edge id="e1" source="n0" target="n5">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Div:101 to Sta:11 Sta11</data>
<data key="length">80</data>
<data key="sourceport">1</data>
<data key="targetport"></data>
</edge>
<edge id="e2" source="n0" target="n6">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Div:101 to IZ:1002</data>
<data key="length">20</data>
<data key="sourceport">3</data>
<data key="targetport"></data>
</edge>
<edge id="e3" source="n1" target="n0">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Blow:1 to Div:101</data>
<data key="length">0</data>
<data key="sourceport"></data>
<data key="targetport"></data>
</edge>
<edge id="e4" source="n2" target="n7">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Div:201 to Sta:20</data>
<data key="length">80</data>
<data key="sourceport">0</data>
<data key="targetport"></data>
</edge>
<edge id="e5" source="n2" target="n8">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Div:201 to Sta:21</data>
<data key="length">80</data>
<data key="sourceport">1</data>
<data key="targetport"></data>
</edge>
<edge id="e6" source="n2" target="n6">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Div:201 to IZ:1002</data>
<data key="length">20</data>
<data key="sourceport">3</data>
<data key="targetport"></data>
</edge>
<edge id="e7" source="n3" target="n2">
<data key="labelE">edge</data>
<data key="EdgeName">Edge from Blow:2 to Div:201</data>
<data key="length">0</data>
<data key="sourceport"></data>
<data key="targetport"></data>
</edge>
</graph>
</graphml>
这是当我使用Boost Graph库中的C++ write_graphml()函数时出现的相同数据:
<?xml version="1.0" encoding="UTF-8"?>
<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="key0" for="edge" attr.name="EdgeName" attr.type="string" />
<key id="key1" for="node" attr.name="UnitName" attr.type="string" />
<key id="key2" for="node" attr.name="id" attr.type="int" />
<key id="key3" for="edge" attr.name="length" attr.type="long" />
<key id="key4" for="edge" attr.name="sourceport" attr.type="string" />
<key id="key5" for="edge" attr.name="targetport" attr.type="string" />
<graph id="G" edgedefault="directed" parse.nodeids="free" parse.edgeids="canonical" parse.order="nodesfirst">
<node id="n0">
<data key="key1">Div:101</data>
<data key="key2">101</data>
</node>
<node id="n1">
<data key="key1">Blow:1</data>
<data key="key2">1</data>
</node>
<node id="n2">
<data key="key1">Sta:20</data>
<data key="key2">20</data>
</node>
<node id="n3">
<data key="key1">Div:201</data>
<data key="key2">201</data>
</node>
<node id="n4">
<data key="key1">Sta:21</data>
<data key="key2">21</data>
</node>
<node id="n5">
<data key="key1">Zn:1====Zn:2:1002</data>
<data key="key2">1002</data>
</node>
<node id="n6">
<data key="key1">Sta:10 Sta10</data>
<data key="key2">10</data>
</node>
<node id="n7">
<data key="key1">Sta:11 Sta11</data>
<data key="key2">11</data>
</node>
<node id="n8">
<data key="key1">Blow:2</data>
<data key="key2">2</data>
</node>
<edge id="e0" source="n0" target="n6">
<data key="key0">Edge from Div:101 to Sta:10 Sta10</data>
<data key="key3">80</data>
<data key="key4">0</data>
<data key="key5"></data>
</edge>
<edge id="e1" source="n0" target="n7">
<data key="key0">Edge from Div:101 to Sta:11 Sta11</data>
<data key="key3">80</data>
<data key="key4">1</data>
<data key="key5"></data>
</edge>
<edge id="e2" source="n0" target="n5">
<data key="key0">Edge from Div:101 to Zn:1====Zn:2:1002</data>
<data key="key3">20</data>
<data key="key4">3</data>
<data key="key5"></data>
</edge>
<edge id="e3" source="n1" target="n0">
<data key="key0">Edge from Blow:1 to Div:101</data>
<data key="key3">0</data>
<data key="key4"></data>
<data key="key5"></data>
</edge>
<edge id="e4" source="n3" target="n2">
<data key="key0">Edge from Div:201 to Sta:20</data>
<data key="key3">80</data>
<data key="key4">0</data>
<data key="key5"></data>
</edge>
<edge id="e5" source="n3" target="n4">
<data key="key0">Edge from Div:201 to Sta:21</data>
<data key="key3">80</data>
<data key="key4">1</data>
<data key="key5"></data>
</edge>
<edge id="e6" source="n3" target="n5">
<data key="key0">Edge from Div:201 to Zn:1====Zn:2:1002</data>
<data key="key3">20</data>
<data key="key4">3</data>
<data key="key5"></data>
</edge>
<edge id="e7" source="n8" target="n3">
<data key="key0">Edge from Blow:2 to Div:201</data>
<data key="key3">0</data>
<data key="key4"></data>
<data key="key5"></data>
</edge>
</graph>
</graphml>
我们在两个应用程序之间存在冲突。 Boost应用程序最初会导出GraphML。另一个应用程序使用JanusGraph / Gremlin / Tinkerpop加载GraphML作为输入并创建图。即使GraphML在语法上是正确的,但JanusGraph / Tinkerpop在读取GraphML时也会引发异常:
java.lang.IllegalArgumentException: Name cannot be in protected namespace: edge
at org.janusgraph.graphdb.types.system.SystemTypeManager.isNotSystemName(SystemTypeManager.java:72)
at org.janusgraph.graphdb.types.StandardRelationTypeMaker.name(StandardRelationTypeMaker.java:188)
at org.janusgraph.graphdb.types.StandardRelationTypeMaker.<init>(StandardRelationTypeMaker.java:57)
at org.janusgraph.graphdb.types.StandardEdgeLabelMaker.<init>(StandardEdgeLabelMaker.java:42)
at org.janusgraph.graphdb.transaction.StandardJanusGraphTx.makeEdgeLabel(StandardJanusGraphTx.java:980)
at org.janusgraph.graphdb.transaction.StandardJanusGraphTx.getOrCreateEdgeLabel(StandardJanusGraphTx.java:965)
at org.janusgraph.graphdb.vertices.AbstractVertex.addEdge(AbstractVertex.java:163)
at org.janusgraph.graphdb.vertices.AbstractVertex.addEdge(AbstractVertex.java:37)
at org.apache.tinkerpop.gremlin.structure.io.graphml.GraphMLReader.readGraph(GraphMLReader.java:191)
我发现可以通过编辑GraphML并在key0上进行全局搜索/替换并将其替换为labelE来解决此问题。我不完全确定为什么这样做,显然我正在尝试避免此步骤,因此我们的第一个想法是让Boost将该字段导出为“labelE”而不是“key0”。
相关说明,如果我使用内存中的Tinkergraph,Tinkerpop可以很好地加载原始GraphML。仅当我将JanusGraph用作基础数据库时才会发生该异常。
最佳答案
你让自己感到困惑。 TinkerPop输出具有完全相同的间接级别。唯一的区别是TinkerPop决定知道节点和边缘数据密钥的ID相同。
读取XML的工具没有任何区别。
实际上,即使是以下情况也将是等效的:
<graphml>
<key id="UnitName" for="node" attr.name="UnitName" attr.type="string" />
<key id="labelV" for="node" attr.name="labelV" attr.type="string" />
<graph id="G" edgedefault="directed">
<node id="n0">
<data key="labelV">vertex</data>
<data key="UnitName">Div:101</data>
</node>
<node id="n1">
<data key="labelV">vertex</data>
<data key="UnitName">Blow:1</data>
</node>
</graph>
</graphml>
两者之间没有区别:
<graphml>
<key id="labelV" for="node" attr.name="UnitName" attr.type="string" />
<key id="UnitName" for="node" attr.name="labelV" attr.type="string" />
<graph id="G" edgedefault="directed">
<node id="n0">
<data key="UnitName">vertex</data>
<data key="labelV">Div:101</data>
</node>
<node id="n1">
<data key="UnitName">vertex</data>
<data key="labelV">Blow:1</data>
</node>
</graph>
</graphml>
是的,对于人类而言,阅读该XML会令人困惑,但人类却不会阅读该XML。
您确实必须问自己,为什么指定的这些详细信息与不相关对您来说很重要,这对您来说很重要。最有可能的甚至不是这种情况。
当然,如果读取XML的工具是基于错误的假设(也就是“有错误”)编写的,那么您可能会处于困境。我建议先解决该问题。
否则,您可以尝试破解GraphML编写器以不使用自动生成的键ID。这不会太难,但是确实会带来麻烦(例如,当edge / node属性之间存在名称类时)。
关于c++ - Boost GraphML格式,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/49740173/