From b55077ac715bbeeeaba2f140150b3b58c4ce80fa Mon Sep 17 00:00:00 2001 From: platypus0127 Date: Tue, 19 Mar 2019 17:25:29 +0800 Subject: [PATCH 1/6] Create ShortestPathAPINew MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 超级节点的边数。与原来的ShortestPathAPI 相比添加了int 参数,这个参数限定了定点的最大边数量,避免了查询的时候经过超级节点。 --- .../api/traversers/ShortestPathAPINew | 81 +++++++++++++++++++ 1 file changed, 81 insertions(+) create mode 100644 hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew new file mode 100644 index 0000000000..a604c9af8c --- /dev/null +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew @@ -0,0 +1,81 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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. + */ + +package com.baidu.hugegraph.api.traversers; + +import com.baidu.hugegraph.HugeGraph; +import com.baidu.hugegraph.api.API; +import com.baidu.hugegraph.api.graph.EdgeAPI; +import com.baidu.hugegraph.api.graph.VertexAPI; +import com.baidu.hugegraph.backend.id.Id; +import com.baidu.hugegraph.core.GraphManager; +import com.baidu.hugegraph.server.RestServer; +import com.baidu.hugegraph.traversal.algorithm.ShortestPathTraverserNew1; +import com.baidu.hugegraph.type.define.Directions; +import com.baidu.hugegraph.util.Log; +import com.codahale.metrics.annotation.Timed; +import org.slf4j.Logger; + +import javax.inject.Singleton; +import javax.ws.rs.*; +import javax.ws.rs.core.Context; +import java.util.List; + +import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_CAPACITY; +import static com.baidu.hugegraph.traversal.algorithm.HugeTraverser.DEFAULT_DEGREE; + +@Path("graphs/{graph}/traversers/shortestpath") +@Singleton +public class ShortestPathAPINew extends API { + + private static final Logger LOG = Log.logger(RestServer.class); + + @GET + @Timed + @Produces(APPLICATION_JSON_WITH_CHARSET) + public String get(@Context GraphManager manager, + @PathParam("graph") String graph, + @QueryParam("source") String source, + @QueryParam("target") String target, + @QueryParam("direction") String direction, + @QueryParam("label") String edgeLabel, + @QueryParam("max_depth") int depth, + @QueryParam("max_path") int max_edges, //超级节点范围。某个节点的边数量大于这个值则为超级节点 + @QueryParam("max_degree") + @DefaultValue(DEFAULT_DEGREE) long degree, + @QueryParam("capacity") + @DefaultValue(DEFAULT_CAPACITY) long capacity) { + LOG.debug("Graph [{}] get shortest path from '{}', to '{}' with " + + "direction {}, edge label {}, max depth '{}', " + + "max degree '{}' and capacity '{}'", + graph, source, target, direction, edgeLabel, depth, + degree, capacity); + + Id sourceId = VertexAPI.checkAndParseVertexId(source); + Id targetId = VertexAPI.checkAndParseVertexId(target); + Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); + + HugeGraph g = graph(manager, graph); + ShortestPathTraverserNew1 traverser = new ShortestPathTraverserNew1(g); + List path = traverser.shortestPath(sourceId, targetId, dir, + edgeLabel, depth,max_edges, degree, + capacity); + return manager.serializer(g).writeIds("path", path); + } +} From b47f38b8fea6ad61af8a57a69a66f5390cc31334 Mon Sep 17 00:00:00 2001 From: platypus0127 Date: Tue, 19 Mar 2019 17:28:24 +0800 Subject: [PATCH 2/6] Create ShortestPathTraverserNew.java MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 超级节点的边数。与原来的ShortestPathAPI 相比添加了int 参数,这个参数限定了定点的最大边数量,避免了查询的时候经过超级节点。 --- .../algorithm/ShortestPathTraverserNew.java | 187 ++++++++++++++++++ 1 file changed, 187 insertions(+) create mode 100644 hugegraph-core/src/main/java/com/baidu/hugegraph/traversal/algorithm/ShortestPathTraverserNew.java diff --git a/hugegraph-core/src/main/java/com/baidu/hugegraph/traversal/algorithm/ShortestPathTraverserNew.java b/hugegraph-core/src/main/java/com/baidu/hugegraph/traversal/algorithm/ShortestPathTraverserNew.java new file mode 100644 index 0000000000..fd5a11781c --- /dev/null +++ b/hugegraph-core/src/main/java/com/baidu/hugegraph/traversal/algorithm/ShortestPathTraverserNew.java @@ -0,0 +1,187 @@ +/* + * Copyright 2017 HugeGraph Authors + * + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with this + * work for additional information regarding copyright ownership. The ASF + * licenses this file to You 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. + */ + +package com.baidu.hugegraph.traversal.algorithm; + +import java.util.Collections; +import java.util.Iterator; +import java.util.List; +import java.util.Map; + +import org.apache.tinkerpop.gremlin.structure.Edge; + +import com.baidu.hugegraph.HugeGraph; +import com.baidu.hugegraph.backend.id.Id; +import com.baidu.hugegraph.structure.HugeEdge; +import com.baidu.hugegraph.type.define.Directions; +import com.baidu.hugegraph.util.E; +import com.google.common.collect.ImmutableList; + +public class ShortestPathTraverserNew extends HugeTraverser { + + public ShortestPathTraverserNew(HugeGraph graph) { + super(graph); + } + + public List shortestPath(Id sourceV, Id targetV, Directions dir, + String label, int depth,int max_edges, long degree, + long capacity) { + E.checkNotNull(sourceV, "source vertex id"); + E.checkNotNull(targetV, "target vertex id"); + E.checkNotNull(dir, "direction"); + checkPositive(depth, "max depth"); + checkDegree(degree); + checkCapacity(capacity); + + if (sourceV.equals(targetV)) { + return ImmutableList.of(sourceV); + } + + Id labelId = this.getEdgeLabelId(label); + Traverser traverser = new Traverser(sourceV, targetV, dir, labelId,max_edges, + degree, capacity); + List path; + while (true) { + // Found, reach max depth or reach capacity, stop searching + if ((path = traverser.forward()) != PATH_NONE || --depth <= 0) { + break; + } + checkCapacity(traverser.capacity, traverser.size, "shortest path"); + + if ((path = traverser.backward()) != PATH_NONE || --depth <= 0) { + Collections.reverse(path); + break; + } + checkCapacity(traverser.capacity, traverser.size, "shortest path"); + } + return path; + } + + private class Traverser { + + // TODO: change Map to Set to reduce memory cost + private Map sources = newMap(); + private Map targets = newMap(); + + private final Directions direction; + private final Id label; + private final long degree; + private final long capacity; + private long size; + private final int max_edges; + + public Traverser(Id sourceV, Id targetV, Directions dir, + Id label,int max_edges, long degree, long capacity) { + this.sources.put(sourceV, new Node(sourceV)); + this.targets.put(targetV, new Node(targetV)); + this.direction = dir; + this.label = label; + this.degree = degree; + this.capacity = capacity; + this.size = 0L; + this.max_edges=max_edges; + } + + /** + * Search forward from source + */ + public List forward() { + Map newVertices = newMap(); + // Traversal vertices of previous level + for (Node v : this.sources.values()) { + //TODO 判断是否为超级节点,如当前节点边的数量大于1000,就不经过滤当前点 + if(v.path().size()< max_edges) { + Iterator edges = edgesOfVertex(v.id(), this.direction, + this.label, this.degree); + while (edges.hasNext()) { + HugeEdge edge = (HugeEdge) edges.next(); + Id target = edge.id().otherVertexId(); + + // If cross point exists, shortest path found, concat them + if (this.targets.containsKey(target)) { + return v.joinPath(this.targets.get(target)); + } + + /* + * Not found shortest path yet, node is added to + * newVertices if: + * 1. not in sources and newVertices yet + * 2. path of node doesn't have loop + */ + if (!newVertices.containsKey(target) && + !this.sources.containsKey(target) && + !v.contains(target)) { + newVertices.put(target, new Node(target, v)); + } + } + } + } + + // Re-init sources + this.sources = newVertices; + this.size += newVertices.size(); + + return PATH_NONE; + } + + /** + * Search backward from target + */ + public List backward() { + Map newVertices = newMap(); + Directions opposite = this.direction.opposite(); + // Traversal vertices of previous level + for (Node v : this.targets.values()) { + //TODO 判断是否为超级节点,如当前节点边的数量大于1000,就不经过滤当前点 + if(v.path().size()< max_edges) { + + Iterator edges = edgesOfVertex(v.id(), opposite, + this.label, this.degree); + while (edges.hasNext()) { + HugeEdge edge = (HugeEdge) edges.next(); + Id target = edge.id().otherVertexId(); + + // If cross point exists, shortest path found, concat them + if (this.sources.containsKey(target)) { + return v.joinPath(this.sources.get(target)); + } + + /* + * Not found shortest path yet, node is added to + * newVertices if: + * 1. not in targets and newVertices yet + * 2. path of node doesn't have loop + */ + if (!newVertices.containsKey(target) && + !this.targets.containsKey(target) && + !v.contains(target)) { + newVertices.put(target, new Node(target, v)); + } + } + } + } + + // Re-init targets + this.targets = newVertices; + this.size += newVertices.size(); + + return PATH_NONE; + } + } +} From 9ae017d1ed746d2ffea2ab4244217b0d384bfd61 Mon Sep 17 00:00:00 2001 From: platypus0127 Date: Tue, 19 Mar 2019 17:29:26 +0800 Subject: [PATCH 3/6] Rename ShortestPathAPINew to ShortestPathAPINew.java --- .../traversers/{ShortestPathAPINew => ShortestPathAPINew.java} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/{ShortestPathAPINew => ShortestPathAPINew.java} (100%) diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java similarity index 100% rename from hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew rename to hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java From 7a7bab6ea8db167a6808801ae0896e7464181838 Mon Sep 17 00:00:00 2001 From: platypus0127 Date: Tue, 19 Mar 2019 17:38:56 +0800 Subject: [PATCH 4/6] Update ShortestPathAPINew.java --- .../com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java index a604c9af8c..7bcc0c4da4 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java @@ -74,7 +74,7 @@ public String get(@Context GraphManager manager, HugeGraph g = graph(manager, graph); ShortestPathTraverserNew1 traverser = new ShortestPathTraverserNew1(g); List path = traverser.shortestPath(sourceId, targetId, dir, - edgeLabel, depth,max_edges, degree, + edgeLabel, depth,max_edges, degree // max_edges超级节点的边数。 capacity); return manager.serializer(g).writeIds("path", path); } From ea8c656b52f646cd8135c7460a1d75449134927d Mon Sep 17 00:00:00 2001 From: platypus0127 Date: Tue, 19 Mar 2019 17:39:39 +0800 Subject: [PATCH 5/6] Update ShortestPathAPINew.java --- .../com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java index 7bcc0c4da4..497a55ca1c 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java @@ -74,7 +74,7 @@ public String get(@Context GraphManager manager, HugeGraph g = graph(manager, graph); ShortestPathTraverserNew1 traverser = new ShortestPathTraverserNew1(g); List path = traverser.shortestPath(sourceId, targetId, dir, - edgeLabel, depth,max_edges, degree // max_edges超级节点的边数。 + edgeLabel, depth,max_edges, degree, // max_edges超级节点的边数。 capacity); return manager.serializer(g).writeIds("path", path); } From 6a45d762e8c78ecbe015271decea91bf0dd776ec Mon Sep 17 00:00:00 2001 From: platypus0127 Date: Tue, 19 Mar 2019 18:36:14 +0800 Subject: [PATCH 6/6] Update ShortestPathAPINew.java --- .../com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java index 497a55ca1c..aa5328100b 100644 --- a/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java +++ b/hugegraph-api/src/main/java/com/baidu/hugegraph/api/traversers/ShortestPathAPINew.java @@ -72,7 +72,7 @@ public String get(@Context GraphManager manager, Directions dir = Directions.convert(EdgeAPI.parseDirection(direction)); HugeGraph g = graph(manager, graph); - ShortestPathTraverserNew1 traverser = new ShortestPathTraverserNew1(g); + ShortestPathTraverserNew traverser = new ShortestPathTraverserNew(g); List path = traverser.shortestPath(sourceId, targetId, dir, edgeLabel, depth,max_edges, degree, // max_edges超级节点的边数。 capacity);