You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2016/02/18 19:44:09 UTC
incubator-tinkerpop git commit: added the concept of initialRank to
PageRankVertexProgram. The initialRank of a vertex is determined by a
Traversal. What is sweet,
in the context of multi-OLAP traversals --- g.V().has('name', 'marko').pageR
Repository: incubator-tinkerpop
Updated Branches:
refs/heads/TINKERPOP-1154 0192240ea -> cb4df815a
added the concept of initialRank to PageRankVertexProgram. The initialRank of a vertex is determined by a Traversal<Vertex,Double>. What is sweet, in the context of multi-OLAP traversals --- g.V().has('name','marko').pageRank(), the initialRank is determined by HaltedTraversersCountTraversal which simply determines the size of the HALTED_TRAVERSERS at that vertex. Thus, marko gets an initial rank of 1 and every other vertex 0. Created a CRAZY long, complex PageRankTest traversal to validate the behavior.
Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/cb4df815
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/cb4df815
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/cb4df815
Branch: refs/heads/TINKERPOP-1154
Commit: cb4df815a2ba8a78bb3e50234c79ba497c07521f
Parents: 0192240
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Thu Feb 18 11:43:58 2016 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Thu Feb 18 11:43:58 2016 -0700
----------------------------------------------------------------------
.../ranking/pagerank/PageRankVertexProgram.java | 28 +++++-----
.../lambda/HaltedTraversersCountTraversal.java | 56 ++++++++++++++++++++
.../step/map/PageRankVertexProgramStep.java | 9 ++--
.../traversal/step/map/VertexProgramStep.java | 11 ++++
.../step/map/GroovyPageRankTest.groovy | 6 +++
.../traversal/step/map/PageRankTest.java | 27 ++++++++++
6 files changed, 121 insertions(+), 16 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cb4df815/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java
index 9a3d54d..cb64a3c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/ranking/pagerank/PageRankVertexProgram.java
@@ -58,12 +58,12 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
private static final String ALPHA = "gremlin.pageRankVertexProgram.alpha";
private static final String TOTAL_ITERATIONS = "gremlin.pageRankVertexProgram.totalIterations";
private static final String EDGE_TRAVERSAL = "gremlin.pageRankVertexProgram.edgeTraversal";
- private static final String VERTEX_TRAVERSAL = "gremlin.pageRankVertexProgram.vertexTraversal";
+ private static final String INITIAL_RANK_TRAVERSAL = "gremlin.pageRankVertexProgram.initialRankTraversal";
private MessageScope.Local<Double> incidentMessageScope = MessageScope.Local.of(__::outE);
private MessageScope.Local<Double> countMessageScope = MessageScope.Local.of(new MessageScope.Local.ReverseTraversalSupplier(this.incidentMessageScope));
private PureTraversal<Vertex, Edge> edgeTraversal = null;
- private PureTraversal<Vertex, Vertex> vertexTraversal = null;
+ private PureTraversal<Vertex, ? extends Number> initialRankTraversal = null;
private double vertexCountAsDouble = 1.0d;
private double alpha = 0.85d;
private int totalIterations = 30;
@@ -76,8 +76,8 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
@Override
public void loadState(final Graph graph, final Configuration configuration) {
- if (configuration.containsKey(VERTEX_TRAVERSAL))
- this.vertexTraversal = PureTraversal.loadState(configuration, VERTEX_TRAVERSAL, graph);
+ if (configuration.containsKey(INITIAL_RANK_TRAVERSAL))
+ this.initialRankTraversal = PureTraversal.loadState(configuration, INITIAL_RANK_TRAVERSAL, graph);
if (configuration.containsKey(EDGE_TRAVERSAL)) {
this.edgeTraversal = PureTraversal.loadState(configuration, EDGE_TRAVERSAL, graph);
this.incidentMessageScope = MessageScope.Local.of(() -> this.edgeTraversal.get().clone());
@@ -99,8 +99,8 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
configuration.setProperty(PROPERTY, this.property);
if (null != this.edgeTraversal)
this.edgeTraversal.storeState(configuration, EDGE_TRAVERSAL);
- if (null != this.vertexTraversal)
- this.vertexTraversal.storeState(configuration, VERTEX_TRAVERSAL);
+ if (null != this.initialRankTraversal)
+ this.initialRankTraversal.storeState(configuration, INITIAL_RANK_TRAVERSAL);
}
@Override
@@ -140,18 +140,20 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
if (memory.isInitialIteration()) {
messenger.sendMessage(this.countMessageScope, 1.0d);
} else if (1 == memory.getIteration()) {
- double initialPageRank = 1.0d / this.vertexCountAsDouble;
+ double initialPageRank = null == this.initialRankTraversal ?
+ 1.0d :
+ TraversalUtil.apply(vertex, this.initialRankTraversal.get()).doubleValue() / this.vertexCountAsDouble;
double edgeCount = IteratorUtils.reduce(messenger.receiveMessages(), 0.0d, (a, b) -> a + b);
vertex.property(VertexProperty.Cardinality.single, this.property, initialPageRank);
vertex.property(VertexProperty.Cardinality.single, EDGE_COUNT, edgeCount);
- messenger.sendMessage(this.incidentMessageScope, initialPageRank / edgeCount);
+ if (!this.terminate(memory)) // don't send messages if this is the last iteration
+ messenger.sendMessage(this.incidentMessageScope, initialPageRank / edgeCount);
} else {
- if (2 == memory.getIteration() && null != this.vertexTraversal && !TraversalUtil.test(vertex, this.vertexTraversal.get()))
- return;
double newPageRank = IteratorUtils.reduce(messenger.receiveMessages(), 0.0d, (a, b) -> a + b);
newPageRank = (this.alpha * newPageRank) + ((1.0d - this.alpha) / this.vertexCountAsDouble);
vertex.property(VertexProperty.Cardinality.single, this.property, newPageRank);
- messenger.sendMessage(this.incidentMessageScope, newPageRank / vertex.<Double>value(EDGE_COUNT));
+ if (!this.terminate(memory)) // don't send messages if this is the last iteration
+ messenger.sendMessage(this.incidentMessageScope, newPageRank / vertex.<Double>value(EDGE_COUNT));
}
}
@@ -202,8 +204,8 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
return this;
}
- public Builder vertices(final Traversal.Admin<Vertex, Vertex> vertexTraversal) {
- PureTraversal.storeState(this.configuration, VERTEX_TRAVERSAL, vertexTraversal);
+ public Builder initialRank(final Traversal.Admin<Vertex, ? extends Number> initialRankTraversal) {
+ PureTraversal.storeState(this.configuration, INITIAL_RANK_TRAVERSAL, initialRankTraversal);
return this;
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cb4df815/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/lambda/HaltedTraversersCountTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/lambda/HaltedTraversersCountTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/lambda/HaltedTraversersCountTraversal.java
new file mode 100644
index 0000000..b09cd7d
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/lambda/HaltedTraversersCountTraversal.java
@@ -0,0 +1,56 @@
+/*
+ * 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 org.apache.tinkerpop.gremlin.process.computer.traversal.lambda;
+
+import org.apache.tinkerpop.gremlin.process.computer.traversal.TraversalVertexProgram;
+import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
+import org.apache.tinkerpop.gremlin.process.traversal.lambda.AbstractLambdaTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.structure.Vertex;
+import org.apache.tinkerpop.gremlin.structure.VertexProperty;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class HaltedTraversersCountTraversal extends AbstractLambdaTraversal<Vertex, Long> {
+
+ private Long count;
+
+ @Override
+ public Long next() {
+ return count;
+ }
+
+ @Override
+ public void addStart(final Traverser<Vertex> start) {
+ final VertexProperty<TraverserSet<Object>> property = start.get().<TraverserSet<Object>>property(TraversalVertexProgram.HALTED_TRAVERSERS);
+ this.count = property.isPresent() ? property.value().bulkSize() : 0l;
+ }
+
+ @Override
+ public String toString() {
+ return "count(" + TraversalVertexProgram.HALTED_TRAVERSERS + ')';
+ }
+
+ @Override
+ public int hashCode() {
+ return this.getClass().hashCode();
+ }
+}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cb4df815/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java
index a5d1669..bbbe968 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/PageRankVertexProgramStep.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.computer.GraphComputer;
import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram;
+import org.apache.tinkerpop.gremlin.process.computer.traversal.lambda.HaltedTraversersCountTraversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
@@ -92,12 +93,14 @@ public final class PageRankVertexProgramStep extends VertexProgramStep implement
public PageRankVertexProgram generateProgram(final Graph graph) {
final Traversal.Admin<Vertex, Edge> detachedTraversal = this.edgeTraversal.getPure();
detachedTraversal.setStrategies(TraversalStrategies.GlobalCache.getStrategies(graph.getClass()));
- return PageRankVertexProgram.build()
+ final PageRankVertexProgram.Builder builder = PageRankVertexProgram.build()
.property(this.pageRankProperty)
.iterations(this.times + 1)
.alpha(this.alpha)
- .edges(detachedTraversal)
- .create(graph);
+ .edges(detachedTraversal);
+ if (this.previousTraversalVertexProgram())
+ builder.initialRank(new HaltedTraversersCountTraversal());
+ return builder.create(graph);
}
@Override
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cb4df815/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
index a85f5b1..7398710 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/VertexProgramStep.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.computer.traversal.step.map;
import org.apache.tinkerpop.gremlin.process.computer.ComputerResult;
import org.apache.tinkerpop.gremlin.process.computer.traversal.step.VertexComputing;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
@@ -57,4 +58,14 @@ public abstract class VertexProgramStep extends AbstractStep<ComputerResult, Com
throw new IllegalStateException(e.getMessage(), e);
}
}
+
+ protected boolean previousTraversalVertexProgram() {
+ Step<?, ?> currentStep = this;
+ while (!(currentStep instanceof EmptyStep)) {
+ if (currentStep instanceof TraversalVertexProgramStep)
+ return true;
+ currentStep = currentStep.getPreviousStep();
+ }
+ return false;
+ }
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cb4df815/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPageRankTest.groovy
----------------------------------------------------------------------
diff --git a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPageRankTest.groovy b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPageRankTest.groovy
index 22ffb0c..b3b3da5 100644
--- a/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPageRankTest.groovy
+++ b/gremlin-groovy-test/src/main/groovy/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroovyPageRankTest.groovy
@@ -20,6 +20,7 @@
package org.apache.tinkerpop.gremlin.process.traversal.step.map
import org.apache.tinkerpop.gremlin.process.traversal.Traversal
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__
import org.apache.tinkerpop.gremlin.process.traversal.util.ScriptTraversal
import org.apache.tinkerpop.gremlin.structure.Vertex
@@ -59,5 +60,10 @@ public abstract class GroovyPageRankTest {
public Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX() {
new ScriptTraversal<>(g, "gremlin-groovy", "g.V.pageRank.by('pageRank').as('a').out('knows').values('pageRank').as('b').select('a', 'b')")
}
+
+ @Override
+ public Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
+ new ScriptTraversal<>(g, "gremlin-groovy", "g.V().hasLabel('software').has('name', 'ripple').pageRank(1.0).by(inE('created')).times(1).by('priors').in('created').union(identity(),both()).valueMap('name', 'priors')")
+ }
}
}
http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/cb4df815/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
index d29230b..3ae98d9 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PageRankTest.java
@@ -37,6 +37,7 @@ import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
/**
* @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -56,6 +57,8 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
public abstract Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX();
+ public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
+
@Test
@LoadGraphWith(MODERN)
public void g_V_pageRank() {
@@ -159,6 +162,25 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
assertEquals(2, counter);
}
+ @Test
+ @LoadGraphWith(MODERN)
+ public void g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
+ final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX();
+ printTraversalForm(traversal);
+ int counter = 0;
+ while (traversal.hasNext()) {
+ final Map<String, List<Object>> map = traversal.next();
+ assertEquals(2, map.size());
+ String name = (String) map.get("name").get(0);
+ double pageRank = (Double) map.get("priors").get(0);
+ assertEquals(name.equals("josh") ? 1.0d : 0.0d, pageRank, 0.0001d);
+ if (name.equals("peter") || name.equals("vadas"))
+ fail("Peter or Vadas should not have been accessed");
+ counter++;
+ }
+ assertEquals(4, counter);
+ }
+
public static class Traversals extends PageRankTest {
@Override
@@ -190,5 +212,10 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
public Traversal<Vertex, Map<String, Object>> get_g_V_pageRank_byXpageRankX_asXaX_outXknowsX_pageRank_asXbX_selectXa_bX() {
return g.V().pageRank().by("pageRank").as("a").out("knows").values("pageRank").as("b").select("a", "b");
}
+
+ @Override
+ public Traversal<Vertex, Map<String, List<Object>>> get_g_V_hasLabelXsoftwareX_hasXname_rippleX_pageRankX1X_byXinEXcreatedXX_timesX1X_byXpriorsX_inXcreatedX_unionXboth__identityX_valueMapXname_priorsX() {
+ return g.V().hasLabel("software").has("name", "ripple").pageRank(1.0).by(__.inE("created")).times(1).by("priors").in("created").union(__.both(), __.identity()).valueMap("name", "priors");
+ }
}
}