图形从单个顶点到N个顶点

时间:2015-11-26 11:05:15

标签: java traversal titan tinkerpop

我有以下示例图:

Graph

我的根节点为LVMap<Vertex, Vertex>包含:

Map = {<A_T, A_V>, <B_T, B_V>, <C_T, C_V>, ... <N_T, N_V>}

我正在尝试创建一个从LV开始的遍历并转到每个离开A_T, A_V, B_T, B_V, C_T, C_V。最初我正在考虑构建我的遍历:

GraphTraversal traversal = graph().traversal().V(LV.id());
traversal.and(out().hasId(A_T.id(), A_V.id()),
              out().hasId(B_T.id(), B_V.id()),
              out().hasId(C_T.id(), C_V.id()),
              ...
              out().hasId(N_T.id(), N_V.id()));

问题是.and(Object . . .)无法动态添加(如我所知),N可能是任何数字,所以有一次我想要:

traversal.and(out().hasId(A_T.id(), A_V.id()),
              out().hasId(B_T.id(), B_V.id());

在另一个我想要的地方:

traversal.and(out().hasId(A_T.id(), A_V.id()),
              out().hasId(B_T.id(), B_V.id()),
              out().hasId(C_T.id(), C_V.id()),
              out().hasId(D_T.id(), D_V.id()));

此遍历应该用作LVMap中所有组件之间现有结构的验证。

有没有办法实现这项功能?

2 个答案:

答案 0 :(得分:2)

让我们先创建示例图和地图:

# Setup
heroku plugins:install https://github.com/heroku/heroku-oauth
heroku authorizations:create -s write
heroku config:add RESTART_API_KEY=<API KEY>
heroku config:add APP_NAME=<App Name>

heroku addons:add scheduler:standard -a <App Name>
heroku addons:open scheduler -a <App Name>
add `rake restart`

# Gemfile
gem 'platform-api', require: false

# Rakefile
task :restart do
  require 'platform-api'
  app_name = ENV.fetch('APP_NAME')
  key = ENV.fetch('RESTART_API_KEY')
  connection = PlatformAPI.connect_oauth(key)
  connection.dyno.list(app_name).map do |info|
    if info['type'] == 'web' && info['state'] == 'up'
      puts "Restarting #{info.inspect}"
      connection.dyno.restart(app_name, info['name'])
    else
      puts "Skipping #{info.inspect}"
    end
  end
end

现在,要弄清楚是否可以找到结构,你可以这样做:

graph = TinkerGraph.open()
names = ["LV",
         "A_C","A_T","A_V",
         "B_C","B_T","B_V",
         "C_C","C_T","C_V"]

vertices = names.collectEntries { def name ->
  [name, graph.addVertex("name", name)]
}

vertices["LV"].addEdge("link", vertices["A_C"])
vertices["LV"].addEdge("link", vertices["B_C"])
vertices["LV"].addEdge("link", vertices["C_C"])
vertices["A_C"].addEdge("link", vertices["A_T"])
vertices["A_C"].addEdge("link", vertices["A_V"])
vertices["B_C"].addEdge("link", vertices["B_T"])
vertices["B_C"].addEdge("link", vertices["B_V"])
vertices["C_C"].addEdge("link", vertices["C_T"])
vertices["C_C"].addEdge("link", vertices["C_V"])

m = [:]
m.put(vertices["A_T"], vertices["A_V"])
m.put(vertices["B_T"], vertices["B_V"])
m.put(vertices["C_T"], vertices["C_V"])

这是Gremlin控制台的结果:

leafs = m.keySet() + m.values()

g = graph.traversal()
found = g.V(vertices["LV"]).out().out().fold().
          where(count(local).is(m.size() << 1)).
          not(unfold().is(without(leafs))).hasNext()

如果我们在地图上添加一些项目,那么这不是结构的一部分:

gremlin> found = g.V(vertices["LV"]).out().out().fold().
gremlin>           where(count(local).is(m.size() << 1)).
gremlin>           not(unfold().is(without(leafs))).hasNext()
==>true

答案 1 :(得分:0)

解决了它。一如既往,我会为可能遇到类似问题的人发布我的解决方案。

问题是and(...)方法可以采用多个参数。所以我可以动态构造最终的遍历。具体来说,我可以做到以下几点。

public void awesomeTraversal(Vertex LV, Map<Vertex, Vertex> vertexMap){
    GraphTraversal<Vertex, Vertex> traversal = graph.traversal().V(LV.id()); //Start at LV

    ArrayList<GraphTraversal> innerTraversals = new ArrayList<>();
    for(Map.Entry<Vertex, Vertex> v : vertexMap){
        // Check you can go to X_T
        innerTraversals.add(__.out().out().is(entry.getKey())); 
        //Check you can go to X_V
        innerTraversals.add(__.out().out().is(entry.getValue()));
    }
    //Filter via and.
    traversal = traversal.and(innerTraversal.toArray(GraphTraversal[innerTraversals.size()]));
    if(traversal.hasNext()){
        System.out.println("Found structure");
    } else {
        System.out.println("No structure");
    }
}

这似乎对我有用。任何改进都将非常受欢迎。