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/16 17:31:33 UTC

incubator-tinkerpop git commit: Simplified the configuration internals of TraversalVertexProgram, PageRankVertexProgram, and PeerPressureVertexProgram. Stubbed the ability to allow these vertex programs determine which source vertices to use for their co

Repository: incubator-tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1154 45b097552 -> c3eb653cb


Simplified the configuration internals of TraversalVertexProgram, PageRankVertexProgram, and PeerPressureVertexProgram. Stubbed the ability to allow these vertex programs determine which source vertices to use for their computation. Added another PageRankTest which verifies the new ByModulating behavior for PageRankVertexProgramStep -- g.V().pageRank().by('friendRank').by(outE('knows')). Introduced PureTraversal which contains an uncompiled and compiled form of a Traversal. Useful for OLAP based VertexPrograms and Steps.


Project: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/commit/c3eb653c
Tree: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/tree/c3eb653c
Diff: http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/diff/c3eb653c

Branch: refs/heads/TINKERPOP-1154
Commit: c3eb653cbd3cb38e0925f0c1c21f4e5761637b79
Parents: 45b0975
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Feb 16 09:31:22 2016 -0700
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Feb 16 09:31:22 2016 -0700

----------------------------------------------------------------------
 .../peerpressure/PeerPressureVertexProgram.java | 31 +++-----
 .../ranking/pagerank/PageRankVertexProgram.java | 79 ++++++++++++--------
 .../traversal/TraversalVertexProgram.java       | 39 ++++------
 .../step/map/PageRankVertexProgramStep.java     | 17 ++++-
 .../step/map/TraversalVertexProgramStep.java    |  2 +-
 .../util/AbstractVertexProgramBuilder.java      |  4 +-
 .../computer/util/ConfigurationTraversal.java   |  5 +-
 .../process/traversal/util/PureTraversal.java   | 75 +++++++++++++++++++
 .../step/map/GroovyPageRankTest.groovy          |  4 +
 .../traversal/step/map/PageRankTest.java        | 32 ++++++++
 10 files changed, 205 insertions(+), 83 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java
index 7bf6029..b53f914 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/clustering/peerpressure/PeerPressureVertexProgram.java
@@ -24,15 +24,13 @@ import org.apache.tinkerpop.gremlin.process.computer.Memory;
 import org.apache.tinkerpop.gremlin.process.computer.MessageScope;
 import org.apache.tinkerpop.gremlin.process.computer.Messenger;
 import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
-import org.apache.tinkerpop.gremlin.process.computer.util.ConfigurationTraversal;
 import org.apache.tinkerpop.gremlin.process.computer.util.StaticVertexProgram;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.MapHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.util.PureTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ScriptTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalClassFunction;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalObjectFunction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -48,7 +46,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.function.Supplier;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
@@ -65,10 +62,10 @@ public class PeerPressureVertexProgram extends StaticVertexProgram<Pair<Serializ
 
     private static final String MAX_ITERATIONS = "gremlin.peerPressureVertexProgram.maxIterations";
     private static final String DISTRIBUTE_VOTE = "gremlin.peerPressureVertexProgram.distributeVote";
-    private static final String TRAVERSAL_SUPPLIER = "gremlin.peerPressureVertexProgram.traversalSupplier";
+    private static final String EDGE_TRAVERSAL = "gremlin.peerPressureVertexProgram.edgeTraversal";
     private static final String VOTE_TO_HALT = "gremlin.peerPressureVertexProgram.voteToHalt";
 
-    private ConfigurationTraversal<Vertex, Edge> configurationTraversal;
+    private PureTraversal<Vertex, Edge> edgeTraversal = null;
     private int maxIterations = 30;
     private boolean distributeVote = false;
 
@@ -81,9 +78,9 @@ public class PeerPressureVertexProgram extends StaticVertexProgram<Pair<Serializ
 
     @Override
     public void loadState(final Graph graph, final Configuration configuration) {
-        if (configuration.containsKey(TRAVERSAL_SUPPLIER)) {
-            this.configurationTraversal = ConfigurationTraversal.loadState(graph, configuration, TRAVERSAL_SUPPLIER);
-            this.voteScope = MessageScope.Local.of(this.configurationTraversal);
+        if (configuration.containsKey(EDGE_TRAVERSAL)) {
+            this.edgeTraversal = PureTraversal.loadState(configuration, EDGE_TRAVERSAL, graph);
+            this.voteScope = MessageScope.Local.of(() -> this.edgeTraversal.getCompiled().clone());
             this.countScope = MessageScope.Local.of(new MessageScope.Local.ReverseTraversalSupplier(this.voteScope));
         }
         this.maxIterations = configuration.getInt(MAX_ITERATIONS, 30);
@@ -95,9 +92,8 @@ public class PeerPressureVertexProgram extends StaticVertexProgram<Pair<Serializ
         super.storeState(configuration);
         configuration.setProperty(MAX_ITERATIONS, this.maxIterations);
         configuration.setProperty(DISTRIBUTE_VOTE, this.distributeVote);
-        if (null != this.configurationTraversal) {
-            this.configurationTraversal.storeState(configuration);
-        }
+        if (null != this.edgeTraversal)
+            this.edgeTraversal.storeState(configuration, EDGE_TRAVERSAL);
     }
 
     @Override
@@ -220,17 +216,10 @@ public class PeerPressureVertexProgram extends StaticVertexProgram<Pair<Serializ
             return this.traversal(new ScriptTraversal<>(traversalSource, scriptEngine, traversalScript, bindings));
         }
 
-        public Builder traversal(final Traversal.Admin<Vertex, Edge> traversal) {
-            ConfigurationTraversal.storeState(new TraversalObjectFunction<>(traversal), this.configuration, TRAVERSAL_SUPPLIER);
-            return this;
-        }
-
-
-        public Builder traversal(final Class<? extends Supplier<Traversal.Admin<?, ?>>> traversalClass) {
-            ConfigurationTraversal.storeState(new TraversalClassFunction(traversalClass), this.configuration, TRAVERSAL_SUPPLIER);
+        public Builder traversal(final Traversal.Admin<Vertex, Edge> edgeTraversal) {
+            PureTraversal.storeState(this.configuration, EDGE_TRAVERSAL, edgeTraversal);
             return this;
         }
-
     }
 
     ////////////////////////////

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/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 2eeb1cf..b627dd5 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
@@ -25,14 +25,12 @@ import org.apache.tinkerpop.gremlin.process.computer.MessageCombiner;
 import org.apache.tinkerpop.gremlin.process.computer.MessageScope;
 import org.apache.tinkerpop.gremlin.process.computer.Messenger;
 import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
-import org.apache.tinkerpop.gremlin.process.computer.util.ConfigurationTraversal;
 import org.apache.tinkerpop.gremlin.process.computer.util.StaticVertexProgram;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.PureTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ScriptTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalClassFunction;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalObjectFunction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
@@ -44,30 +42,34 @@ import java.util.Arrays;
 import java.util.HashSet;
 import java.util.Optional;
 import java.util.Set;
-import java.util.function.Supplier;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
 public class PageRankVertexProgram extends StaticVertexProgram<Double> {
 
-    private MessageScope.Local<Double> incidentMessageScope = MessageScope.Local.of(__::outE);
-    private MessageScope.Local<Double> countMessageScope = MessageScope.Local.of(new MessageScope.Local.ReverseTraversalSupplier(this.incidentMessageScope));
 
     public static final String PAGE_RANK = "gremlin.pageRankVertexProgram.pageRank";
     public static final String EDGE_COUNT = "gremlin.pageRankVertexProgram.edgeCount";
 
+    public static final String PAGE_RANK_PROPERTY = "gremlin.pageRankVertexProgram.pageRankProperty";
     private static final String VERTEX_COUNT = "gremlin.pageRankVertexProgram.vertexCount";
     private static final String ALPHA = "gremlin.pageRankVertexProgram.alpha";
     private static final String TOTAL_ITERATIONS = "gremlin.pageRankVertexProgram.totalIterations";
-    private static final String TRAVERSAL_SUPPLIER = "gremlin.pageRankVertexProgram.traversalSupplier";
+    private static final String EDGE_TRAVERSAL = "gremlin.pageRankVertexProgram.edgeTraversal";
+    private static final String VERTEX_TRAVERSAL = "gremlin.pageRankVertexProgram.vertexTraversal";
+
 
-    private ConfigurationTraversal<Vertex, Edge> configurationTraversal;
+    //private ConfigurationTraversal<Vertex, Edge> configurationTraversal;
+    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 double vertexCountAsDouble = 1.0d;
     private double alpha = 0.85d;
     private int totalIterations = 30;
-
-    private static final Set<String> COMPUTE_KEYS = new HashSet<>(Arrays.asList(PAGE_RANK, EDGE_COUNT));
+    private String pageRankProperty = PAGE_RANK;
+    private Set<String> computeKeys;
 
     private PageRankVertexProgram() {
 
@@ -75,25 +77,32 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
 
     @Override
     public void loadState(final Graph graph, final Configuration configuration) {
-        if (configuration.containsKey(TRAVERSAL_SUPPLIER)) {
-            this.configurationTraversal = ConfigurationTraversal.loadState(graph, configuration, TRAVERSAL_SUPPLIER);
-            this.incidentMessageScope = MessageScope.Local.of(this.configurationTraversal);
+        if (configuration.containsKey(VERTEX_TRAVERSAL))
+            this.vertexTraversal = PureTraversal.loadState(configuration, VERTEX_TRAVERSAL, graph);
+        if (configuration.containsKey(EDGE_TRAVERSAL)) {
+            this.edgeTraversal = PureTraversal.loadState(configuration, EDGE_TRAVERSAL, graph);
+            this.incidentMessageScope = MessageScope.Local.of(() -> this.edgeTraversal.getCompiled().clone());
             this.countMessageScope = MessageScope.Local.of(new MessageScope.Local.ReverseTraversalSupplier(this.incidentMessageScope));
         }
         this.vertexCountAsDouble = configuration.getDouble(VERTEX_COUNT, 1.0d);
         this.alpha = configuration.getDouble(ALPHA, 0.85d);
         this.totalIterations = configuration.getInt(TOTAL_ITERATIONS, 30);
+        this.pageRankProperty = configuration.getString(PAGE_RANK_PROPERTY, PAGE_RANK);
+        this.computeKeys = new HashSet<>(Arrays.asList(this.pageRankProperty, EDGE_COUNT));
+
     }
 
     @Override
     public void storeState(final Configuration configuration) {
-        configuration.setProperty(VERTEX_PROGRAM, PageRankVertexProgram.class.getName());
+        super.storeState(configuration);
         configuration.setProperty(VERTEX_COUNT, this.vertexCountAsDouble);
         configuration.setProperty(ALPHA, this.alpha);
         configuration.setProperty(TOTAL_ITERATIONS, this.totalIterations);
-        if (null != this.configurationTraversal) {
-            this.configurationTraversal.storeState(configuration);
-        }
+        configuration.setProperty(PAGE_RANK_PROPERTY, this.pageRankProperty);
+        if (null != this.edgeTraversal)
+            this.edgeTraversal.storeState(configuration, EDGE_TRAVERSAL);
+        if (null != this.vertexTraversal)
+            this.vertexTraversal.storeState(configuration, VERTEX_TRAVERSAL);
     }
 
     @Override
@@ -108,7 +117,7 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
 
     @Override
     public Set<String> getElementComputeKeys() {
-        return COMPUTE_KEYS;
+        return this.computeKeys;
     }
 
     @Override
@@ -135,13 +144,13 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
         } else if (1 == memory.getIteration()) {
             double initialPageRank = 1.0d / this.vertexCountAsDouble;
             double edgeCount = IteratorUtils.reduce(messenger.receiveMessages(), 0.0d, (a, b) -> a + b);
-            vertex.property(VertexProperty.Cardinality.single, PAGE_RANK, initialPageRank);
+            vertex.property(VertexProperty.Cardinality.single, this.pageRankProperty, initialPageRank);
             vertex.property(VertexProperty.Cardinality.single, EDGE_COUNT, edgeCount);
             messenger.sendMessage(this.incidentMessageScope, initialPageRank / edgeCount);
         } else {
             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, PAGE_RANK, newPageRank);
+            vertex.property(VertexProperty.Cardinality.single, this.pageRankProperty, newPageRank);
             messenger.sendMessage(this.incidentMessageScope, newPageRank / vertex.<Double>value(EDGE_COUNT));
         }
     }
@@ -153,7 +162,7 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
 
     @Override
     public String toString() {
-        return StringFactory.vertexProgramString(this, "alpha=" + this.alpha + ",iterations=" + this.totalIterations);
+        return StringFactory.vertexProgramString(this, "alpha=" + this.alpha + ", iterations=" + this.totalIterations);
     }
 
     //////////////////////////////
@@ -178,25 +187,35 @@ public class PageRankVertexProgram extends StaticVertexProgram<Double> {
             return this;
         }
 
-        public Builder traversal(final TraversalSource traversalSource, final String scriptEngine, final String traversalScript, final Object... bindings) {
-            return this.traversal(new ScriptTraversal<>(traversalSource, scriptEngine, traversalScript, bindings));
+        public Builder pageRankProperty(final String key) {
+            this.configuration.setProperty(PAGE_RANK_PROPERTY, key);
+            return this;
         }
 
-        public Builder traversal(final Traversal.Admin<Vertex, Edge> traversal) {
-            ConfigurationTraversal.storeState(new TraversalObjectFunction<>(traversal), this.configuration, TRAVERSAL_SUPPLIER);
+        public Builder vertexCount(final long vertexCount) {
+            this.configuration.setProperty(VERTEX_COUNT, (double) vertexCount);
             return this;
         }
 
-
-        public Builder traversal(final Class<? extends Supplier<Traversal.Admin<?, ?>>> traversalClass) {
-            ConfigurationTraversal.storeState(new TraversalClassFunction(traversalClass), this.configuration, TRAVERSAL_SUPPLIER);
+        public Builder edges(final Traversal.Admin<Vertex, Edge> edgeTraversal) {
+            PureTraversal.storeState(this.configuration, EDGE_TRAVERSAL, edgeTraversal);
             return this;
         }
 
-        public Builder vertexCount(final long vertexCount) {
-            this.configuration.setProperty(VERTEX_COUNT, (double) vertexCount);
+        public Builder vertices(final Traversal.Admin<Vertex, Vertex> vertexTraversal) {
+            PureTraversal.storeState(this.configuration, VERTEX_TRAVERSAL, vertexTraversal);
             return this;
         }
+
+        @Deprecated
+        public Builder traversal(final TraversalSource traversalSource, final String scriptEngine, final String traversalScript, final Object... bindings) {
+            return this.edges(new ScriptTraversal<>(traversalSource, scriptEngine, traversalScript, bindings));
+        }
+
+        @Deprecated
+        public Builder traversal(final Traversal.Admin<Vertex, Edge> traversal) {
+            return this.edges(traversal);
+        }
     }
 
     ////////////////////////////

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
index 9c2d64b..a2b0c65 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/TraversalVertexProgram.java
@@ -28,7 +28,6 @@ import org.apache.tinkerpop.gremlin.process.computer.Messenger;
 import org.apache.tinkerpop.gremlin.process.computer.VertexProgram;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.step.sideEffect.mapreduce.TraverserMapReduce;
 import org.apache.tinkerpop.gremlin.process.computer.util.AbstractVertexProgramBuilder;
-import org.apache.tinkerpop.gremlin.process.computer.util.ConfigurationTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSideEffects;
 import org.apache.tinkerpop.gremlin.process.traversal.TraversalSource;
@@ -40,11 +39,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffect
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.EmptyTraversal;
+import org.apache.tinkerpop.gremlin.process.traversal.util.PureTraversal;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ScriptTraversal;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalClassFunction;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalMatrix;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalObjectFunction;
 import org.apache.tinkerpop.gremlin.structure.Direction;
 import org.apache.tinkerpop.gremlin.structure.Edge;
 import org.apache.tinkerpop.gremlin.structure.Element;
@@ -60,7 +58,6 @@ import java.util.HashSet;
 import java.util.Iterator;
 import java.util.Optional;
 import java.util.Set;
-import java.util.function.Supplier;
 
 
 /**
@@ -78,14 +75,14 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
 
     public static final String HALTED_TRAVERSERS = "gremlin.traversalVertexProgram.haltedTraversers";
     private static final String VOTE_TO_HALT = "gremlin.traversalVertexProgram.voteToHalt";
-    public static final String TRAVERSAL_SUPPLIER = "gremlin.traversalVertexProgram.traversalSupplier";
+    public static final String TRAVERSAL = "gremlin.traversalVertexProgram.traversal";
 
     // TODO: if not an adjacent traversal, use Local message scope -- a dual messaging system.
     private static final Set<MessageScope> MESSAGE_SCOPES = new HashSet<>(Collections.singletonList(MessageScope.Global.instance()));
     private static final Set<String> ELEMENT_COMPUTE_KEYS = new HashSet<>(Arrays.asList(HALTED_TRAVERSERS, TraversalSideEffects.SIDE_EFFECTS));
     private static final Set<String> MEMORY_COMPUTE_KEYS = new HashSet<>(Collections.singletonList(VOTE_TO_HALT));
 
-    private ConfigurationTraversal<?, ?> configurationTraversal;
+    private PureTraversal<?, ?> pureTraversal;
     private Traversal.Admin<?, ?> traversal;
     private TraversalMatrix<?, ?> traversalMatrix;
 
@@ -98,36 +95,31 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
      * A helper method to yield a {@link Traversal} from the {@link Graph} and provided {@link Configuration}.
      *
      * @param graph         the graph that the traversal will run against
-     * @param configuration The configuration containing the TRAVERSAL_SUPPLIER key.
+     * @param configuration The configuration containing the TRAVERSAL key.
      * @return the traversal supplied by the configuration
      */
     public static Traversal.Admin<?, ?> getTraversal(final Graph graph, final Configuration configuration) {
-        return VertexProgram.<TraversalVertexProgram>createVertexProgram(graph, configuration).getTraversal();
-    }
-
-    public Traversal.Admin<?, ?> getTraversal() {
-        return this.traversal;
+        return VertexProgram.<TraversalVertexProgram>createVertexProgram(graph, configuration).traversal;
     }
 
     @Override
     public void loadState(final Graph graph, final Configuration configuration) {
-        this.configurationTraversal = ConfigurationTraversal.loadState(graph, configuration, TRAVERSAL_SUPPLIER);
-        if (null == this.configurationTraversal) {
-            throw new IllegalArgumentException("The configuration does not have a traversal supplier:" + TRAVERSAL_SUPPLIER);
-        }
-        this.traversal = this.configurationTraversal.get();
+        if (!configuration.containsKey(TRAVERSAL))
+            throw new IllegalArgumentException("The configuration does not have a traversal supplier: " + TRAVERSAL);
+        this.pureTraversal = PureTraversal.loadState(configuration, TRAVERSAL, graph);
+        this.traversal = this.pureTraversal.getCompiled();
         this.traversalMatrix = new TraversalMatrix<>(this.traversal);
         for (final MapReducer<?, ?, ?, ?, ?> mapReducer : TraversalHelper.getStepsOfAssignableClassRecursively(MapReducer.class, this.traversal)) {
             this.mapReducers.add(mapReducer.getMapReduce());
         }
         if (!(this.traversal.getEndStep() instanceof SideEffectCapStep) && !(this.traversal.getEndStep() instanceof ReducingBarrierStep))
-            this.mapReducers.add(new TraverserMapReduce(this.traversal.clone()));
+            this.mapReducers.add(new TraverserMapReduce(this.traversal));
     }
 
     @Override
     public void storeState(final Configuration configuration) {
         VertexProgram.super.storeState(configuration);
-        this.configurationTraversal.storeState(configuration);
+        this.pureTraversal.storeState(configuration, TRAVERSAL);
     }
 
     @Override
@@ -157,7 +149,7 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
             final GraphStep<Element, Element> graphStep = (this.traversal.getStartStep() instanceof GraphStep) ?
                     (GraphStep<Element, Element>) this.traversal.getStartStep() :
                     new GraphStep((Traversal.Admin) EmptyTraversal.instance(), Vertex.class, true); // if no start vertices, then do all vertices
-            final String future = graphStep.getNextStep().getId();
+            final String future = (this.traversal.getStartStep() instanceof GraphStep) ? graphStep.getNextStep().getId() : this.traversal.getStartStep().getId();
             final TraverserGenerator traverserGenerator = this.traversal.getTraverserGenerator();
             if (graphStep.returnsVertex()) {  // VERTICES (process the first step locally)
                 if (ElementHelper.idExists(vertex.id(), graphStep.getIds())) {
@@ -284,12 +276,7 @@ public final class TraversalVertexProgram implements VertexProgram<TraverserSet<
         }
 
         public Builder traversal(final Traversal.Admin<?, ?> traversal) {
-            ConfigurationTraversal.storeState(new TraversalObjectFunction<>(traversal), this.configuration, TRAVERSAL_SUPPLIER);
-            return this;
-        }
-
-        public Builder traversal(final Class<? extends Supplier<Traversal.Admin<?, ?>>> traversalClass) {
-            ConfigurationTraversal.storeState(new TraversalClassFunction(traversalClass), this.configuration, TRAVERSAL_SUPPLIER);
+            PureTraversal.storeState(this.configuration, TRAVERSAL, traversal);
             return this;
         }
     }

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/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 ecd015c..59b31ad 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
@@ -51,6 +51,7 @@ public final class PageRankVertexProgramStep extends AbstractStep<ComputerResult
 
     private Traversal.Admin<Vertex, Edge> pageRankTraversal;
     private Traversal.Admin<Vertex, Edge> purePageRankTraversal;
+    private String pageRankProperty = PageRankVertexProgram.PAGE_RANK;
     private boolean first = true;
 
 
@@ -66,12 +67,12 @@ public final class PageRankVertexProgramStep extends AbstractStep<ComputerResult
                 this.first = false;
                 final Graph graph = this.getTraversal().getGraph().get();
                 final GraphComputer graphComputer = this.graphComputerFunction.apply(graph).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW);
-                return this.traversal.getTraverserGenerator().generate(graphComputer.program(PageRankVertexProgram.build().traversal(this.compileTraversal(graph)).create(graph)).submit().get(), this, 1l);
+                return this.traversal.getTraverserGenerator().generate(graphComputer.program(this.generateProgram(graph)).submit().get(), this, 1l);
             } else {
                 final Traverser.Admin<ComputerResult> traverser = this.starts.next();
                 final Graph graph = traverser.get().graph();
                 final GraphComputer graphComputer = this.graphComputerFunction.apply(graph).persist(GraphComputer.Persist.EDGES).result(GraphComputer.ResultGraph.NEW);
-                return traverser.split(graphComputer.program(PageRankVertexProgram.build().traversal(this.compileTraversal(graph)).create(graph)).submit().get(), this);
+                return traverser.split(graphComputer.program(this.generateProgram(graph)).submit().get(), this);
             }
         } catch (final InterruptedException | ExecutionException e) {
             throw new IllegalStateException(e.getMessage(), e);
@@ -85,6 +86,11 @@ public final class PageRankVertexProgramStep extends AbstractStep<ComputerResult
     }
 
     @Override
+    public void modulateBy(final String pageRankProperty) {
+        this.pageRankProperty = pageRankProperty;
+    }
+
+    @Override
     public List<Traversal.Admin<Vertex, Edge>> getLocalChildren() {
         return Collections.singletonList(this.pageRankTraversal);
     }
@@ -99,6 +105,13 @@ public final class PageRankVertexProgramStep extends AbstractStep<ComputerResult
         this.graphComputerFunction = graphComputerFunction;
     }
 
+    private PageRankVertexProgram generateProgram(final Graph graph) {
+        return PageRankVertexProgram.build()
+                .pageRankProperty(this.pageRankProperty)
+                .edges(this.compileTraversal(graph))
+                .create(graph);
+    }
+
     private final Traversal.Admin<Vertex, Edge> compileTraversal(final Graph graph) {
         final Traversal.Admin<Vertex, Edge> compiledPageRankTraversal = this.purePageRankTraversal.clone();
         compiledPageRankTraversal.setStrategies(TraversalStrategies.GlobalCache.getStrategies(graph.getClass()));

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java
index 500de8a..7dde14c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/traversal/step/map/TraversalVertexProgramStep.java
@@ -68,7 +68,7 @@ public final class TraversalVertexProgramStep extends AbstractStep<ComputerResul
                 this.first = false;
                 final Graph graph = this.getTraversal().getGraph().get();
                 final GraphComputer graphComputer = this.graphComputerFunction.apply(graph);
-                final ComputerResult result = graphComputer.program(TraversalVertexProgram.build().traversal(this.compileTraversal(graph)).create(this.getTraversal().getGraph().get())).submit().get();
+                final ComputerResult result = graphComputer.program(TraversalVertexProgram.build().traversal(this.compileTraversal(graph)).create(graph)).submit().get();
                 return this.getTraversal().getTraverserGenerator().generate(result, (Step) this, 1l);
             } else {
                 final Traverser.Admin<ComputerResult> traverser = this.starts.next();

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java
index 50e5157..3d8cedc 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/AbstractVertexProgramBuilder.java
@@ -27,14 +27,14 @@ import org.apache.tinkerpop.gremlin.structure.Graph;
  */
 public abstract class AbstractVertexProgramBuilder<B extends VertexProgram.Builder> implements VertexProgram.Builder {
 
-    public static final String GREMLIN_GROOVY = "gremlin-groovy";
-
     protected final BaseConfiguration configuration = new BaseConfiguration();
 
     public AbstractVertexProgramBuilder() {
+        this.configuration.setDelimiterParsingDisabled(true);
     }
 
     public AbstractVertexProgramBuilder(final Class<? extends VertexProgram> vertexProgramClass) {
+        this();
         this.configuration.setProperty(VertexProgram.VERTEX_PROGRAM, vertexProgramClass.getName());
     }
 

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ConfigurationTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ConfigurationTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ConfigurationTraversal.java
index eb8cc83..7142166 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ConfigurationTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/computer/util/ConfigurationTraversal.java
@@ -21,6 +21,7 @@ package org.apache.tinkerpop.gremlin.process.computer.util;
 
 import org.apache.commons.configuration.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.util.ScriptTraversal;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 
 import java.util.function.Function;
@@ -28,7 +29,9 @@ import java.util.function.Supplier;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @deprecated As of release 3.2.0, replaced by {@link org.apache.tinkerpop.gremlin.process.traversal.util.PureTraversal}.
  */
+@Deprecated
 public final class ConfigurationTraversal<S, E> implements Supplier<Traversal.Admin<S, E>> {
 
     private Function<Graph, Traversal.Admin<S, E>> traversalFunction;
@@ -67,4 +70,4 @@ public final class ConfigurationTraversal<S, E> implements Supplier<Traversal.Ad
         configurationTraversal.traversalFunction = configValue instanceof String ? VertexProgramHelper.deserialize(configuration, configKey) : (Function<Graph, Traversal.Admin<S, E>>) configValue;
         return configurationTraversal;
     }
-}
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java
new file mode 100644
index 0000000..8d0c267
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/PureTraversal.java
@@ -0,0 +1,75 @@
+/*
+ * 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.traversal.util;
+
+import org.apache.commons.configuration.Configuration;
+import org.apache.tinkerpop.gremlin.process.computer.util.VertexProgramHelper;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.structure.Graph;
+
+import java.io.Serializable;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class PureTraversal<S, E> implements Serializable {
+
+    private final Traversal.Admin<S, E> pureTraversal;
+    private transient Traversal.Admin<S, E> compiledTraversal;
+
+    public PureTraversal(final Traversal.Admin<S, E> pureTraversal) {
+        this.pureTraversal = pureTraversal;
+    }
+
+    public Traversal.Admin<S, E> getPure() {
+        return this.pureTraversal;
+    }
+
+    public Traversal.Admin<S, E> getCompiled() {
+        if (null == this.compiledTraversal) {
+            this.compiledTraversal = this.pureTraversal.clone();
+            this.pureTraversal.getGraph().ifPresent(this.compiledTraversal::setGraph);
+            if (!this.compiledTraversal.isLocked())
+                this.compiledTraversal.applyStrategies();
+        }
+        return this.compiledTraversal;
+    }
+
+    public void storeState(final Configuration configuration, final String configurationKey) {
+        try {
+            VertexProgramHelper.serialize(this, configuration, configurationKey);   // the traversal can not be serialized (probably because of lambdas). As such, try direct reference.
+        } catch (final IllegalArgumentException e) {
+            configuration.setProperty(configurationKey, this);
+        }
+    }
+
+    ////////////
+
+    public static <S, E> void storeState(final Configuration configuration, final String configurationKey, final Traversal.Admin<S, E> traversal) {
+        new PureTraversal<>(traversal).storeState(configuration, configurationKey);
+    }
+
+    public static <S, E> PureTraversal<S, E> loadState(final Configuration configuration, final String configurationKey, final Graph graph) {
+        final Object configValue = configuration.getProperty(configurationKey);
+        final PureTraversal<S, E> pureTraversal = (configValue instanceof String ? (PureTraversal<S, E>) VertexProgramHelper.deserialize(configuration, configurationKey) : ((PureTraversal<S, E>) configValue));
+        pureTraversal.pureTraversal.setGraph(graph);
+        return pureTraversal;
+    }
+}

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/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 f5a348b..438f2f7 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
@@ -35,6 +35,10 @@ public abstract class GroovyPageRankTest {
             new ScriptTraversal<>(g, "gremlin-groovy", "g.V.pageRank")
         }
 
+        @Override
+        public Traversal<Vertex, Map<String, List<Object>>> get_g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_valueMapXname_friendRankX() {
+            new ScriptTraversal<>(g, "gremlin-groovy", "g.V.pageRank.by(outE('knows')).by('friendRank').valueMap('name','friendRank')")
+        }
 
         @Override
         public Traversal<Vertex, String> get_g_V_pageRank_order_byXpageRank_decrX_name() {

http://git-wip-us.apache.org/repos/asf/incubator-tinkerpop/blob/c3eb653c/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 51fa4b7..8f4bb0e 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
@@ -25,11 +25,13 @@ import org.apache.tinkerpop.gremlin.process.GremlinProcessRunner;
 import org.apache.tinkerpop.gremlin.process.computer.ranking.pagerank.PageRankVertexProgram;
 import org.apache.tinkerpop.gremlin.process.traversal.Order;
 import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 import org.junit.runner.RunWith;
 
 import java.util.List;
+import java.util.Map;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.junit.Assert.assertEquals;
@@ -47,6 +49,8 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, String> get_g_V_pageRank_order_byXpageRank_decrX_name_limitX2X();
 
+    public abstract Traversal<Vertex, Map<String, List<Object>>> get_g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_valueMapXname_friendRankX();
+
     @Test
     @LoadGraphWith(MODERN)
     public void g_V_pageRank() {
@@ -78,6 +82,29 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
+    public void g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_valueMapXname_friendRankX() {
+        final Traversal<Vertex, Map<String, List<Object>>> traversal = get_g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_valueMapXname_friendRankX();
+        printTraversalForm(traversal);
+        int counter = 0;
+        while (traversal.hasNext()) {
+            final Map<String, List<Object>> map = traversal.next();
+            assertEquals(2, map.size());
+            assertEquals(1, map.get("name").size());
+            assertEquals(1, map.get("friendRank").size());
+            String name = (String) map.get("name").get(0);
+            Double friendRank = (Double) map.get("friendRank").get(0);
+            if (name.equals("lop") || name.equals("ripple") || name.equals("peter") || name.equals("marko"))
+                assertEquals(0.15, friendRank, 0.01);
+            else
+                assertEquals(0.21375, friendRank, 0.01);
+
+            counter++;
+        }
+        assertEquals(6, counter);
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
     public void g_V_pageRank_order_byXpageRank_decrX_name_limitX2X() {
         final Traversal<Vertex, String> traversal = get_g_V_pageRank_order_byXpageRank_decrX_name_limitX2X();
         printTraversalForm(traversal);
@@ -95,6 +122,11 @@ public abstract class PageRankTest extends AbstractGremlinProcessTest {
         }
 
         @Override
+        public Traversal<Vertex, Map<String, List<Object>>> get_g_V_pageRank_byXoutEXknowsXX_byXfriendRankX_valueMapXname_friendRankX() {
+            return g.V().pageRank().by(__.outE("knows")).by("friendRank").valueMap("name", "friendRank");
+        }
+
+        @Override
         public Traversal<Vertex, String> get_g_V_pageRank_order_byXpageRank_decrX_name() {
             return g.V().pageRank().order().by(PageRankVertexProgram.PAGE_RANK, Order.decr).values("name");
         }