You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by sp...@apache.org on 2021/12/03 22:48:02 UTC

[tinkerpop] 01/01: TINKERPOP-2635 filtering for unproductive by() WIP

This is an automated email from the ASF dual-hosted git repository.

spmallette pushed a commit to branch TINKERPOP-2635
in repository https://gitbox.apache.org/repos/asf/tinkerpop.git

commit 02533bc9a6a5a62bf043fd352bf24cfdabf8abed
Author: Stephen Mallette <st...@amazon.com>
AuthorDate: Fri Dec 3 17:01:35 2021 -0500

    TINKERPOP-2635 filtering for unproductive by() WIP
---
 CHANGELOG.asciidoc                                 |   2 +
 docs/src/dev/developer/for-committers.asciidoc     |   3 +
 .../tinkerpop/gremlin/process/traversal/Path.java  |   6 +-
 .../tinkerpop/gremlin/process/traversal/Step.java  |   2 +-
 .../process/traversal/TraversalStrategies.java     |   2 -
 .../traversal/step/filter/DedupGlobalStep.java     |  72 ++++++-----
 .../traversal/step/filter/PathFilterStep.java      |  17 ++-
 .../traversal/step/filter/SampleGlobalStep.java    |  20 +++-
 .../traversal/step/filter/WherePredicateStep.java  |  34 ++++--
 .../process/traversal/step/map/GroupCountStep.java |   2 +-
 .../process/traversal/step/map/GroupStep.java      |  14 ++-
 .../process/traversal/step/map/MathStep.java       |  29 +++--
 .../traversal/step/map/OrderGlobalStep.java        |  15 ++-
 .../process/traversal/step/map/OrderLocalStep.java | 104 ++++++++++------
 .../process/traversal/step/map/PathStep.java       |  44 ++++---
 .../process/traversal/step/map/ProjectStep.java    |   2 +-
 .../traversal/step/map/PropertyMapStep.java        |  13 +-
 .../process/traversal/step/map/SelectOneStep.java  |   7 +-
 .../process/traversal/step/map/SelectStep.java     |  12 +-
 .../process/traversal/step/map/TreeStep.java       |  12 +-
 .../step/sideEffect/AggregateGlobalStep.java       |   8 +-
 .../step/sideEffect/AggregateLocalStep.java        |   2 +-
 .../traversal/step/sideEffect/SackValueStep.java   |  18 ++-
 .../process/traversal/util/TraversalProduct.java   |  55 +++++++++
 .../process/traversal/util/TraversalUtil.java      | 133 +++++++++++++--------
 .../gremlin/util/function/ChainedComparator.java   |   2 +
 .../gremlin/process/traversal/PathTest.java        |  20 ++++
 .../optimization/PathProcessorStrategyTest.java    |  19 +--
 .../Gherkin/GherkinTestRunner.cs                   |   3 +-
 .../Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs |  43 +++++++
 .../test/cucumber/feature-steps.js                 |   2 +-
 .../gremlin-javascript/test/cucumber/gremlin.js    |  45 ++++++-
 gremlin-python/src/main/python/radish/gremlin.py   |  45 +++++++
 .../server/op/session/SessionOpProcessor.java      |   6 +-
 gremlin-test/features/filter/CyclicPath.feature    |  14 +++
 gremlin-test/features/filter/Dedup.feature         |  48 +++++++-
 gremlin-test/features/filter/Sample.feature        |  11 ++
 gremlin-test/features/filter/SimplePath.feature    |  17 +++
 gremlin-test/features/filter/Where.feature         |  13 +-
 gremlin-test/features/map/Math.feature             |  28 +++++
 gremlin-test/features/map/Max.feature              |  40 +++++++
 gremlin-test/features/map/Mean.feature             |  44 +++++++
 gremlin-test/features/map/Min.feature              |  40 +++++++
 gremlin-test/features/map/Order.feature            |  76 +++++++++++-
 gremlin-test/features/map/Path.feature             |  14 +++
 gremlin-test/features/map/Project.feature          |  18 +++
 gremlin-test/features/map/Select.feature           |  31 ++++-
 gremlin-test/features/map/Sum.feature              |  45 ++++++-
 gremlin-test/features/map/ValueMap.feature         |  18 ++-
 gremlin-test/features/sideEffect/Aggregate.feature |  73 ++++++++++-
 gremlin-test/features/sideEffect/Group.feature     |  22 ++++
 .../features/sideEffect/GroupCount.feature         |  22 ++++
 gremlin-test/features/sideEffect/Sack.feature      |  14 +++
 .../process/traversal/step/filter/DedupTest.java   |   3 +-
 .../process/traversal/step/filter/WhereTest.java   |   4 +-
 .../process/traversal/step/map/MaxTest.java        |   2 -
 .../process/traversal/step/map/MeanTest.java       |   2 -
 .../process/traversal/step/map/MinTest.java        |   2 -
 .../process/traversal/step/map/OrderTest.java      |   2 +-
 .../process/traversal/step/map/PathTest.java       |   4 +-
 .../process/traversal/step/map/ProjectTest.java    |  37 ++++--
 .../process/traversal/step/map/SelectTest.java     |   2 +-
 .../process/traversal/step/map/SumTest.java        |   4 +-
 .../traversal/step/sideEffect/AggregateTest.java   |   4 +-
 .../traversal/step/sideEffect/GroupTest.java       |   2 +-
 .../traversal/step/sideEffect/TreeTest.java        |  25 ++++
 66 files changed, 1253 insertions(+), 241 deletions(-)

diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index 703ba95..08275c2 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -39,6 +39,8 @@ limitations under the License.
 * Created a way to produce a corpus of Gremlin traversals via `FeatureReader` and `DocumentationReader` in `gremlin-language`.
 * Exposed Gherkin tests as part of the provider test suite.
 * Packaged Gherkin tests and data as standalone package as a convenience distribution.
+* Removed `ProductiveByStrategy` as a strategy that is applied by default.
+* Changed `by()` modulator semantics to consistently filter.
 * Removed previously deprecated `application/vnd.gremlin-v1.0+gryo-lite` serialization format.
 * Removed previously deprecated `AuthenticationSettings.enableAuditLog`.
 * Removed previously deprecated `GroovyTranslator` from `gremlin-groovy` module.
diff --git a/docs/src/dev/developer/for-committers.asciidoc b/docs/src/dev/developer/for-committers.asciidoc
index 4114259..8a6c568 100644
--- a/docs/src/dev/developer/for-committers.asciidoc
+++ b/docs/src/dev/developer/for-committers.asciidoc
@@ -530,6 +530,9 @@ or meta-properties for creating or querying data.
 * `@RemoteOnly` - The scenario uses some Gremlin syntax that cannot be supported outside of remote test executions. The
 best example of this sort of test would be one that uses the remote `Lambda` syntax.
 
+Tag filters can be applied to Intellij at execution time by adding a system properties of
+`-Dcucumber.filter.tags=<step-filter>`.
+
 == Developing Benchmarks
 
 Benchmarks are a useful tool to track performance between TinkerPop versions and also as tools to aid development
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
index d8e51c2..9d78f21 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Path.java
@@ -26,6 +26,7 @@ import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Objects;
 import java.util.Optional;
 import java.util.Set;
 import java.util.function.BiConsumer;
@@ -198,8 +199,7 @@ public interface Path extends Cloneable, Iterable<Object> {
     public Path clone();
 
     /**
-     * Determines whether the path is a simple or not.
-     * A simple path has no cycles and thus, no repeated objects.
+     * Determines whether the path is a simple or not. A simple path has no cycles and thus, no repeated objects.
      *
      * @return Whether the path is simple or not
      */
@@ -207,7 +207,7 @@ public interface Path extends Cloneable, Iterable<Object> {
         final List<Object> objects = this.objects();
         for (int i = 0; i < objects.size() - 1; i++) {
             for (int j = i + 1; j < objects.size(); j++) {
-                if (objects.get(i).equals(objects.get(j)))
+                if (Objects.equals(objects.get(i), objects.get(j)))
                     return false;
             }
         }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java
index 6bc34f5..99fdd91 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/Step.java
@@ -41,7 +41,7 @@ import java.util.Set;
 public interface Step<S, E> extends Iterator<Traverser.Admin<E>>, Serializable, Cloneable {
 
     /**
-     * Add a iterator of {@link Traverser.Admin} objects of type S to the step.
+     * Add an iterator of {@link Traverser.Admin} objects of type S to the step.
      *
      * @param starts The iterator of objects to add
      */
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
index 37ad108..01deea1 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
@@ -23,7 +23,6 @@ import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.finaliza
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.GraphFilterStrategy;
 import org.apache.tinkerpop.gremlin.process.computer.traversal.strategy.optimization.MessagePassingReductionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.ConnectiveStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.AdjacentToIncidentStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
@@ -225,7 +224,6 @@ public interface TraversalStrategies extends Serializable, Cloneable, Iterable<T
                     IncidentToAdjacentStrategy.instance(),
                     AdjacentToIncidentStrategy.instance(),
                     ByModulatorOptimizationStrategy.instance(),
-                    ProductiveByStrategy.instance(),
                     FilterRankingStrategy.instance(),
                     MatchPredicateStrategy.instance(),
                     RepeatUnrollStrategy.instance(),
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
index dd8235d..9f5b0e5 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupGlobalStep.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.Property;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -73,11 +74,18 @@ public final class DedupGlobalStep<S> extends FilterStep<S> implements Traversal
         if (this.onGraphComputer && !this.executingAtMaster) return true;
         traverser.setBulk(1L);
         if (null == this.dedupLabels) {
-            return this.duplicateSet.add(TraversalUtil.applyNullable(traverser, this.dedupTraversal));
+            final TraversalProduct product = TraversalUtil.produce(traverser, this.dedupTraversal);
+            return product.isProductive() && this.duplicateSet.add(product.get());
         } else {
             final List<Object> objects = new ArrayList<>(this.dedupLabels.size());
-            this.dedupLabels.forEach(label -> objects.add(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal)));
-            return this.duplicateSet.add(objects);
+            for (String label : dedupLabels) {
+                final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal);
+                if (!product.isProductive()) break;
+                objects.add(product.get());
+            }
+
+            // the object sizes must be equal or else it means a by() wasn't productive and that path will be filtered
+            return objects.size() == dedupLabels.size() && duplicateSet.add(objects);
         }
     }
 
@@ -194,42 +202,50 @@ public final class DedupGlobalStep<S> extends FilterStep<S> implements Traversal
         while (this.starts.hasNext()) {
             final Traverser.Admin<S> traverser = this.starts.next();
             final Object object;
+            boolean productive;
             if (null != this.dedupLabels) {
                 object = new ArrayList<>(this.dedupLabels.size());
                 for (final String label : this.dedupLabels) {
-                    ((List) object).add(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal));
+                    final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, label, traverser), this.dedupTraversal);
+                    if (!product.isProductive()) break;
+                    ((List) object).add(product.get());
                 }
+
+                productive = ((List) object).size() == this.dedupLabels.size();
             } else {
-                object = TraversalUtil.applyNullable(traverser, this.dedupTraversal);
+                final TraversalProduct product = TraversalUtil.produce(traverser, this.dedupTraversal);
+                productive = product.isProductive();
+                object = productive ? product.get() : null;
             }
-            if (!map.containsKey(object)) {
-                traverser.setBulk(1L);
-
-                // DetachedProperty and DetachedVertexProperty both have a transient for the Host element. that causes
-                // trouble for olap which ends up requiring the Host later. can't change the transient without some
-                // consequences: (1) we break gryo formatting and io tests start failing (2) storing the element with
-                // the property has the potential to bloat detached Element instances as it basically stores that data
-                // twice. Not sure if it's smart to change that at least in 3.4.x and not without some considerable
-                // thought as to what might be major changes. To work around the problem we will detach properties as
-                // references so that the parent element goes with it. Also, given TINKERPOP-2318 property comparisons
-                // have changed in such a way that allows this to work properly
-                if (this.onGraphComputer) {
-                    if (traverser.get() instanceof Property)
-                        traverser.set(ReferenceFactory.detach(traverser.get()));
-                    else
-                        traverser.set(DetachedFactory.detach(traverser.get(), true));
-                } else {
-                    traverser.set(traverser.get());
+
+            if (productive) {
+                if (!map.containsKey(object)) {
+                    traverser.setBulk(1L);
+
+                    // DetachedProperty and DetachedVertexProperty both have a transient for the Host element. that causes
+                    // trouble for olap which ends up requiring the Host later. can't change the transient without some
+                    // consequences: (1) we break gryo formatting and io tests start failing (2) storing the element with
+                    // the property has the potential to bloat detached Element instances as it basically stores that data
+                    // twice. Not sure if it's smart to change that at least in 3.4.x and not without some considerable
+                    // thought as to what might be major changes. To work around the problem we will detach properties as
+                    // references so that the parent element goes with it. Also, given TINKERPOP-2318 property comparisons
+                    // have changed in such a way that allows this to work properly
+                    if (this.onGraphComputer) {
+                        if (traverser.get() instanceof Property)
+                            traverser.set(ReferenceFactory.detach(traverser.get()));
+                        else
+                            traverser.set(DetachedFactory.detach(traverser.get(), true));
+                    } else {
+                        traverser.set(traverser.get());
+                    }
+                    map.put(object, traverser);
                 }
-                map.put(object, traverser);
             }
         }
+
         this.barrier = null;
         this.barrierIterator = null;
-        if (map.isEmpty())
-            throw FastNoSuchElementException.instance();
-        else
-            return map;
+        return map;
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
index 8fa93bf..7a7d9db 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/PathFilterStep.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -62,8 +63,20 @@ public final class PathFilterStep<S> extends FilterStep<S> implements FromToModu
         else {
             this.traversalRing.reset();
             final Path byPath = MutablePath.make();
-            path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels));
-            return byPath.isSimple() == this.isSimple;
+            final List<Set<String>> labels = path.labels();
+            final List<Object> objects = path.objects();
+            for (int ix = 0; ix < objects.size(); ix++) {
+                final Traversal.Admin t = traversalRing.next();
+                final TraversalProduct p = TraversalUtil.produce(objects.get(ix), t);
+
+                // if not productive we can quit coz this path is getting filtered
+                if (!p.isProductive()) break;
+
+                byPath.extend(p.get(), labels.get(ix));
+            }
+
+            // the path sizes must be equal or else it means a by() wasn't productive and that path will be filtered
+            return path.size() == byPath.size() && byPath.isSimple() == this.isSimple;
         }
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
index b342100..20c8396a 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/SampleGlobalStep.java
@@ -28,11 +28,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrie
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
 import java.util.Collections;
 import java.util.List;
+import java.util.Optional;
 import java.util.Random;
 import java.util.Set;
 
@@ -79,7 +81,7 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
     @Override
     public void processAllStarts() {
         while (this.starts.hasNext()) {
-            this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
+            this.createProjectedTraverser(this.starts.next()).ifPresent(traverserSet::add);
         }
     }
 
@@ -124,8 +126,20 @@ public final class SampleGlobalStep<S> extends CollectingBarrierStep<S> implemen
     }
 
 
-    private final ProjectedTraverser<S, Number> createProjectedTraverser(final Traverser.Admin<S> traverser) {
-        return new ProjectedTraverser<>(traverser, Collections.singletonList(TraversalUtil.apply(traverser, this.probabilityTraversal)));
+    private Optional<ProjectedTraverser<S, Number>> createProjectedTraverser(final Traverser.Admin<S> traverser) {
+        final TraversalProduct product = TraversalUtil.produce(traverser, this.probabilityTraversal);
+        if (product.isProductive()) {
+            final Object o = product.get();
+            if (!(o instanceof Number)) {
+                throw new IllegalStateException(String.format(
+                        "Traverser %s does not evaluate to a number with %s", traverser, this.probabilityTraversal));
+            }
+
+            return Optional.of(new ProjectedTraverser<>(traverser, Collections.singletonList((Number) product.get())));
+        } else {
+            return Optional.empty();
+        }
+
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
index 2ab3d9d..6820f88 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WherePredicateStep.java
@@ -28,6 +28,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -74,11 +75,21 @@ public final class WherePredicateStep<S> extends FilterStep<S> implements Scopin
         }
     }
 
-    private void setPredicateValues(final P<Object> predicate, final Traverser.Admin<S> traverser, final Iterator<String> selectKeysIterator) {
-        if (predicate instanceof ConnectiveP)
-            ((ConnectiveP<Object>) predicate).getPredicates().forEach(p -> this.setPredicateValues(p, traverser, selectKeysIterator));
-        else
-            predicate.setValue(TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, selectKeysIterator.next(), traverser), this.traversalRing.next()));
+    private boolean setPredicateValues(final P<Object> predicate, final Traverser.Admin<S> traverser, final Iterator<String> selectKeysIterator) {
+        if (predicate instanceof ConnectiveP) {
+            for (P<Object> p : ((ConnectiveP<Object>) predicate).getPredicates()) {
+                if (!this.setPredicateValues(p, traverser, selectKeysIterator))
+                    return false;
+            }
+
+            return true;
+        } else {
+            final TraversalProduct product = TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, selectKeysIterator.next(), traverser), this.traversalRing.next());
+            if (product.isProductive())
+                predicate.setValue(product.get());
+
+            return product.isProductive();
+        }
     }
 
     public Optional<P<?>> getPredicate() {
@@ -101,17 +112,18 @@ public final class WherePredicateStep<S> extends FilterStep<S> implements Scopin
 
     @Override
     protected boolean filter(final Traverser.Admin<S> traverser) {
-        final Object value = null == this.startKey ?
-                TraversalUtil.applyNullable(traverser, this.traversalRing.next()) :
-                TraversalUtil.applyNullable((S) this.getSafeScopeValue(Pop.last, this.startKey, traverser), this.traversalRing.next());
-        this.setPredicateValues(this.predicate, traverser, this.selectKeys.iterator());
+        final TraversalProduct product = null == this.startKey ?
+                TraversalUtil.produce(traverser, this.traversalRing.next()) :
+                TraversalUtil.produce((S) this.getSafeScopeValue(Pop.last, this.startKey, traverser), this.traversalRing.next());
+
+        final boolean predicateValuesProductive = this.setPredicateValues(this.predicate, traverser, this.selectKeys.iterator());
         this.traversalRing.reset();
-        return this.predicate.test(value);
+
+        return product.isProductive() && predicateValuesProductive && this.predicate.test(product.get());
     }
 
     @Override
     public String toString() {
-        // TODO: revert the predicates to their string form?
         return StringFactory.stepString(this, this.startKey, this.predicate, this.traversalRing);
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
index 0f3fa25..77fd379 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupCountStep.java
@@ -54,7 +54,7 @@ public class GroupCountStep<S, E> extends ReducingBarrierStep<S, Map<E, Long>> i
     @Override
     public Map<E, Long> projectTraverser(final Traverser.Admin<S> traverser) {
         final Map<E, Long> map = new HashMap<>(1);
-        map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), traverser.bulk());
+        TraversalUtil.produce(traverser, this.keyTraversal).ifProductive(p -> map.put((E) p, traverser.bulk()));
         return map;
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
index 2213b2e..ff7ba1c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/GroupStep.java
@@ -124,11 +124,15 @@ public final class GroupStep<S, K, V> extends ReducingBarrierStep<S, Map<K, V>>
             resetBarrierForProfiling = false;
         }
 
-        if (null == this.barrierStep) {
-            if (this.valueTraversal.hasNext())
-                map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.valueTraversal.next());
-        } else if (this.barrierStep.hasNextBarrier())
-            map.put(TraversalUtil.applyNullable(traverser, this.keyTraversal), (V) this.barrierStep.nextBarrier());
+        TraversalUtil.produce(traverser, this.keyTraversal).ifProductive(p -> {
+            if (null == this.barrierStep) {
+                if (this.valueTraversal.hasNext()) {
+                    map.put((K) p, (V) this.valueTraversal.next());
+                }
+            } else if (this.barrierStep.hasNextBarrier())
+                map.put((K) p, (V) this.barrierStep.nextBarrier());
+        });
+
         return map;
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
index 149f67a..612e20d 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
@@ -29,6 +29,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -45,7 +47,7 @@ import java.util.regex.Pattern;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class MathStep<S> extends ScalarMapStep<S, Double> implements ByModulating, TraversalParent, Scoping, PathProcessor {
+public final class MathStep<S> extends MapStep<S, Double> implements ByModulating, TraversalParent, Scoping, PathProcessor {
 
     private static final String CURRENT = "_";
     private final String equation;
@@ -61,16 +63,21 @@ public final class MathStep<S> extends ScalarMapStep<S, Double> implements ByMod
 
     @Override
     protected Traverser.Admin<Double> processNextStart() {
-        return PathProcessor.processTraverserPathLabels(super.processNextStart(), this.keepLabels);
-    }
+        final Traverser.Admin traverser = this.starts.next();
 
-    @Override
-    protected Double map(final Traverser.Admin<S> traverser) {
         final Expression localExpression = new Expression(this.expression.getExpression());
+        boolean productive = true;
         for (final String var : this.expression.getVariables()) {
-            final Object o = var.equals(CURRENT) ?
-                    TraversalUtil.applyNullable(traverser, this.traversalRing.next()) :
-                    TraversalUtil.applyNullable((S) this.getNullableScopeValue(Pop.last, var, traverser), this.traversalRing.next());
+            final TraversalProduct product = var.equals(CURRENT) ?
+                    TraversalUtil.produce(traverser, this.traversalRing.next()) :
+                    TraversalUtil.produce((S) this.getNullableScopeValue(Pop.last, var, traverser), this.traversalRing.next());
+
+            if (!product.isProductive()) {
+                productive = false;
+                break;
+            }
+
+            final Object o = product.get();
 
             // it's possible for ElementValueTraversal to return null or something that is possibly not a Number.
             // worth a check to try to return a nice error message. The TraversalRing<S, Number> is a bit optimistic
@@ -83,7 +90,11 @@ public final class MathStep<S> extends ScalarMapStep<S, Double> implements ByMod
             localExpression.setVariable(var, ((Number) o).doubleValue());
         }
         this.traversalRing.reset();
-        return localExpression.evaluate();
+
+        // if at least one of the traversals wasnt productive it will filter
+        return productive ?
+                PathProcessor.processTraverserPathLabels(traverser.split(localExpression.evaluate(), this), this.keepLabels) :
+                EmptyTraverser.instance();
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
index a7f7892..2723790 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderGlobalStep.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.util.CollectingBarrie
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.ProjectedTraverser;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.function.MultiComparator;
@@ -42,6 +43,7 @@ import java.util.Collections;
 import java.util.Comparator;
 import java.util.Iterator;
 import java.util.List;
+import java.util.Optional;
 import java.util.Random;
 import java.util.Set;
 import java.util.function.BinaryOperator;
@@ -79,7 +81,8 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
     @Override
     public void processAllStarts() {
         while (this.starts.hasNext()) {
-            this.traverserSet.add(this.createProjectedTraverser(this.starts.next()));
+            // only add the traverser if the comparator traversal was productive
+            this.createProjectedTraverser(this.starts.next()).ifPresent(traverserSet::add);
         }
     }
 
@@ -170,16 +173,20 @@ public final class OrderGlobalStep<S, C extends Comparable> extends CollectingBa
         return MemoryComputeKey.of(this.getId(), new OrderBiOperator<>(this.limit, this.multiComparator, this.random), false, true);
     }
 
-    private final ProjectedTraverser<S, Object> createProjectedTraverser(final Traverser.Admin<S> traverser) {
+    private Optional<ProjectedTraverser<S, Object>> createProjectedTraverser(final Traverser.Admin<S> traverser) {
         // this was ProjectedTraverser<S, C> but the projection may not be C in the case of a lambda where a
         // Comparable may not be expected but rather an object that can be compared in any way given a lambda.
         // not sure why this is suddenly an issue but Intellij would not let certain tests pass without this
         // adjustment here.
         final List<Object> projections = new ArrayList<>(this.comparators.size());
         for (final Pair<Traversal.Admin<S, C>, Comparator<C>> pair : this.comparators) {
-            projections.add(TraversalUtil.apply(traverser, pair.getValue0()));
+            final TraversalProduct product = TraversalUtil.produce(traverser, pair.getValue0());
+            if (!product.isProductive()) break;
+            projections.add(product.get());
         }
-        return new ProjectedTraverser(traverser, projections);
+
+        // if a traversal wasn't productive then the sizes wont match and it will filter
+        return projections.size() == comparators.size() ? Optional.of(new ProjectedTraverser(traverser, projections)) : Optional.empty();
     }
 
     private final MultiComparator<C> createMultiComparator() {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
index eb3a5f8..fdcfaa4 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderLocalStep.java
@@ -27,8 +27,9 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.ComparatorHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Seedable;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
-import org.apache.tinkerpop.gremlin.util.function.ChainedComparator;
 import org.javatuples.Pair;
 
 import java.util.ArrayList;
@@ -48,7 +49,6 @@ import java.util.stream.Collectors;
 public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep<S, S> implements ComparatorHolder<S, C>, ByModulating, TraversalParent, Seedable {
 
     private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
-    private ChainedComparator<S, C> chainedComparator = null;
     private final Random random = new Random();
 
     public OrderLocalStep(final Traversal.Admin traversal) {
@@ -62,15 +62,73 @@ public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep
 
     @Override
     protected S map(final Traverser.Admin<S> traverser) {
-        if (null == this.chainedComparator)
-            this.chainedComparator = new ChainedComparator<>(false, this.comparators);
         final S start = traverser.get();
-        if (start instanceof Collection)
-            return (S) sortCollection((Collection) start, this.chainedComparator);
-        else if (start instanceof Map)
-            return (S) sortMap((Map) start, this.chainedComparator);
-        else
-            return start;
+
+        // modulate each traverser object and keep its value to sort on as Pair<traverser-object,List<modulated-object>>
+        // as of 3.6.0 this transformation occurs in place and values held in memory so that unproductive by() values
+        // can be filtered. without this trade-off for more memory it would be necessary to apply the modulation twice
+        // once for the filter and once for the compare.
+        if (start instanceof Collection) {
+            final Collection<S> original = (Collection<S>) start;
+            final List<Pair<S, List<C>>> filteredAndModulated = filterAndModulate(original);
+            return (S) filteredAndModulated.stream().map(Pair::getValue0).collect(Collectors.toList());
+        } else if (start instanceof Map) {
+            final List<Pair<S, List<C>>> filteredAndModulated = filterAndModulate(((Map) start).entrySet());
+            final LinkedHashMap sortedMap = new LinkedHashMap();
+            filteredAndModulated.stream().map(Pair::getValue0).map(entry -> (Map.Entry) entry).
+                    forEach(entry -> sortedMap.put(entry.getKey(), entry.getValue()));
+            return (S) sortedMap;
+        }
+
+        return start;
+    }
+
+    /**
+     * Take the collection and apply modulators removing traversers that have modulators that aren't productive.
+     */
+    private List<Pair<S, List<C>>> filterAndModulate(final Collection<S> original) {
+        if (comparators.isEmpty())
+            this.comparators.add(new Pair<>(new IdentityTraversal(), (Comparator) Order.asc));
+
+        // detect shuffle and optimize by either ignoring other comparators if shuffle is last or
+        // ignoring comparators that are shuffles if they are in the middle
+        final boolean isShuffle = (Comparator) this.comparators.get(this.comparators.size() - 1).getValue1() == Order.shuffle;
+        final List<Pair<Traversal.Admin<S, C>, Comparator<C>>> relevantComparators = isShuffle ?
+                this.comparators :
+                this.comparators.stream().filter(p -> (Comparator) p.getValue1() != Order.shuffle).collect(Collectors.toList());
+
+        final List<Pair<S, List<C>>> filteredAndModulated = new ArrayList<>();
+        final List<Traversal.Admin<S, C>> modulators = relevantComparators.stream().map(Pair::getValue0).collect(Collectors.toList());
+        for (S s : original) {
+            // filter out unproductive by()
+            final List<C> modulations = modulators.stream().map(t -> TraversalUtil.produce(s, t)).
+                    filter(TraversalProduct::isProductive).
+                    map(product -> (C) product.get()).collect(Collectors.toList());
+
+            // when sizes arent the same it means a by() wasn't productive and it is ignored
+            if (modulations.size() == modulators.size()) {
+                filteredAndModulated.add(Pair.with(s, modulations));
+            }
+        }
+
+        if (isShuffle) {
+            Collections.shuffle(filteredAndModulated, random);
+        } else {
+            // sort the filter/modulated local list in place using the index of the modulator/comparators
+            Collections.sort(filteredAndModulated, (o1, o2) -> {
+                final List<C> modulated1 = o1.getValue1();
+                final List<C> modulated2 = o2.getValue1();
+                for (int ix = 0; ix < modulated1.size(); ix++) {
+                    final int comparison = relevantComparators.get(ix).getValue1().compare(modulated1.get(ix), modulated2.get(ix));
+                    if (comparison != 0)
+                        return comparison;
+                }
+
+                return 0;
+            });
+        }
+
+        return filteredAndModulated;
     }
 
     @Override
@@ -138,7 +196,6 @@ public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep
         for (final Pair<Traversal.Admin<S, C>, Comparator<C>> comparator : this.comparators) {
             clone.comparators.add(new Pair<>(comparator.getValue0().clone(), comparator.getValue1()));
         }
-        clone.chainedComparator = null;
         return clone;
     }
 
@@ -147,29 +204,4 @@ public final class OrderLocalStep<S, C extends Comparable> extends ScalarMapStep
         super.setTraversal(parentTraversal);
         this.comparators.stream().map(Pair::getValue0).forEach(TraversalParent.super::integrateChild);
     }
-
-    /////////////
-
-    private <A> List<A> sortCollection(final Collection<A> collection, final ChainedComparator comparator) {
-        if (collection instanceof List) {
-            if (comparator.isShuffle())
-                Collections.shuffle((List) collection, random);
-            else
-                Collections.sort((List) collection, comparator);
-            return (List<A>) collection;
-        } else {
-            return sortCollection(new ArrayList<>(collection), comparator);
-        }
-    }
-
-    private <K, V> Map<K, V> sortMap(final Map<K, V> map, final ChainedComparator comparator) {
-        final List<Map.Entry<K, V>> entries = new ArrayList<>(map.entrySet());
-        if (comparator.isShuffle())
-            Collections.shuffle(entries, random);
-        else
-            Collections.sort(entries, comparator);
-        final LinkedHashMap<K, V> sortedMap = new LinkedHashMap<>();
-        entries.forEach(entry -> sortedMap.put(entry.getKey(), entry.getValue()));
-        return sortedMap;
-    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
index 07c8d7d..8d073a9 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathStep.java
@@ -27,6 +27,8 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.PathProcessor;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.MutablePath;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -38,7 +40,7 @@ import java.util.Set;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class PathStep<S> extends ScalarMapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating, FromToModulating {
+public final class PathStep<S> extends MapStep<S, Path> implements TraversalParent, PathProcessor, ByModulating, FromToModulating {
 
     private TraversalRing<Object, Object> traversalRing;
     private Set<String> keepLabels;
@@ -51,20 +53,6 @@ public final class PathStep<S> extends ScalarMapStep<S, Path> implements Travers
     }
 
     @Override
-    protected Path map(final Traverser.Admin<S> traverser) {
-        final Path path = traverser.path().subPath(this.fromLabel, this.toLabel);
-        if (this.traversalRing.isEmpty())
-            return path;
-        else {
-            this.traversalRing.reset();
-            final Path byPath = MutablePath.make();
-            path.forEach((object, labels) -> byPath.extend(TraversalUtil.applyNullable(object, this.traversalRing.next()), labels));
-            return byPath;
-        }
-    }
-
-
-    @Override
     public PathStep<S> clone() {
         final PathStep<S> clone = (PathStep<S>) super.clone();
         clone.traversalRing = this.traversalRing.clone();
@@ -122,7 +110,31 @@ public final class PathStep<S> extends ScalarMapStep<S, Path> implements Travers
 
     @Override
     protected Traverser.Admin<Path> processNextStart() {
-        return PathProcessor.processTraverserPathLabels(super.processNextStart(), this.keepLabels);
+        final Traverser.Admin<S> traverser = this.starts.next();
+        final Path path = traverser.path().subPath(this.fromLabel, this.toLabel);
+        if (this.traversalRing.isEmpty())
+            return PathProcessor.processTraverserPathLabels(traverser.split(path, this), this.keepLabels);
+        else {
+            this.traversalRing.reset();
+            final Path byPath = MutablePath.make();
+
+            final List<Set<String>> labels = path.labels();
+            final List<Object> objects = path.objects();
+            for (int ix = 0; ix < objects.size(); ix++) {
+                final Traversal.Admin t = traversalRing.next();
+                final TraversalProduct p = TraversalUtil.produce(objects.get(ix), t);
+
+                // if not productive we can quit coz this path is getting filtered
+                if (!p.isProductive()) break;
+
+                byPath.extend(p.get(), labels.get(ix));
+            }
+
+            // the path sizes must be equal or else it means a by() wasn't productive and that path will be filtered
+            return path.size() == byPath.size() ?
+                    PathProcessor.processTraverserPathLabels(traverser.split(byPath, this), this.keepLabels) :
+                    EmptyTraverser.instance();
+        }
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
index b97c8d6..1aa9eae 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectStep.java
@@ -52,7 +52,7 @@ public final class ProjectStep<S, E> extends ScalarMapStep<S, Map<String, E>> im
     protected Map<String, E> map(final Traverser.Admin<S> traverser) {
         final Map<String, E> end = new LinkedHashMap<>(this.projectKeys.size(), 1.0f);
         for (final String projectKey : this.projectKeys) {
-            end.put(projectKey, TraversalUtil.applyNullable(traverser, this.traversalRing.next()));
+            TraversalUtil.produce(traverser, this.traversalRing.next()).ifProductive(p -> end.put(projectKey, (E) p));
         }
         this.traversalRing.reset();
         return end;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
index 12cd6be..35f83cd 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PropertyMapStep.java
@@ -26,6 +26,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Parameters;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.WithOptions;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.Element;
@@ -39,6 +40,7 @@ import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collections;
+import java.util.HashSet;
 import java.util.Iterator;
 import java.util.LinkedHashMap;
 import java.util.List;
@@ -108,8 +110,15 @@ public class PropertyMapStep<K,E> extends ScalarMapStep<Element, Map<K, E>>
             }
         }
         if (!traversalRing.isEmpty()) {
-            for (final Object key : map.keySet()) {
-                map.compute(key, (k, v) -> TraversalUtil.applyNullable(v, (Traversal.Admin) this.traversalRing.next()));
+            // will cop a ConcurrentModification if a key is dropped so need this little copy here
+            final Set<Object> keys = new HashSet<>(map.keySet());
+            for (final Object key : keys) {
+                map.compute(key, (k, v) -> {
+                    final TraversalProduct product = TraversalUtil.produce(v, (Traversal.Admin) this.traversalRing.next());
+
+                    // compute() should take the null and remove the key
+                    return product.isProductive() ? product.get() : null;
+                });
             }
             this.traversalRing.reset();
         }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
index 976c512..b2de4b0 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectOneStep.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
@@ -59,7 +60,11 @@ public final class SelectOneStep<S, E> extends MapStep<S, E> implements Traversa
         try {
             final S o = getScopeValue(pop, selectKey, traverser);
             if (null == o) return traverser.split(null, this);
-            final Traverser.Admin<E> outTraverser = traverser.split(TraversalUtil.applyNullable(o, this.selectTraversal), this);
+
+            final TraversalProduct product = TraversalUtil.produce(o, this.selectTraversal);
+            if (!product.isProductive()) return EmptyTraverser.instance();
+
+            final Traverser.Admin<E> outTraverser = traverser.split((E) product.get(), this);
             if (!(this.getTraversal().getParent() instanceof MatchStep))
                 PathProcessor.processTraverserPathLabels(outTraverser, this.keepLabels);
             return outTraverser;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
index 9edde9d..05a6a5b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectStep.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.Scoping;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -69,8 +70,17 @@ public final class SelectStep<S, E> extends MapStep<S, Map<String, E>> implement
         try {
             for (final String selectKey : this.selectKeys) {
                 final E end = this.getScopeValue(this.pop, selectKey, traverser);
-                bindings.put(selectKey, TraversalUtil.applyNullable(end, this.traversalRing.next()));
+                final TraversalProduct product = TraversalUtil.produce(end, this.traversalRing.next());
+
+                if (!product.isProductive()) break;
+
+                bindings.put(selectKey, (E) product.get());
             }
+
+            // bindings should be the same size as keys or else there was an uproductive by() in which case we filter
+            // with an EmptyTraverser
+            if (bindings.size() != selectKeys.size()) return EmptyTraverser.instance();
+
         } catch (KeyNotFoundException nfe) {
             return EmptyTraverser.instance();
         } finally {
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
index 1904859..ee70053 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/TreeStep.java
@@ -27,6 +27,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ReducingBarrierStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.Tree;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalRing;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
@@ -81,10 +82,13 @@ public final class TreeStep<S> extends ReducingBarrierStep<S, Tree> implements T
         Tree depth = topTree;
         final Path path = traverser.path();
         for (int i = 0; i < path.size(); i++) {
-            final Object object = TraversalUtil.applyNullable(path.<Object>get(i), this.traversalRing.next());
-            if (!depth.containsKey(object))
-                depth.put(object, new Tree<>());
-            depth = (Tree) depth.get(object);
+            final TraversalProduct product = TraversalUtil.produce(path.<Object>get(i), this.traversalRing.next());
+            if (product.isProductive()) {
+                final Object object = product.get();
+                if (!depth.containsKey(object))
+                    depth.put(object, new Tree<>());
+                depth = (Tree) depth.get(object);
+            }
         }
         this.traversalRing.reset();
         return topTree;
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
index 0f75963..c8fa203 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateGlobalStep.java
@@ -31,6 +31,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequire
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.TraverserSet;
 import org.apache.tinkerpop.gremlin.process.traversal.util.FastNoSuchElementException;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
+import org.apache.tinkerpop.gremlin.structure.util.CloseableIterator;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 import org.apache.tinkerpop.gremlin.util.function.BulkSetSupplier;
 
@@ -125,8 +126,11 @@ public final class AggregateGlobalStep<S> extends AbstractStep<S, S> implements
             final BulkSet<Object> bulkSet = new BulkSet<>();
             while (this.starts.hasNext()) {
                 final Traverser.Admin<S> traverser = this.starts.next();
-                bulkSet.add(TraversalUtil.applyNullable(traverser, this.aggregateTraversal), traverser.bulk());
-                traverser.setStepId(this.getNextStep().getId()); // when barrier is reloaded, the traversers should be at the next step
+                TraversalUtil.produce(traverser, aggregateTraversal).ifProductive(p -> bulkSet.add(p, traverser.bulk()));
+
+                traverser.setStepId(this.getNextStep().getId());
+
+                // when barrier is reloaded, the traversers should be at the next step
                 this.barrier.add(traverser);
             }
             this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
index 3c7c0fa..7331caf 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateLocalStep.java
@@ -53,7 +53,7 @@ public final class AggregateLocalStep<S> extends SideEffectStep<S> implements Si
     @Override
     protected void sideEffect(final Traverser.Admin<S> traverser) {
         final BulkSet<Object> bulkSet = new BulkSet<>();
-        bulkSet.add(TraversalUtil.applyNullable(traverser, this.storeTraversal), traverser.bulk());
+        TraversalUtil.produce(traverser, this.storeTraversal).ifProductive(p -> bulkSet.add(p, traverser.bulk()));
         this.getTraversal().getSideEffects().add(this.sideEffectKey, bulkSet);
     }
 
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
index bd0e828..b19f099 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/SackValueStep.java
@@ -23,7 +23,10 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.step.ByModulating;
 import org.apache.tinkerpop.gremlin.process.traversal.step.LambdaHolder;
 import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.AbstractStep;
 import org.apache.tinkerpop.gremlin.process.traversal.traverser.TraverserRequirement;
+import org.apache.tinkerpop.gremlin.process.traversal.traverser.util.EmptyTraverser;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalProduct;
 import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalUtil;
 import org.apache.tinkerpop.gremlin.structure.util.StringFactory;
 
@@ -35,7 +38,7 @@ import java.util.function.BiFunction;
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
  */
-public final class SackValueStep<S, A, B> extends SideEffectStep<S> implements TraversalParent, ByModulating, LambdaHolder {
+public final class SackValueStep<S, A, B> extends AbstractStep<S, S> implements TraversalParent, ByModulating, LambdaHolder {
 
     private Traversal.Admin<S, B> sackTraversal = null;
 
@@ -63,8 +66,17 @@ public final class SackValueStep<S, A, B> extends SideEffectStep<S> implements T
     }
 
     @Override
-    protected void sideEffect(final Traverser.Admin<S> traverser) {
-        traverser.sack(this.sackFunction.apply(traverser.sack(), null == this.sackTraversal ? (B) traverser.get() : TraversalUtil.apply(traverser, this.sackTraversal)));
+    protected Traverser.Admin<S> processNextStart() {
+        final Traverser.Admin<S> traverser = this.starts.next();
+        if (null == sackTraversal) {
+            traverser.sack(this.sackFunction.apply(traverser.sack(), (B) traverser.get()));
+            return traverser;
+        } else {
+            final TraversalProduct product = TraversalUtil.produce(traverser, this.sackTraversal);
+            if (!product.isProductive()) return EmptyTraverser.instance();
+            traverser.sack(this.sackFunction.apply(traverser.sack(), (B) product.get()));
+            return traverser;
+        }
     }
 
     @Override
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalProduct.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalProduct.java
new file mode 100644
index 0000000..9711d81
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalProduct.java
@@ -0,0 +1,55 @@
+/*
+ * 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.tinkerpop.gremlin.process.traversal.Traversal;
+
+import java.util.function.Consumer;
+
+/**
+ * This class represents the state of the output of a child {@link Traversal} where it is either productive or not.
+ * It is productive if it has at least one traverser within it, even if that traverser is holding a {@code null}.
+ */
+public final class TraversalProduct {
+    public static final TraversalProduct UNPRODUCTIVE = new TraversalProduct();
+    private final Object o;
+    private final boolean productive;
+
+    private TraversalProduct() {
+        this.o = null; // null is valid technically but productive=false trumps it
+        this.productive = false;
+    }
+
+    TraversalProduct(final Object o) {
+        this.o = o;
+        this.productive = true;
+    }
+
+    public Object get() {
+        return o;
+    }
+
+    public boolean isProductive() {
+        return productive;
+    }
+
+    public void ifProductive(final Consumer<Object> c) {
+        if (productive) c.accept(o);
+    }
+}
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java
index 4b2b15f..1acb547 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalUtil.java
@@ -34,12 +34,8 @@ public final class TraversalUtil {
     private TraversalUtil() {
     }
 
-    public static final <S, E> E apply(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
-        final Traverser.Admin<S> split = traverser.split();
-        split.setSideEffects(traversal.getSideEffects());
-        split.setBulk(1l);
-        traversal.reset();
-        traversal.addStart(split);
+    public static <S, E> E apply(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+        final Traverser<S> split = prepare(traverser, traversal);
         try {
             return traversal.next(); // map
         } catch (final NoSuchElementException e) {
@@ -52,23 +48,43 @@ public final class TraversalUtil {
         }
     }
 
-    public static final <S, E> Iterator<E> applyAll(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
-        final Traverser.Admin<S> split = traverser.split();
-        split.setSideEffects(traversal.getSideEffects());
-        split.setBulk(1l);
+    public static <S, E> E apply(final S start, final Traversal.Admin<S, E> traversal) {
         traversal.reset();
-        traversal.addStart(split);
+        traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
+        try {
+            return traversal.next(); // map
+        } catch (final NoSuchElementException e) {
+            throw new IllegalArgumentException("The provided start does not map to a value: " + start + "->" + traversal);
+        } finally {
+            //Close the traversal to release any underlying resources.
+            CloseableIterator.closeIterator(traversal);
+        }
+    }
+
+    public static <S, E> E applyNullable(final S start, final Traversal.Admin<S, E> traversal) {
+        return null == traversal ? (E) start : TraversalUtil.apply(start, traversal);
+    }
+
+    public static <S, E> E applyNullable(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+        return null == traversal ? (E) traverser.get() : TraversalUtil.apply(traverser, traversal);
+    }
+
+    public static <S, E> Iterator<E> applyAll(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+        prepare(traverser, traversal);
         return traversal; // flatmap
     }
 
-    public static final <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal, E end) {
+    public static <S, E> Iterator<E> applyAll(final S start, final Traversal.Admin<S, E> traversal) {
+        traversal.reset();
+        traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
+        return traversal; // flatMap
+    }
+
+    public static <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal, E end) {
         if (null == end) return TraversalUtil.test(traverser, traversal);
 
-        final Traverser.Admin<S> split = traverser.split();
-        split.setSideEffects(traversal.getSideEffects());
-        split.setBulk(1l);
-        traversal.reset();
-        traversal.addStart(split);
+        prepare(traverser, traversal);
+
         final Step<?, E> endStep = traversal.getEndStep();
         boolean result = false;
         while (traversal.hasNext()) {
@@ -85,17 +101,44 @@ public final class TraversalUtil {
         return result;
     }
 
-    public static final <S, E> E applyNullable(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
-        return null == traversal ? (E) traverser.get() : TraversalUtil.apply(traverser, traversal);
+    public static <S, E> TraversalProduct produce(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+        if (null == traversal) {
+            return new TraversalProduct(traverser.get());
+        } else {
+            prepare(traverser, traversal);
+            try {
+                if (traversal.hasNext()) {
+                    return new TraversalProduct(traversal.next());
+                } else {
+                    return TraversalProduct.UNPRODUCTIVE;
+                }
+            } finally {
+                CloseableIterator.closeIterator(traversal);
+            }
+        }
     }
 
-    public static final <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
-        final Traverser.Admin<S> split = traverser.split();
-        split.setSideEffects(traversal.getSideEffects());
-        split.setBulk(1l);
-        traversal.reset();
-        traversal.addStart(split);
-        boolean val =  traversal.hasNext(); // filter
+    public static <S, E> TraversalProduct produce(final S start, final Traversal.Admin<S, E> traversal) {
+        if (null == traversal) {
+            return new TraversalProduct(start);
+        } else {
+            traversal.reset();
+            traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1L));
+            try {
+                if (traversal.hasNext()) {
+                    return new TraversalProduct(traversal.next());
+                } else {
+                    return TraversalProduct.UNPRODUCTIVE;
+                }
+            } finally {
+                CloseableIterator.closeIterator(traversal);
+            }
+        }
+    }
+
+    public static <S, E> boolean test(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+        prepare(traverser, traversal);
+        final boolean val =  traversal.hasNext(); // filter
 
         //Close the traversal to release any underlying resources.
         CloseableIterator.closeIterator(traversal);
@@ -103,28 +146,7 @@ public final class TraversalUtil {
         return val;
     }
 
-    ///////
-
-    public static final <S, E> E apply(final S start, final Traversal.Admin<S, E> traversal) {
-        traversal.reset();
-        traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
-        try {
-            return traversal.next(); // map
-        } catch (final NoSuchElementException e) {
-            throw new IllegalArgumentException("The provided start does not map to a value: " + start + "->" + traversal);
-        } finally {
-            //Close the traversal to release any underlying resources.
-            CloseableIterator.closeIterator(traversal);
-        }
-    }
-
-    public static final <S, E> Iterator<E> applyAll(final S start, final Traversal.Admin<S, E> traversal) {
-        traversal.reset();
-        traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
-        return traversal; // flatMap
-    }
-
-    public static final <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal, final E end) {
+    public static <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal, final E end) {
         if (null == end) return TraversalUtil.test(start, traversal);
 
         traversal.reset();
@@ -145,11 +167,7 @@ public final class TraversalUtil {
         return result;
     }
 
-    public static final <S, E> E applyNullable(final S start, final Traversal.Admin<S, E> traversal) {
-        return null == traversal ? (E) start : TraversalUtil.apply(start, traversal);
-    }
-
-    public static final <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal) {
+    public static <S, E> boolean test(final S start, final Traversal.Admin<S, E> traversal) {
         traversal.reset();
         traversal.addStart(traversal.getTraverserGenerator().generate(start, traversal.getStartStep(), 1l));
         boolean result = traversal.hasNext(); // filter
@@ -159,4 +177,13 @@ public final class TraversalUtil {
 
         return result;
     }
+
+    public static <S, E> Traverser<S> prepare(final Traverser.Admin<S> traverser, final Traversal.Admin<S, E> traversal) {
+        final Traverser.Admin<S> split = traverser.split();
+        split.setSideEffects(traversal.getSideEffects());
+        split.setBulk(1L);
+        traversal.reset();
+        traversal.addStart(split);
+        return split;
+    }
 }
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java
index 984767f..1a7b114 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/function/ChainedComparator.java
@@ -33,7 +33,9 @@ import java.util.stream.Collectors;
 
 /**
  * @author Marko A. Rodriguez (http://markorodriguez.com)
+ * @deprecated As of release 3.6.0, not replaced.
  */
+@Deprecated
 public final class ChainedComparator<S, C extends Comparable> implements Comparator<S>, Serializable, Cloneable {
 
     private List<Pair<Traversal.Admin<S, C>, Comparator<C>>> comparators = new ArrayList<>();
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java
index 4adc701..c28ffc4 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/PathTest.java
@@ -33,6 +33,8 @@ import java.util.List;
 import java.util.function.Supplier;
 import java.util.stream.Collectors;
 
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -529,4 +531,22 @@ public class PathTest {
             assertEquals(1, subPath.labels().get(2).size());
         });
     }
+
+    @Test
+    public void shouldHandleNullSemanticsCorrectly() {
+        PATH_SUPPLIERS.forEach(supplier -> {
+            final Path p = supplier.get();
+            assertThat(p.isSimple(), is(true));
+            p.extend(null, Collections.emptySet());
+            assertThat(p.isSimple(), is(true));
+            p.extend(1, Collections.emptySet());
+            assertThat(p.isSimple(), is(true));
+            p.extend(null, Collections.emptySet());
+
+            // immutable path won't change so its just going to always be empty and thus always simple
+            if (!(p instanceof ImmutablePath)) {
+                assertThat(p.isSimple(), is(false));
+            }
+        });
+    }
 }
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
index 88bb949..47cd52f 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/PathProcessorStrategyTest.java
@@ -43,6 +43,7 @@ import java.util.Arrays;
 import java.util.Collection;
 import java.util.Collections;
 import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.coalesce;
 import static org.junit.Assert.assertEquals;
@@ -53,9 +54,9 @@ import static org.junit.Assert.assertEquals;
 @RunWith(Parameterized.class)
 public class PathProcessorStrategyTest {
     private static final Translator.ScriptTranslator translator = GroovyTranslator.of("__");
-    private static final Collection<TraversalStrategy> withoutProductiveByStrategy =
-            TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList().stream().
-                    filter(s -> s != ProductiveByStrategy.instance()).collect(Collectors.toList());
+    private static final Collection<TraversalStrategy> withProductiveByStrategy =
+            Stream.concat(Stream.of(ProductiveByStrategy.instance()),
+                          TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList().stream()).collect(Collectors.toList());
 
     @Parameterized.Parameter(value = 0)
     public Traversal.Admin original;
@@ -94,12 +95,12 @@ public class PathProcessorStrategyTest {
                 {__.select("a").by(__.outE().count()), __.select("a").map(__.outE().count()), Collections.emptyList()},
                 {__.select("a").by("name"), __.select("a").map(new ValueTraversal<>("name")), Collections.emptyList()},
                 {__.select("a").out(), __.select("a").out(), Collections.emptyList()},
-                {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
-                {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
-                {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
-                {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by("name"), withoutProductiveByStrategy},
-                {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").map(__.values("name")), withoutProductiveByStrategy},
-                {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").map(__.values("name")), withoutProductiveByStrategy},
+                {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), withProductiveByStrategy},
+                {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), withProductiveByStrategy},
+                {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").by(new ValueTraversal<>("name", coalesce(new ValueTraversal<>("name"), new ConstantTraversal(null)).asAdmin())), withProductiveByStrategy},
+                {__.select(Pop.all, "a").by(__.values("name")), __.select(Pop.all, "a").by("name"), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+                {__.select(Pop.last, "a").by(__.values("name")), __.select(Pop.last, "a").map(__.values("name")), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
+                {__.select(Pop.first, "a").by(__.values("name")), __.select(Pop.first, "a").map(__.values("name")), TraversalStrategies.GlobalCache.getStrategies(Graph.class).toList()},
                 // select("a","b")
                 {__.select("a", "b"), __.select("a", "b"), Collections.emptyList()},
                 {__.select("a", "b").by(), __.select("a", "b").by(), Collections.emptyList()},
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
index 412a16f..ace783d 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/GherkinTestRunner.cs
@@ -44,7 +44,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
             new Dictionary<string, IgnoreReason>
             {
                 // Add here the name of scenarios to ignore and the reason, e.g.:
-                {"g_V_group_byXageX", IgnoreReason.NullKeysInMapNotSupported},
+                {"g_withStrategiesXProductiveByStrategyX_V_group_byXageX", IgnoreReason.NullKeysInMapNotSupported},
+                {"g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX", IgnoreReason.NullKeysInMapNotSupported},
 
                 // they are not failing as a result of the Gremlin itself - they are failing because of shortcomings in
                 // the test suite.
diff --git a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
index 8977404..7186968 100644
--- a/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
+++ b/gremlin-dotnet/test/Gremlin.Net.IntegrationTest/Gherkin/Gremlin.cs
@@ -131,6 +131,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_coinX0X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Coin(0.0)}}, 
                {"g_withStrategiesXSeedStrategyX_V_coinX50X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Coin(0.5)}}, 
                {"g_VX1X_outXcreatedX_inXcreatedX_cyclicPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("created").In("created").CyclicPath()}}, 
+               {"g_VX1X_both_both_cyclicPath_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Both().Both().CyclicPath().By("age")}}, 
                {"g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("created").In("created").CyclicPath().Path()}}, 
                {"g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out("created").As("b").In("created").As("c").CyclicPath().From("a").To("b").Path()}}, 
                {"g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(0).V().Both().Coalesce<object>(__.Has("name","marko").Both(),__.Constant<object>(0)).CyclicPath().Path()}}, 
@@ -155,6 +156,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_both_properties_dedup_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Properties<object>().Dedup().Count()}}, 
                {"g_V_both_properties_properties_dedup_count", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Properties<object>().Properties<object>().Dedup().Count()}}, 
                {"g_V_order_byXname_descX_barrier_dedup_age_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By("name",Order.Desc).Barrier().Dedup().By("age").Values<object>("name")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Order().By("name",Order.Desc).Barrier().Dedup().By("age").Values<object>("name")}}, 
+               {"g_V_both_dedup_age_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Dedup().By("age").Values<object>("name")}}, 
+               {"g_V_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Both().As("b").Both().As("c").Dedup("a","b").By("age").Select<object>("a","b","c").By("name")}}, 
                {"g_V_drop", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV().As("a").AddV().As("b").AddE("knows").To("a"), (g,p) =>g.V().Drop(), (g,p) =>g.V(), (g,p) =>g.E()}}, 
                {"g_V_outE_drop", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV().As("a").AddV().As("b").AddE("knows").To("a"), (g,p) =>g.V().OutE().Drop(), (g,p) =>g.V(), (g,p) =>g.E()}}, 
                {"g_V_properties_drop", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.AddV().Property("name","bob").AddV().Property("name","alice"), (g,p) =>g.V().Properties<object>().Drop(), (g,p) =>g.V(), (g,p) =>g.V().Properties<object>()}}, 
@@ -281,10 +285,12 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_localXoutE_sampleX1X_byXweightXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.OutE().Sample(1).By("weight"))}}, 
                {"g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_sampleX2X_foldXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Group<object,object>().By(T.Label).By(__.BothE().Values<object>("weight").Order().Sample(2).Fold()).Unfold<object>()}}, 
                {"g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_fold_sampleXlocal_5XXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Group<object,object>().By(T.Label).By(__.BothE().Values<object>("weight").Order().Fold().Sample(Scope.Local,5)).Unfold<object>()}}, 
+               {"g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new SeedStrategy(seed: 999999)).V().Order().By(T.Label,Order.Desc).Sample(1).By("age")}}, 
                {"g_VX1X_outXcreatedX_inXcreatedX_simplePath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out("created").In("created").SimplePath()}}, 
                {"g_V_repeatXboth_simplePathX_timesX3X_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat(__.Both().SimplePath()).Times(3).Path()}}, 
                {"g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Out().As("b").Out().As("c").SimplePath().By(T.Label).From("b").To("c").Path().By("name")}}, 
                {"g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_simplePath_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(0).V().Both().Coalesce<object>(__.Has("name","marko").Both(),__.Constant<object>(0)).SimplePath().Path()}}, 
+               {"g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().As("a").Both().As("b").SimplePath().Path().By("age").From("a").To("b")}}, 
                {"g_V_valuesXnameX_order_tailXglobal_2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Tail<object>(Scope.Global,2)}}, 
                {"g_V_valuesXnameX_order_tailX2X", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Tail<object>(2)}}, 
                {"g_V_valuesXnameX_order_tail", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Order().Tail<object>()}}, 
@@ -323,6 +329,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").OutE("created").As("b").InV().As("c").In("created").As("d").Where("a",P.Lt("b").Or(P.Gt("c")).And(P.Neq("d"))).By("age").By("weight").By(__.In("created").Values<object>("age").Min<object>()).Select<object>("a","c [...]
                {"g_VX1X_asXaX_out_hasXageX_whereXgtXaXX_byXageX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).As("a").Out().Has("age").Where(P.Gt("a")).By("age").Values<object>("name")}}, 
                {"g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid3"]).As("a").In().Out().As("b").Where("a",P.Eq("b")).By("age").Values<object>("name")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V(p["vid3"]).As("a").In().Out().As("b").Where("a",P.Eq("b")).By("age").Values<object>("name")}}, 
                {"g_V_coworker", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).Aggregate("p").As("p1").Values<object>("name").As("p1n").Select<object>("p").Unfold<object>().Where(P.Neq("p1")).As("p2").Values<object>("name").As("p2n").Select<object>("p2").Out("created").Choose<object>(__.In("created").Where(P.Eq("p1")),__.Values<object>("name"),__.Constant<object>(p["xx1"])).Group<object,object>(). [...]
                {"g_V_coworker_with_midV", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).As("p1").V().HasLabel("person").Where(P.Neq("p1")).Filter(__.OutE("created")).As("p2").Map<object>(__.Out("created").Where(__.In("created").As("p1")).Values<object>("name").Fold()).Group<object,object>().By(__.Select<object>("p1").By("name")).By(__.Group<object,object>().By(__.Select<object>("p2").By("name")). [...]
                {"g_V_playlist_paths", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("name","Bob_Dylan").In("sungBy").Order().By("name").As("a").Repeat(__.Out().Order().By("name").SimplePath().From("a")).Until(__.Out("writtenBy").Has("name","Johnny_Cash")).Limit<object>(1).As("b").Repeat(__.Out().Order().By("name").As("c").SimplePath().From("b").To("c")).Until(__.Out("sungBy").Has("name","Grateful_Dead")).Limit<object>(1).Path().From("a") [...]
@@ -451,6 +458,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_asXaX_outXcreatedX_asXbX_mathXb_plus_aX_byXinXcreatedX_countX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Out("created").As("b").Math("b + a").By(__.In("created").Count()).By("age")}}, 
                {"g_withSackX1X_injectX1X_repeatXsackXsumX_byXconstantX1XXX_timesX5X_emit_mathXsin__X_byXsackX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSack(1).Inject(1).Repeat(__.Sack(Operator.Sum).By(__.Constant<object>(1))).Times(5).Emit().Math("sin _").By(__.Sack<object>())}}, 
                {"g_V_projectXa_b_cX_byXbothE_weight_sumX_byXbothE_countX_byXnameX_order_byXmathXa_div_bX_descX_selectXcX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Project<object>("a","b","c").By(__.BothE().Values<object>("weight").Sum<object>()).By(__.BothE().Count()).By("name").Order().By(__.Math("a / b"),Order.Desc).Select<object>("c")}}, 
+               {"g_V_mathXit_plus_itXbyXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Math("_+_").By("age")}}, 
+               {"g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>().Math("_+_").By(__.Select<object>("age").Unfold<object>())}}, 
                {"g_V_age_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Max<object>()}}, 
                {"g_V_foo_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Max<object>()}}, 
                {"g_V_name_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Max<object>()}}, 
@@ -460,7 +469,9 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_aggregateXaX_byXageX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Max<object>()}}, 
                {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Max<object>()}}, 
                {"g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Max<object>(Scope.Local)}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Max<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXfooX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Max<object>()}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Max<object>()}}, 
                {"g_V_foo_fold_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Max<object>(Scope.Local)}}, 
                {"g_V_name_fold_maxXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Fold().Max<object>(Scope.Local)}}, 
                {"g_V_repeatXbothX_timesX5X_age_max", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat(__.Both()).Times(5).Values<object>("age").Max<object>()}}, 
@@ -471,9 +482,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_foo_fold_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Mean<object>(Scope.Local)}}, 
                {"g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_meanX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("software").Group<object,object>().By("name").By(__.BothE().Values<object>("weight").Mean<object>())}}, 
                {"g_V_aggregateXaX_byXageX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Mean<object>(Scope.Local)}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Mean<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXageX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Mean<object>()}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Mean<object>()}}, 
                {"g_V_aggregateXaX_byXfooX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Mean<object>(Scope.Local)}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Mean<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXfooX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Mean<object>()}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Mean<object>()}}, 
                {"g_injectXnull_10_20_nullX_mean", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null,p["xx1"],p["xx2"],null).Mean<object>()}}, 
                {"g_injectXlistXnull_10_20_nullXX_meanXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Mean<object>(Scope.Local)}}, 
                {"g_V_age_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Min<object>()}}, 
@@ -481,9 +496,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_name_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Min<object>()}}, 
                {"g_V_age_fold_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("age").Fold().Min<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXageX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Min<object>(Scope.Local)}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Min<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXageX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Min<object>()}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Min<object>()}}, 
                {"g_V_aggregateXaX_byXfooX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Min<object>(Scope.Local)}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Min<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXfooX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Min<object>()}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Min<object>()}}, 
                {"g_V_foo_fold_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Min<object>(Scope.Local)}}, 
                {"g_V_name_fold_minXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("name").Fold().Min<object>(Scope.Local)}}, 
                {"g_V_repeatXbothX_timesX5X_age_min", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Repeat(__.Both()).Times(5).Values<object>("age").Min<object>()}}, 
@@ -508,11 +527,16 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_both_hasLabelXpersonX_order_byXage_descX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().HasLabel("person").Order().By("age",Order.Desc).Values<object>("name")}}, 
                {"g_V_order_byXoutE_count_descX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By(__.OutE().Count(),Order.Desc)}}, 
                {"g_V_hasLabelXpersonX_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Order().By("age")}}, 
+               {"g_V_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Order().By("age")}}, 
+               {"g_V_fold_orderXlocalX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fold().Order(Scope.Local).By("age")}}, 
+               {"g_V_fold_orderXlocalX_byXage_descX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fold().Order(Scope.Local).By("age",Order.Desc)}}, 
                {"g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Or(__.HasLabel("person"),__.Has("software","name","lop")).Order().By("age")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Or(__.HasLabel("person"),__.Has("software","name","lop")).Order().By("age")}}, 
                {"g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V((Vertex) p["v1"]).HasLabel("person").Map<object>((IFunction) p["l1"]).Order(Scope.Local).By(Column.Values,Order.Desc).By(Column.Keys,Order.Asc)}}, 
                {"g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("song","name","OH BOY").Out("followedBy").Out("followedBy").Order().By("performances").By("songType",Order.Desc).By("name")}}, 
                {"g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("song").Order().By("performances",Order.Desc).By("name").Range<object>(110,120).Values<object>("name")}}, 
                {"g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ElementMap<object>().Order(Scope.Local).By(Column.Keys,Order.Desc).Unfold<object>()}}, 
+               {"g_VX1X_elementMap_orderXlocalX_byXkeys_ascXunfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ElementMap<object>().Order(Scope.Local).By(Column.Keys,Order.Asc).Unfold<object>()}}, 
                {"g_V_pageRank_hasXpageRankX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().PageRank().Has("gremlin.pageRankVertexProgram.pageRank")}}, 
                {"g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").PageRank().With("~tinkerpop.pageRank.edges",__.BothE()).With("~tinkerpop.pageRank.propertyName","projectRank").With("~tinkerpop.pageRank.times",0).ValueMap<object,object>("name","projectRank")}}, 
                {"g_V_pageRank_order_byXpageRank_descX_byXnameX_name", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().PageRank().Order().By("gremlin.pageRankVertexProgram.pageRank",Order.Desc).By("name").Values<object>("name")}}, 
@@ -530,6 +554,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_VX1X_outEXcreatedX_inV_inE_outV_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).OutE("created").InV().InE().OutV().Path()}}, 
                {"g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Out().As("b").Out().As("c").Path().From("b").To("c").By("name")}}, 
                {"g_VX1X_out_path_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Out().Path().By("age")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V(p["vid1"]).Out().Path().By("age")}}, 
                {"g_injectX1_null_nullX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(1,null,null).Path()}}, 
                {"g_injectX1_null_nullX_path_dedup", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(1,null,null).Path().Dedup()}}, 
                {"g_V_peerPressure_hasXclusterX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().PeerPressure().Has("gremlin.peerPressureVertexProgram.cluster")}}, 
@@ -539,6 +564,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__descX_selectXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").Project<object>("a","b").By("name").By(__.In("created").Count()).Order().By(__.Select<object>("b"),Order.Desc).Select<object>("a")}}, 
                {"g_V_valueMap_projectXxX_byXselectXnameXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>().Project<object>("x").By(__.Select<object>("name"))}}, 
                {"g_V_projectXa_bX_byXinE_countX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Project<object>("a","b").By(__.InE().Count()).By("age")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Project<object>("a","b").By(__.InE().Count()).By("age")}}, 
                {"g_V_hasXageX_propertiesXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name").Value<object>()}}, 
                {"g_V_hasXageX_propertiesXname_ageX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("name","age").Value<object>()}}, 
                {"g_V_hasXageX_propertiesXage_nameX_value", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").Properties<object>("age","name").Value<object>()}}, 
@@ -607,6 +633,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).Properties<object>("weight").As("a").Select<object>("a").By(T.Key)}}, 
                {"g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.E(p["eid11"]).Properties<object>("weight").As("a").Select<object>("a").By(T.Value)}}, 
                {"g_V_asXaX_selectXaX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a").Select<object>("a").By("age")}}, 
+               {"g_V_asXa_nX_selectXa_nX_byXageX_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().As("a","n").Select<object>("a","n").By("age").By("name")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().As("a").Select<object>("a").By("age")}}, 
                {"g_withSideEffectXk_nullX_injectXxX_selectXkX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSideEffect("k",null).Inject("x").Select<object>("k")}}, 
                {"g_V_shortestPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Identity().ShortestPath()}}, 
                {"g_V_both_dedup_shortestPath", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Both().Dedup().ShortestPath()}}, 
@@ -629,9 +657,13 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_foo_fold_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Values<object>("foo").Fold().Sum<object>(Scope.Local)}}, 
                {"g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_sumX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("software").Group<object,object>().By("name").By(__.BothE().Values<object>("weight").Sum<object>())}}, 
                {"g_V_aggregateXaX_byXageX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Sum<object>(Scope.Local)}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Sum<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXageX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Sum<object>()}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("age").Cap<object>("a").Unfold<object>().Sum<object>()}}, 
                {"g_V_aggregateXaX_byXfooX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Sum<object>(Scope.Local)}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Sum<object>(Scope.Local)}}, 
                {"g_V_aggregateXaX_byXfooX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Sum<object>()}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("a").By("foo").Cap<object>("a").Unfold<object>().Sum<object>()}}, 
                {"g_injectXnull_10_5_nullX_sum", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject<object>(null,p["xx1"],p["xx2"],null).Sum<object>()}}, 
                {"g_injectXlistXnull_10_5_nullXX_sumXlocalX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.Inject(p["xx1"]).Sum<object>(Scope.Local)}}, 
                {"g_V_localXoutE_foldX_unfold", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Local<object>(__.OutE().Fold()).Unfold<object>()}}, 
@@ -650,6 +682,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Filter(__.OutE("created")).ValueMap<object,object>().With("~tinkerpop.valueMap.tokens")}}, 
                {"g_VX1X_valueMapXname_locationX_byXunfoldX_by", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).ValueMap<object,object>("name","location").By(__.Unfold<object>()).By()}}, 
                {"g_V_valueMapXname_age_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>("name","age",null)}}, 
+               {"g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().ValueMap<object,object>("name","age").By(__.Is("x")).By(__.Unfold<object>())}}, 
                {"g_VXnullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(null)}}, 
                {"g_VXlistXnullXX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["xx1"])}}, 
                {"g_VX1_nullX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"],null)}}, 
@@ -711,17 +744,24 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_aggregateXxX_byXnameX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By("name").Cap<object>("x")}}, 
                {"g_V_out_aggregateXaX_path", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out().Aggregate("a").Path()}}, 
                {"g_V_hasLabelXpersonX_aggregateXxX_byXageX_capXxX_asXyX_selectXyX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().HasLabel("person").Aggregate("x").By("age").Cap<object>("x").As("y").Select<object>("y")}}, 
+               {"g_V_aggregateXxX_byXageX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By("age").Cap<object>("x")}}, 
+               {"g_V_aggregateXlocal_xX_byXageX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate(Scope.Local,"x").By("age").Cap<object>("x")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate(Scope.Local,"x").By("age").Cap<object>("x")}}, 
                {"g_V_aggregateXlocal_a_nameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate(Scope.Local,"a").By("name").Out().Cap<object>("a")}}, 
                {"g_VX1X_aggregateXlocal_aX_byXnameX_out_aggregateXlocal_aX_byXnameX_name_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Aggregate(Scope.Local,"a").By("name").Out().Aggregate(Scope.Local,"a").By("name").Values<object>("name").Cap<object>("a")}}, 
                {"g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSideEffect("a",p["xx1"]).V().Both().Values<object>("name").Aggregate(Scope.Local,"a").Cap<object>("a")}}, 
                {"g_V_aggregateXlocal_aX_byXoutEXcreatedX_countX_out_out_aggregateXlocal_aX_byXinEXcreatedX_weight_sumX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate(Scope.Local,"a").By(__.OutE("created").Count()).Out().Out().Aggregate(Scope.Local,"a").By(__.InE("created").Values<object>("weight").Sum<object>()).Cap<object>("a")}}, 
                {"g_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By(__.Values<object>("age").Is(P.Gt(29))).Cap<object>("x")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("x").By(__.Values<object>("age").Is(P.Gt(29))).Cap<object>("x")}}, 
                {"g_V_aggregateXxX_byXout_order_byXnameXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Aggregate("x").By(__.Out().Order().By("name")).Cap<object>("x")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Aggregate("x").By(__.Out().Order().By("name")).Cap<object>("x")}}, 
                {"g_V_fail", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fail()}}, 
                {"g_V_failXmsgX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Fail("msg")}}, 
                {"g_V_unionXout_failX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Union<object>(__.Out(),__.Fail())}}, 
                {"g_V_group_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("name")}}, 
                {"g_V_group_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("age")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_group_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().Group<object,object>().By("age")}}, 
+               {"g_V_group_byXnameX_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("name").By("age")}}, 
                {"g_V_group_byXnameX_by", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By("name").By()}}, 
                {"g_V_groupXaX_byXnameX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group("a").By("name").Cap<object>("a")}}, 
                {"g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("lang").Group("a").By("lang").By("name").Out().Cap<object>("a")}}, 
@@ -745,6 +785,8 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_V_group_byXlabelX_byXlabel_countX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group<object,object>().By(__.Label()).By(__.Label().Count())}}, 
                {"g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Group("m").By(__.Label()).By(__.Label().Count()).Cap<object>("m")}}, 
                {"g_V_outXcreatedX_groupCount_byXnameX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").GroupCount<object>().By("name")}}, 
+               {"g_V_groupCount_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().GroupCount<object>().By("age")}}, 
+               {"g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithStrategies(new ProductiveByStrategy(productiveKeys: new List<object> {})).V().GroupCount<object>().By("age")}}, 
                {"g_V_outXcreatedX_name_groupCount", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").Values<object>("name").GroupCount<object>()}}, 
                {"g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").GroupCount("a").By("name").Cap<object>("a")}}, 
                {"g_V_outXcreatedX_name_groupCountXaX_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Out("created").Values<object>("name").GroupCount("a").Cap<object>("a")}}, 
@@ -783,6 +825,7 @@ namespace Gremlin.Net.IntegrationTest.Gherkin
                {"g_withBulkXfalseX_withSackX1_sumX_VX1X_localXoutEXknowsX_barrierXnormSackX_inVX_inXknowsX_barrier_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithBulk(false).WithSack(1.0,Operator.Sum).V(p["vid1"]).Local<object>(__.OutE("knows").Barrier(Barrier.NormSack).InV()).In("knows").Barrier().Sack<object>()}}, 
                {"g_withBulkXfalseX_withSackX1_sumX_V_out_barrier_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithBulk(false).WithSack(1,Operator.Sum).V().Out().Barrier().Sack<object>()}}, 
                {"g_withSackX1_sumX_VX1X_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.WithSack(1.0,Operator.Sum).V(p["vid1"]).Local<object>(__.Out("knows").Barrier(Barrier.NormSack)).In("knows").Barrier().Sack<object>()}}, 
+               {"g_V_sackXassignX_byXageX_sack", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Sack(Operator.Assign).By("age").Sack<object>()}}, 
                {"g_V_hasXageX_groupCountXaX_byXnameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Has("age").GroupCount("a").By("name").Out().Cap<object>("a")}}, 
                {"g_V_storeXa_nameX_out_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V().Store("a").By("name").Out().Cap<object>("a")}}, 
                {"g_VX1X_storeXaX_byXnameX_out_storeXaX_byXnameX_name_capXaX", new List<Func<GraphTraversalSource, IDictionary<string, object>, ITraversal>> {(g,p) =>g.V(p["vid1"]).Store("a").By("name").Out().Store("a").By("name").Values<object>("name").Cap<object>("a")}}, 
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
index 5205f85..90f63ff 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/feature-steps.js
@@ -68,7 +68,7 @@ const ignoredScenarios = {
   // An associative array containing the scenario name as key, for example:
   'g_withSideEffectXa_setX_V_both_name_storeXaX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
   'g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX': new IgnoreError(ignoreReason.setNotSupported),
-  'g_V_group_byXageX': new IgnoreError(ignoreReason.nullKeysInMapNotSupportedWell),
+  'g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX': new IgnoreError(ignoreReason.nullKeysInMapNotSupportedWell),
   'g_V_shortestPath_edgesIncluded': new IgnoreError(ignoreReason.needsFurtherInvestigation),
   'g_V_shortestPath_edgesIncluded_edgesXoutEX': new IgnoreError(ignoreReason.needsFurtherInvestigation),
   'g_V_shortestpath': new IgnoreError(ignoreReason.needsFurtherInvestigation)
diff --git a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
index d303f97..ea908b0 100644
--- a/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
+++ b/gremlin-javascript/src/main/javascript/gremlin-javascript/test/cucumber/gremlin.js
@@ -119,6 +119,7 @@ const gremlins = {
     g_V_coinX0X: [function({g}) { return g.V().coin(0.0) }], 
     g_withStrategiesXSeedStrategyX_V_coinX50X: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().coin(0.5) }], 
     g_VX1X_outXcreatedX_inXcreatedX_cyclicPath: [function({g, vid1}) { return g.V(vid1).out("created").in_("created").cyclicPath() }], 
+    g_VX1X_both_both_cyclicPath_byXageX: [function({g, vid1}) { return g.V(vid1).both().both().cyclicPath().by("age") }], 
     g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path: [function({g, vid1}) { return g.V(vid1).out("created").in_("created").cyclicPath().path() }], 
     g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path: [function({g, vid1}) { return g.V(vid1).as("a").out("created").as("b").in_("created").as("c").cyclicPath().from_("a").to("b").path() }], 
     g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path: [function({g}) { return g.inject(0).V().both().coalesce(__.has("name","marko").both(),__.constant(0)).cyclicPath().path() }], 
@@ -143,6 +144,9 @@ const gremlins = {
     g_V_both_properties_dedup_count: [function({g}) { return g.V().both().properties().dedup().count() }], 
     g_V_both_properties_properties_dedup_count: [function({g}) { return g.V().both().properties().properties().dedup().count() }], 
     g_V_order_byXname_descX_barrier_dedup_age_name: [function({g}) { return g.V().order().by("name",Order.desc).barrier().dedup().by("age").values("name") }], 
+    g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().order().by("name",Order.desc).barrier().dedup().by("age").values("name") }], 
+    g_V_both_dedup_age_name: [function({g}) { return g.V().both().dedup().by("age").values("name") }], 
+    g_V_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name: [function({g}) { return g.V().as("a").both().as("b").both().as("c").dedup("a","b").by("age").select("a","b","c").by("name") }], 
     g_V_drop: [function({g}) { return g.addV().as("a").addV().as("b").addE("knows").to("a") }, function({g}) { return g.V().drop() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
     g_V_outE_drop: [function({g}) { return g.addV().as("a").addV().as("b").addE("knows").to("a") }, function({g}) { return g.V().outE().drop() }, function({g}) { return g.V() }, function({g}) { return g.E() }], 
     g_V_properties_drop: [function({g}) { return g.addV().property("name","bob").addV().property("name","alice") }, function({g}) { return g.V().properties().drop() }, function({g}) { return g.V() }, function({g}) { return g.V().properties() }], 
@@ -269,10 +273,12 @@ const gremlins = {
     g_V_localXoutE_sampleX1X_byXweightXX: [function({g}) { return g.V().local(__.outE().sample(1).by("weight")) }], 
     g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_sampleX2X_foldXunfold: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().group().by(T.label).by(__.bothE().values("weight").order().sample(2).fold()).unfold() }], 
     g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_fold_sampleXlocal_5XXunfold: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().group().by(T.label).by(__.bothE().values("weight").order().fold().sample(Scope.local,5)).unfold() }], 
+    g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX: [function({g}) { return g.withStrategies(new SeedStrategy({seed:999999})).V().order().by(T.label,Order.desc).sample(1).by("age") }], 
     g_VX1X_outXcreatedX_inXcreatedX_simplePath: [function({g, vid1}) { return g.V(vid1).out("created").in_("created").simplePath() }], 
     g_V_repeatXboth_simplePathX_timesX3X_path: [function({g}) { return g.V().repeat(__.both().simplePath()).times(3).path() }], 
     g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX: [function({g}) { return g.V().as("a").out().as("b").out().as("c").simplePath().by(T.label).from_("b").to("c").path().by("name") }], 
     g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_simplePath_path: [function({g}) { return g.inject(0).V().both().coalesce(__.has("name","marko").both(),__.constant(0)).simplePath().path() }], 
+    g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX: [function({g}) { return g.V().both().as("a").both().as("b").simplePath().path().by("age").from_("a").to("b") }], 
     g_V_valuesXnameX_order_tailXglobal_2X: [function({g}) { return g.V().values("name").order().tail(Scope.global,2) }], 
     g_V_valuesXnameX_order_tailX2X: [function({g}) { return g.V().values("name").order().tail(2) }], 
     g_V_valuesXnameX_order_tail: [function({g}) { return g.V().values("name").order().tail() }], 
@@ -311,6 +317,7 @@ const gremlins = {
     g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX: [function({g}) { return g.V().as("a").outE("created").as("b").inV().as("c").in_("created").as("d").where("a",P.lt("b").or(P.gt("c")).and(P.neq("d"))).by("age").by("weight").by(__.in_("created").values("age").min()).select("a","c","d").by("name") }], 
     g_VX1X_asXaX_out_hasXageX_whereXgtXaXX_byXageX_name: [function({g, vid1}) { return g.V(vid1).as("a").out().has("age").where(P.gt("a")).by("age").values("name") }], 
     g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name: [function({g, vid3}) { return g.V(vid3).as("a").in_().out().as("b").where("a",P.eq("b")).by("age").values("name") }], 
+    g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name: [function({g, vid3}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V(vid3).as("a").in_().out().as("b").where("a",P.eq("b")).by("age").values("name") }], 
     g_V_coworker: [function({g, xx1}) { return g.V().hasLabel("person").filter(__.outE("created")).aggregate("p").as("p1").values("name").as("p1n").select("p").unfold().where(P.neq("p1")).as("p2").values("name").as("p2n").select("p2").out("created").choose(__.in_("created").where(P.eq("p1")),__.values("name"),__.constant(xx1)).group().by(__.select("p1n")).by(__.group().by(__.select("p2n")).by(__.unfold().fold().project("numCoCreated","coCreated").by(__.count(Scope.local)).by())).unfold() }], 
     g_V_coworker_with_midV: [function({g}) { return g.V().hasLabel("person").filter(__.outE("created")).as("p1").V().hasLabel("person").where(P.neq("p1")).filter(__.outE("created")).as("p2").map(__.out("created").where(__.in_("created").as("p1")).values("name").fold()).group().by(__.select("p1").by("name")).by(__.group().by(__.select("p2").by("name")).by(__.project("numCoCreated","coCreated").by(__.count(Scope.local)).by())).unfold() }], 
     g_V_playlist_paths: [function({g}) { return g.V().has("name","Bob_Dylan").in_("sungBy").order().by("name").as("a").repeat(__.out().order().by("name").simplePath().from_("a")).until(__.out("writtenBy").has("name","Johnny_Cash")).limit(1).as("b").repeat(__.out().order().by("name").as("c").simplePath().from_("b").to("c")).until(__.out("sungBy").has("name","Grateful_Dead")).limit(1).path().from_("a").unfold().project("song","artists").by("name").by(__.coalesce(__.out("sungBy","writtenBy" [...]
@@ -439,14 +446,20 @@ const gremlins = {
     g_V_asXaX_outXcreatedX_asXbX_mathXb_plus_aX_byXinXcreatedX_countX_byXageX: [function({g}) { return g.V().as("a").out("created").as("b").math("b + a").by(__.in_("created").count()).by("age") }], 
     g_withSackX1X_injectX1X_repeatXsackXsumX_byXconstantX1XXX_timesX5X_emit_mathXsin__X_byXsackX: [function({g}) { return g.withSack(1).inject(1).repeat(__.sack(Operator.sum).by(__.constant(1))).times(5).emit().math("sin _").by(__.sack()) }], 
     g_V_projectXa_b_cX_byXbothE_weight_sumX_byXbothE_countX_byXnameX_order_byXmathXa_div_bX_descX_selectXcX: [function({g}) { return g.V().project("a","b","c").by(__.bothE().values("weight").sum()).by(__.bothE().count()).by("name").order().by(__.math("a / b"),Order.desc).select("c") }], 
+    g_V_mathXit_plus_itXbyXageX: [function({g}) { return g.V().math("_+_").by("age") }], 
+    g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX: [function({g}) { return g.V().valueMap().math("_+_").by(__.select("age").unfold()) }], 
     g_V_age_max: [function({g}) { return g.V().values("age").max() }], 
     g_V_foo_max: [function({g}) { return g.V().values("foo").max() }], 
     g_V_name_max: [function({g}) { return g.V().values("name").max() }], 
     g_V_age_fold_maxXlocalX: [function({g}) { return g.V().values("age").fold().max(Scope.local) }], 
     g_V_aggregateXaX_byXageX_capXaX_maxXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").max(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_maxXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").max(Scope.local) }], 
     g_V_aggregateXaX_byXageX_capXaX_unfold_max: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().max() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().max() }], 
     g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").max(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").max(Scope.local) }], 
     g_V_aggregateXaX_byXfooX_capXaX_unfold_max: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().max() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().max() }], 
     g_V_foo_fold_maxXlocalX: [function({g}) { return g.V().values("foo").fold().max(Scope.local) }], 
     g_V_name_fold_maxXlocalX: [function({g}) { return g.V().values("name").fold().max(Scope.local) }], 
     g_V_repeatXbothX_timesX5X_age_max: [function({g}) { return g.V().repeat(__.both()).times(5).values("age").max() }], 
@@ -457,9 +470,13 @@ const gremlins = {
     g_V_foo_fold_meanXlocalX: [function({g}) { return g.V().values("foo").fold().mean(Scope.local) }], 
     g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_meanX: [function({g}) { return g.V().hasLabel("software").group().by("name").by(__.bothE().values("weight").mean()) }], 
     g_V_aggregateXaX_byXageX_meanXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").mean(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").mean(Scope.local) }], 
     g_V_aggregateXaX_byXageX_capXaX_unfold_mean: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().mean() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().mean() }], 
     g_V_aggregateXaX_byXfooX_meanXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").mean(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").mean(Scope.local) }], 
     g_V_aggregateXaX_byXfooX_capXaX_unfold_mean: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().mean() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().mean() }], 
     g_injectXnull_10_20_nullX_mean: [function({g, xx1, xx2}) { return g.inject(null,xx1,xx2,null).mean() }], 
     g_injectXlistXnull_10_20_nullXX_meanXlocalX: [function({g, xx1}) { return g.inject(xx1).mean(Scope.local) }], 
     g_V_age_min: [function({g}) { return g.V().values("age").min() }], 
@@ -467,9 +484,13 @@ const gremlins = {
     g_V_name_min: [function({g}) { return g.V().values("name").min() }], 
     g_V_age_fold_minXlocalX: [function({g}) { return g.V().values("age").fold().min(Scope.local) }], 
     g_V_aggregateXaX_byXageX_capXaX_minXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").min(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").min(Scope.local) }], 
     g_V_aggregateXaX_byXageX_capXaX_unfold_min: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().min() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().min() }], 
     g_V_aggregateXaX_byXfooX_capXaX_minXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").min(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").min(Scope.local) }], 
     g_V_aggregateXaX_byXfooX_capXaX_unfold_min: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().min() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().min() }], 
     g_V_foo_fold_minXlocalX: [function({g}) { return g.V().values("foo").fold().min(Scope.local) }], 
     g_V_name_fold_minXlocalX: [function({g}) { return g.V().values("name").fold().min(Scope.local) }], 
     g_V_repeatXbothX_timesX5X_age_min: [function({g}) { return g.V().repeat(__.both()).times(5).values("age").min() }], 
@@ -494,11 +515,14 @@ const gremlins = {
     g_V_both_hasLabelXpersonX_order_byXage_descX_name: [function({g}) { return g.V().both().hasLabel("person").order().by("age",Order.desc).values("name") }], 
     g_V_order_byXoutE_count_descX: [function({g}) { return g.V().order().by(__.outE().count(),Order.desc) }], 
     g_V_hasLabelXpersonX_order_byXageX: [function({g}) { return g.V().hasLabel("person").order().by("age") }], 
+    g_V_order_byXageX: [function({g}) { return g.V().order().by("age") }], 
+    g_V_fold_orderXlocalX_byXageX: [function({g}) { return g.V().fold().order(Scope.local).by("age") }, function({g}) { return g.V().fold().order(Scope.local).by("age",Order.desc) }], 
     g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX: [function({g}) { return g.V().or(__.hasLabel("person"),__.has("software","name","lop")).order().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().or(__.hasLabel("person"),__.has("software","name","lop")).order().by("age") }], 
     g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX: [function({g, l1, v1}) { return g.V(v1).hasLabel("person").map(l1).order(Scope.local).by(Column.values,Order.desc).by(Column.keys,Order.asc) }], 
     g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX: [function({g}) { return g.V().has("song","name","OH BOY").out("followedBy").out("followedBy").order().by("performances").by("songType",Order.desc).by("name") }], 
     g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name: [function({g}) { return g.V().hasLabel("song").order().by("performances",Order.desc).by("name").range(110,120).values("name") }], 
-    g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold: [function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.desc).unfold() }], 
+    g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold: [function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.desc).unfold() }, function({g, vid1}) { return g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.asc).unfold() }], 
     g_V_pageRank_hasXpageRankX: [function({g}) { return g.V().pageRank().has("gremlin.pageRankVertexProgram.pageRank") }], 
     g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX: [function({g}) { return g.V().out("created").pageRank().with_("~tinkerpop.pageRank.edges",__.bothE()).with_("~tinkerpop.pageRank.propertyName","projectRank").with_("~tinkerpop.pageRank.times",0).valueMap("name","projectRank") }], 
     g_V_pageRank_order_byXpageRank_descX_byXnameX_name: [function({g}) { return g.V().pageRank().order().by("gremlin.pageRankVertexProgram.pageRank",Order.desc).by("name").values("name") }], 
@@ -516,6 +540,7 @@ const gremlins = {
     g_VX1X_outEXcreatedX_inV_inE_outV_path: [function({g, vid1}) { return g.V(vid1).outE("created").inV().inE().outV().path() }], 
     g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX: [function({g}) { return g.V().as("a").out().as("b").out().as("c").path().from_("b").to("c").by("name") }], 
     g_VX1X_out_path_byXageX: [function({g, vid1}) { return g.V(vid1).out().path().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX: [function({g, vid1}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V(vid1).out().path().by("age") }], 
     g_injectX1_null_nullX_path: [function({g}) { return g.inject(1,null,null).path() }], 
     g_injectX1_null_nullX_path_dedup: [function({g}) { return g.inject(1,null,null).path().dedup() }], 
     g_V_peerPressure_hasXclusterX: [function({g}) { return g.V().peerPressure().has("gremlin.peerPressureVertexProgram.cluster") }], 
@@ -525,6 +550,7 @@ const gremlins = {
     g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__descX_selectXaX: [function({g}) { return g.V().out("created").project("a","b").by("name").by(__.in_("created").count()).order().by(__.select("b"),Order.desc).select("a") }], 
     g_V_valueMap_projectXxX_byXselectXnameXX: [function({g}) { return g.V().valueMap().project("x").by(__.select("name")) }], 
     g_V_projectXa_bX_byXinE_countX_byXageX: [function({g}) { return g.V().project("a","b").by(__.inE().count()).by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().project("a","b").by(__.inE().count()).by("age") }], 
     g_V_hasXageX_propertiesXnameX: [function({g}) { return g.V().has("age").properties("name").value() }], 
     g_V_hasXageX_propertiesXname_ageX_value: [function({g}) { return g.V().has("age").properties("name","age").value() }], 
     g_V_hasXageX_propertiesXage_nameX_value: [function({g}) { return g.V().has("age").properties("age","name").value() }], 
@@ -593,6 +619,8 @@ const gremlins = {
     g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.key) }], 
     g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX: [function({g, eid11}) { return g.E(eid11).properties("weight").as("a").select("a").by(T.value) }], 
     g_V_asXaX_selectXaX_byXageX: [function({g}) { return g.V().as("a").select("a").by("age") }], 
+    g_V_asXa_nX_selectXa_nX_byXageX_byXnameX: [function({g}) { return g.V().as("a","n").select("a","n").by("age").by("name") }], 
+    g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().as("a").select("a").by("age") }], 
     g_withSideEffectXk_nullX_injectXxX_selectXkX: [function({g}) { return g.withSideEffect("k",null).inject("x").select("k") }], 
     g_V_shortestPath: [function({g}) { return g.V().identity().shortestPath() }], 
     g_V_both_dedup_shortestPath: [function({g}) { return g.V().both().dedup().shortestPath() }], 
@@ -615,9 +643,13 @@ const gremlins = {
     g_V_foo_fold_sumXlocalX: [function({g}) { return g.V().values("foo").fold().sum(Scope.local) }], 
     g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_sumX: [function({g}) { return g.V().hasLabel("software").group().by("name").by(__.bothE().values("weight").sum()) }], 
     g_V_aggregateXaX_byXageX_sumXlocalX: [function({g}) { return g.V().aggregate("a").by("age").cap("a").sum(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").sum(Scope.local) }], 
     g_V_aggregateXaX_byXageX_capXaX_unfold_sum: [function({g}) { return g.V().aggregate("a").by("age").cap("a").unfold().sum() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("age").cap("a").unfold().sum() }], 
     g_V_aggregateXaX_byXfooX_sumXlocalX: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").sum(Scope.local) }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").sum(Scope.local) }], 
     g_V_aggregateXaX_byXfooX_capXaX_unfold_sum: [function({g}) { return g.V().aggregate("a").by("foo").cap("a").unfold().sum() }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("a").by("foo").cap("a").unfold().sum() }], 
     g_injectXnull_10_5_nullX_sum: [function({g, xx1, xx2}) { return g.inject(null,xx1,xx2,null).sum() }], 
     g_injectXlistXnull_10_5_nullXX_sumXlocalX: [function({g, xx1}) { return g.inject(xx1).sum(Scope.local) }], 
     g_V_localXoutE_foldX_unfold: [function({g}) { return g.V().local(__.outE().fold()).unfold() }], 
@@ -636,6 +668,7 @@ const gremlins = {
     g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX: [function({g}) { return g.V().hasLabel("person").filter(__.outE("created")).valueMap().with_("~tinkerpop.valueMap.tokens") }], 
     g_VX1X_valueMapXname_locationX_byXunfoldX_by: [function({g, vid1}) { return g.V(vid1).valueMap("name","location").by(__.unfold()).by() }], 
     g_V_valueMapXname_age_nullX: [function({g}) { return g.V().valueMap("name","age",null) }], 
+    g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX: [function({g}) { return g.V().valueMap("name","age").by(__.is("x")).by(__.unfold()) }], 
     g_VXnullX: [function({g}) { return g.V(null) }], 
     g_VXlistXnullXX: [function({g, xx1}) { return g.V(xx1) }], 
     g_VX1_nullX: [function({g, vid1}) { return g.V(vid1,null) }], 
@@ -697,17 +730,24 @@ const gremlins = {
     g_V_aggregateXxX_byXnameX_capXxX: [function({g}) { return g.V().aggregate("x").by("name").cap("x") }], 
     g_V_out_aggregateXaX_path: [function({g}) { return g.V().out().aggregate("a").path() }], 
     g_V_hasLabelXpersonX_aggregateXxX_byXageX_capXxX_asXyX_selectXyX: [function({g}) { return g.V().hasLabel("person").aggregate("x").by("age").cap("x").as("y").select("y") }], 
+    g_V_aggregateXxX_byXageX_capXxX: [function({g}) { return g.V().aggregate("x").by("age").cap("x") }], 
+    g_V_aggregateXlocal_xX_byXageX_capXxX: [function({g}) { return g.V().aggregate(Scope.local,"x").by("age").cap("x") }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate(Scope.local,"x").by("age").cap("x") }], 
     g_V_aggregateXlocal_a_nameX_out_capXaX: [function({g}) { return g.V().aggregate(Scope.local,"a").by("name").out().cap("a") }], 
     g_VX1X_aggregateXlocal_aX_byXnameX_out_aggregateXlocal_aX_byXnameX_name_capXaX: [function({g, vid1}) { return g.V(vid1).aggregate(Scope.local,"a").by("name").out().aggregate(Scope.local,"a").by("name").values("name").cap("a") }], 
     g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX: [function({g, xx1}) { return g.withSideEffect("a",xx1).V().both().values("name").aggregate(Scope.local,"a").cap("a") }], 
     g_V_aggregateXlocal_aX_byXoutEXcreatedX_countX_out_out_aggregateXlocal_aX_byXinEXcreatedX_weight_sumX: [function({g}) { return g.V().aggregate(Scope.local,"a").by(__.outE("created").count()).out().out().aggregate(Scope.local,"a").by(__.inE("created").values("weight").sum()).cap("a") }], 
     g_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX: [function({g}) { return g.V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x") }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x") }], 
     g_V_aggregateXxX_byXout_order_byXnameXX_capXxX: [function({g}) { return g.V().aggregate("x").by(__.out().order().by("name")).cap("x") }], 
+    g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().aggregate("x").by(__.out().order().by("name")).cap("x") }], 
     g_V_fail: [function({g}) { return g.V().fail() }], 
     g_V_failXmsgX: [function({g}) { return g.V().fail("msg") }], 
     g_V_unionXout_failX: [function({g}) { return g.V().union(__.out(),__.fail()) }], 
     g_V_group_byXnameX: [function({g}) { return g.V().group().by("name") }], 
     g_V_group_byXageX: [function({g}) { return g.V().group().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_group_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().group().by("age") }], 
+    g_V_group_byXnameX_byXageX: [function({g}) { return g.V().group().by("name").by("age") }], 
     g_V_group_byXnameX_by: [function({g}) { return g.V().group().by("name").by() }], 
     g_V_groupXaX_byXnameX_capXaX: [function({g}) { return g.V().group("a").by("name").cap("a") }], 
     g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX: [function({g}) { return g.V().has("lang").group("a").by("lang").by("name").out().cap("a") }], 
@@ -731,6 +771,8 @@ const gremlins = {
     g_V_group_byXlabelX_byXlabel_countX: [function({g}) { return g.V().group().by(__.label()).by(__.label().count()) }], 
     g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX: [function({g}) { return g.V().group("m").by(__.label()).by(__.label().count()).cap("m") }], 
     g_V_outXcreatedX_groupCount_byXnameX: [function({g}) { return g.V().out("created").groupCount().by("name") }], 
+    g_V_groupCount_byXageX: [function({g}) { return g.V().groupCount().by("age") }], 
+    g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX: [function({g}) { return g.withStrategies(new ProductiveByStrategy({productiveKeys:[]})).V().groupCount().by("age") }], 
     g_V_outXcreatedX_name_groupCount: [function({g}) { return g.V().out("created").values("name").groupCount() }], 
     g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX: [function({g}) { return g.V().out("created").groupCount("a").by("name").cap("a") }], 
     g_V_outXcreatedX_name_groupCountXaX_capXaX: [function({g}) { return g.V().out("created").values("name").groupCount("a").cap("a") }], 
@@ -769,6 +811,7 @@ const gremlins = {
     g_withBulkXfalseX_withSackX1_sumX_VX1X_localXoutEXknowsX_barrierXnormSackX_inVX_inXknowsX_barrier_sack: [function({g, vid1}) { return g.withBulk(false).withSack(1.0,Operator.sum).V(vid1).local(__.outE("knows").barrier(Barrier.normSack).inV()).in_("knows").barrier().sack() }], 
     g_withBulkXfalseX_withSackX1_sumX_V_out_barrier_sack: [function({g}) { return g.withBulk(false).withSack(1,Operator.sum).V().out().barrier().sack() }], 
     g_withSackX1_sumX_VX1X_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack: [function({g, vid1}) { return g.withSack(1.0,Operator.sum).V(vid1).local(__.out("knows").barrier(Barrier.normSack)).in_("knows").barrier().sack() }], 
+    g_V_sackXassignX_byXageX_sack: [function({g}) { return g.V().sack(Operator.assign).by("age").sack() }], 
     g_V_hasXageX_groupCountXaX_byXnameX_out_capXaX: [function({g}) { return g.V().has("age").groupCount("a").by("name").out().cap("a") }], 
     g_V_storeXa_nameX_out_capXaX: [function({g}) { return g.V().store("a").by("name").out().cap("a") }], 
     g_VX1X_storeXaX_byXnameX_out_storeXaX_byXnameX_name_capXaX: [function({g, vid1}) { return g.V(vid1).store("a").by("name").out().store("a").by("name").values("name").cap("a") }], 
diff --git a/gremlin-python/src/main/python/radish/gremlin.py b/gremlin-python/src/main/python/radish/gremlin.py
index 13900d6..5e705c6 100644
--- a/gremlin-python/src/main/python/radish/gremlin.py
+++ b/gremlin-python/src/main/python/radish/gremlin.py
@@ -104,6 +104,7 @@ world.gremlins = {
     'g_V_coinX0X': [(lambda g:g.V().coin(float(0.0)))], 
     'g_withStrategiesXSeedStrategyX_V_coinX50X': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().coin(float(0.5)))], 
     'g_VX1X_outXcreatedX_inXcreatedX_cyclicPath': [(lambda g, vid1=None:g.V(vid1).out('created').in_('created').cyclicPath())], 
+    'g_VX1X_both_both_cyclicPath_byXageX': [(lambda g, vid1=None:g.V(vid1).both().both().cyclicPath().by('age'))], 
     'g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path': [(lambda g, vid1=None:g.V(vid1).out('created').in_('created').cyclicPath().path())], 
     'g_VX1X_asXaX_outXcreatedX_asXbX_inXcreatedX_asXcX_cyclicPath_fromXaX_toXbX_path': [(lambda g, vid1=None:g.V(vid1).as_('a').out('created').as_('b').in_('created').as_('c').cyclicPath().from_('a').to('b').path())], 
     'g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_cyclicPath_path': [(lambda g:g.inject(0).V().both().coalesce(__.has('name','marko').both(),__.constant(0)).cyclicPath().path())], 
@@ -128,6 +129,9 @@ world.gremlins = {
     'g_V_both_properties_dedup_count': [(lambda g:g.V().both().properties().dedup().count())], 
     'g_V_both_properties_properties_dedup_count': [(lambda g:g.V().both().properties().properties().dedup().count())], 
     'g_V_order_byXname_descX_barrier_dedup_age_name': [(lambda g:g.V().order().by('name',Order.desc).barrier().dedup().by('age').name)], 
+    'g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().order().by('name',Order.desc).barrier().dedup().by('age').name)], 
+    'g_V_both_dedup_age_name': [(lambda g:g.V().both().dedup().by('age').name)], 
+    'g_V_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name': [(lambda g:g.V().as_('a').both().as_('b').both().as_('c').dedup('a','b').by('age').select('a','b','c').by('name'))], 
     'g_V_drop': [(lambda g:g.addV().as_('a').addV().as_('b').addE('knows').to('a')), (lambda g:g.V().drop()), (lambda g:g.V()), (lambda g:g.E())], 
     'g_V_outE_drop': [(lambda g:g.addV().as_('a').addV().as_('b').addE('knows').to('a')), (lambda g:g.V().outE().drop()), (lambda g:g.V()), (lambda g:g.E())], 
     'g_V_properties_drop': [(lambda g:g.addV().property('name','bob').addV().property('name','alice')), (lambda g:g.V().properties().drop()), (lambda g:g.V()), (lambda g:g.V().properties())], 
@@ -254,10 +258,12 @@ world.gremlins = {
     'g_V_localXoutE_sampleX1X_byXweightXX': [(lambda g:g.V().local(__.outE().sample(1).by('weight')))], 
     'g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_sampleX2X_foldXunfold': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().group().by(T.label).by(__.bothE().weight.order().sample(2).fold()).unfold())], 
     'g_withStrategiesXSeedStrategyX_V_group_byXlabelX_byXbothE_weight_order_fold_sampleXlocal_5XXunfold': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().group().by(T.label).by(__.bothE().weight.order().fold().sample(Scope.local,5)).unfold())], 
+    'g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('SeedStrategy',{'seed':999999,'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SeedStrategy')]).V().order().by(T.label,Order.desc).sample(1).by('age'))], 
     'g_VX1X_outXcreatedX_inXcreatedX_simplePath': [(lambda g, vid1=None:g.V(vid1).out('created').in_('created').simplePath())], 
     'g_V_repeatXboth_simplePathX_timesX3X_path': [(lambda g:g.V().repeat(__.both().simplePath()).times(3).path())], 
     'g_V_asXaX_out_asXbX_out_asXcX_simplePath_byXlabelX_fromXbX_toXcX_path_byXnameX': [(lambda g:g.V().as_('a').out().as_('b').out().as_('c').simplePath().by(T.label).from_('b').to('c').path().by('name'))], 
     'g_injectX0X_V_both_coalesceXhasXname_markoX_both_constantX0XX_simplePath_path': [(lambda g:g.inject(0).V().both().coalesce(__.has('name','marko').both(),__.constant(0)).simplePath().path())], 
+    'g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX': [(lambda g:g.V().both().as_('a').both().as_('b').simplePath().path().by('age').from_('a').to('b'))], 
     'g_V_valuesXnameX_order_tailXglobal_2X': [(lambda g:g.V().name.order().tail(Scope.global_,2))], 
     'g_V_valuesXnameX_order_tailX2X': [(lambda g:g.V().name.order().tail(2))], 
     'g_V_valuesXnameX_order_tail': [(lambda g:g.V().name.order().tail())], 
@@ -296,6 +302,7 @@ world.gremlins = {
     'g_V_asXaX_outEXcreatedX_asXbX_inV_asXcX_inXcreatedX_asXdX_whereXa_ltXbX_orXgtXcXX_andXneqXdXXX_byXageX_byXweightX_byXinXcreatedX_valuesXageX_minX_selectXa_c_dX': [(lambda g:g.V().as_('a').outE('created').as_('b').inV().as_('c').in_('created').as_('d').where('a',P.lt('b').or_(P.gt('c')).and_(P.neq('d'))).by('age').by('weight').by(__.in_('created').age.min_()).select('a','c','d').by('name'))], 
     'g_VX1X_asXaX_out_hasXageX_whereXgtXaXX_byXageX_name': [(lambda g, vid1=None:g.V(vid1).as_('a').out().has('age').where(P.gt('a')).by('age').name)], 
     'g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name': [(lambda g, vid3=None:g.V(vid3).as_('a').in_().out().as_('b').where('a',P.eq('b')).by('age').name)], 
+    'g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name': [(lambda g, vid3=None:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V(vid3).as_('a').in_().out().as_('b').where('a',P.eq('b')).by('age').name)], 
     'g_V_coworker': [(lambda g, xx1=None:g.V().hasLabel('person').filter_(__.outE('created')).aggregate('p').as_('p1').name.as_('p1n').select('p').unfold().where(P.neq('p1')).as_('p2').name.as_('p2n').select('p2').out('created').choose(__.in_('created').where(P.eq('p1')),__.name,__.constant(xx1)).group().by(__.select('p1n')).by(__.group().by(__.select('p2n')).by(__.unfold().fold().project('numCoCreated','coCreated').by(__.count(Scope.local)).by())).unfold())], 
     'g_V_coworker_with_midV': [(lambda g:g.V().hasLabel('person').filter_(__.outE('created')).as_('p1').V().hasLabel('person').where(P.neq('p1')).filter_(__.outE('created')).as_('p2').map(__.out('created').where(__.in_('created').as_('p1')).name.fold()).group().by(__.select('p1').by('name')).by(__.group().by(__.select('p2').by('name')).by(__.project('numCoCreated','coCreated').by(__.count(Scope.local)).by())).unfold())], 
     'g_V_playlist_paths': [(lambda g:g.V().has('name','Bob_Dylan').in_('sungBy').order().by('name').as_('a').repeat(__.out().order().by('name').simplePath().from_('a')).until(__.out('writtenBy').has('name','Johnny_Cash'))[0:1].as_('b').repeat(__.out().order().by('name').as_('c').simplePath().from_('b').to('c')).until(__.out('sungBy').has('name','Grateful_Dead'))[0:1].path().from_('a').unfold().project('song','artists').by('name').by(__.coalesce(__.out('sungBy','writtenBy').dedup().name.o [...]
@@ -424,14 +431,20 @@ world.gremlins = {
     'g_V_asXaX_outXcreatedX_asXbX_mathXb_plus_aX_byXinXcreatedX_countX_byXageX': [(lambda g:g.V().as_('a').out('created').as_('b').math('b + a').by(__.in_('created').count()).by('age'))], 
     'g_withSackX1X_injectX1X_repeatXsackXsumX_byXconstantX1XXX_timesX5X_emit_mathXsin__X_byXsackX': [(lambda g:g.withSack(1).inject(1).repeat(__.sack(Operator.sum_).by(__.constant(1))).times(5).emit().math('sin _').by(__.sack()))], 
     'g_V_projectXa_b_cX_byXbothE_weight_sumX_byXbothE_countX_byXnameX_order_byXmathXa_div_bX_descX_selectXcX': [(lambda g:g.V().project('a','b','c').by(__.bothE().weight.sum_()).by(__.bothE().count()).by('name').order().by(__.math('a / b'),Order.desc).select('c'))], 
+    'g_V_mathXit_plus_itXbyXageX': [(lambda g:g.V().math('_+_').by('age'))], 
+    'g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX': [(lambda g:g.V().valueMap().math('_+_').by(__.select('age').unfold()))], 
     'g_V_age_max': [(lambda g:g.V().age.max_())], 
     'g_V_foo_max': [(lambda g:g.V().foo.max_())], 
     'g_V_name_max': [(lambda g:g.V().name.max_())], 
     'g_V_age_fold_maxXlocalX': [(lambda g:g.V().age.fold().max_(Scope.local))], 
     'g_V_aggregateXaX_byXageX_capXaX_maxXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').max_(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_maxXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').max_(Scope.local))], 
     'g_V_aggregateXaX_byXageX_capXaX_unfold_max': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().max_())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().max_())], 
     'g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').max_(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').max_(Scope.local))], 
     'g_V_aggregateXaX_byXfooX_capXaX_unfold_max': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().max_())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().max_())], 
     'g_V_foo_fold_maxXlocalX': [(lambda g:g.V().foo.fold().max_(Scope.local))], 
     'g_V_name_fold_maxXlocalX': [(lambda g:g.V().name.fold().max_(Scope.local))], 
     'g_V_repeatXbothX_timesX5X_age_max': [(lambda g:g.V().repeat(__.both()).times(5).age.max_())], 
@@ -442,9 +455,13 @@ world.gremlins = {
     'g_V_foo_fold_meanXlocalX': [(lambda g:g.V().foo.fold().mean(Scope.local))], 
     'g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_meanX': [(lambda g:g.V().hasLabel('software').group().by('name').by(__.bothE().weight.mean()))], 
     'g_V_aggregateXaX_byXageX_meanXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').mean(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').mean(Scope.local))], 
     'g_V_aggregateXaX_byXageX_capXaX_unfold_mean': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().mean())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().mean())], 
     'g_V_aggregateXaX_byXfooX_meanXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').mean(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').mean(Scope.local))], 
     'g_V_aggregateXaX_byXfooX_capXaX_unfold_mean': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().mean())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().mean())], 
     'g_injectXnull_10_20_nullX_mean': [(lambda g, xx1=None,xx2=None:g.inject(None,xx1,xx2,None).mean())], 
     'g_injectXlistXnull_10_20_nullXX_meanXlocalX': [(lambda g, xx1=None:g.inject(xx1).mean(Scope.local))], 
     'g_V_age_min': [(lambda g:g.V().age.min_())], 
@@ -452,9 +469,13 @@ world.gremlins = {
     'g_V_name_min': [(lambda g:g.V().name.min_())], 
     'g_V_age_fold_minXlocalX': [(lambda g:g.V().age.fold().min_(Scope.local))], 
     'g_V_aggregateXaX_byXageX_capXaX_minXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').min_(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').min_(Scope.local))], 
     'g_V_aggregateXaX_byXageX_capXaX_unfold_min': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().min_())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().min_())], 
     'g_V_aggregateXaX_byXfooX_capXaX_minXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').min_(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').min_(Scope.local))], 
     'g_V_aggregateXaX_byXfooX_capXaX_unfold_min': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().min_())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().min_())], 
     'g_V_foo_fold_minXlocalX': [(lambda g:g.V().foo.fold().min_(Scope.local))], 
     'g_V_name_fold_minXlocalX': [(lambda g:g.V().name.fold().min_(Scope.local))], 
     'g_V_repeatXbothX_timesX5X_age_min': [(lambda g:g.V().repeat(__.both()).times(5).age.min_())], 
@@ -479,11 +500,16 @@ world.gremlins = {
     'g_V_both_hasLabelXpersonX_order_byXage_descX_name': [(lambda g:g.V().both().hasLabel('person').order().by('age',Order.desc).name)], 
     'g_V_order_byXoutE_count_descX': [(lambda g:g.V().order().by(__.outE().count(),Order.desc))], 
     'g_V_hasLabelXpersonX_order_byXageX': [(lambda g:g.V().hasLabel('person').order().by('age'))], 
+    'g_V_order_byXageX': [(lambda g:g.V().order().by('age'))], 
+    'g_V_fold_orderXlocalX_byXageX': [(lambda g:g.V().fold().order(Scope.local).by('age'))], 
+    'g_V_fold_orderXlocalX_byXage_descX': [(lambda g:g.V().fold().order(Scope.local).by('age',Order.desc))], 
     'g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX': [(lambda g:g.V().or_(__.hasLabel('person'),__.has('software','name','lop')).order().by('age'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().or_(__.hasLabel('person'),__.has('software','name','lop')).order().by('age'))], 
     'g_VX1X_hasXlabel_personX_mapXmapXint_ageXX_orderXlocalX_byXvalues_descX_byXkeys_ascX': [(lambda g, l1=None,v1=None:g.V(v1).hasLabel('person').map(l1).order(Scope.local).by(Column.values,Order.desc).by(Column.keys,Order.asc))], 
     'g_V_hasXsong_name_OHBOYX_outXfollowedByX_outXfollowedByX_order_byXperformancesX_byXsongType_descX': [(lambda g:g.V().has('song','name','OH BOY').out('followedBy').out('followedBy').order().by('performances').by('songType',Order.desc).by('name'))], 
     'g_V_hasLabelXsongX_order_byXperformances_descX_byXnameX_rangeX110_120X_name': [(lambda g:g.V().hasLabel('song').order().by('performances',Order.desc).by('name')[110:120].name)], 
     'g_VX1X_elementMap_orderXlocalX_byXkeys_descXunfold': [(lambda g, vid1=None:g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.desc).unfold())], 
+    'g_VX1X_elementMap_orderXlocalX_byXkeys_ascXunfold': [(lambda g, vid1=None:g.V(vid1).elementMap().order(Scope.local).by(Column.keys,Order.asc).unfold())], 
     'g_V_pageRank_hasXpageRankX': [(lambda g:g.V().pageRank().has('gremlin.pageRankVertexProgram.pageRank'))], 
     'g_V_outXcreatedX_pageRank_withXedges_bothEX_withXpropertyName_projectRankX_withXtimes_0X_valueMapXname_projectRankX': [(lambda g:g.V().out('created').pageRank().with_('~tinkerpop.pageRank.edges',__.bothE()).with_('~tinkerpop.pageRank.propertyName','projectRank').with_('~tinkerpop.pageRank.times',0).valueMap('name','projectRank'))], 
     'g_V_pageRank_order_byXpageRank_descX_byXnameX_name': [(lambda g:g.V().pageRank().order().by('gremlin.pageRankVertexProgram.pageRank',Order.desc).by('name').name)], 
@@ -501,6 +527,7 @@ world.gremlins = {
     'g_VX1X_outEXcreatedX_inV_inE_outV_path': [(lambda g, vid1=None:g.V(vid1).outE('created').inV().inE().outV().path())], 
     'g_V_asXaX_out_asXbX_out_asXcX_path_fromXbX_toXcX_byXnameX': [(lambda g:g.V().as_('a').out().as_('b').out().as_('c').path().from_('b').to('c').by('name'))], 
     'g_VX1X_out_path_byXageX': [(lambda g, vid1=None:g.V(vid1).out().path().by('age'))], 
+    'g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX': [(lambda g, vid1=None:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V(vid1).out().path().by('age'))], 
     'g_injectX1_null_nullX_path': [(lambda g:g.inject(1,None,None).path())], 
     'g_injectX1_null_nullX_path_dedup': [(lambda g:g.inject(1,None,None).path().dedup())], 
     'g_V_peerPressure_hasXclusterX': [(lambda g:g.V().peerPressure().has('gremlin.peerPressureVertexProgram.cluster'))], 
@@ -510,6 +537,7 @@ world.gremlins = {
     'g_V_outXcreatedX_projectXa_bX_byXnameX_byXinXcreatedX_countX_order_byXselectXbX__descX_selectXaX': [(lambda g:g.V().out('created').project('a','b').by('name').by(__.in_('created').count()).order().by(__.select('b'),Order.desc).select('a'))], 
     'g_V_valueMap_projectXxX_byXselectXnameXX': [(lambda g:g.V().valueMap().project('x').by(__.select('name')))], 
     'g_V_projectXa_bX_byXinE_countX_byXageX': [(lambda g:g.V().project('a','b').by(__.inE().count()).by('age'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().project('a','b').by(__.inE().count()).by('age'))], 
     'g_V_hasXageX_propertiesXnameX': [(lambda g:g.V().has('age').properties('name').value())], 
     'g_V_hasXageX_propertiesXname_ageX_value': [(lambda g:g.V().has('age').properties('name','age').value())], 
     'g_V_hasXageX_propertiesXage_nameX_value': [(lambda g:g.V().has('age').properties('age','name').value())], 
@@ -578,6 +606,8 @@ world.gremlins = {
     'g_EX11X_propertiesXweightX_asXaX_selectXaX_byXkeyX': [(lambda g, eid11=None:g.E(eid11).properties('weight').as_('a').select('a').by(T.key))], 
     'g_EX11X_propertiesXweightX_asXaX_selectXaX_byXvalueX': [(lambda g, eid11=None:g.E(eid11).properties('weight').as_('a').select('a').by(T.value))], 
     'g_V_asXaX_selectXaX_byXageX': [(lambda g:g.V().as_('a').select('a').by('age'))], 
+    'g_V_asXa_nX_selectXa_nX_byXageX_byXnameX': [(lambda g:g.V().as_('a','n').select('a','n').by('age').by('name'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().as_('a').select('a').by('age'))], 
     'g_withSideEffectXk_nullX_injectXxX_selectXkX': [(lambda g:g.withSideEffect('k',None).inject('x').select('k'))], 
     'g_V_shortestPath': [(lambda g:g.V().identity().shortestPath())], 
     'g_V_both_dedup_shortestPath': [(lambda g:g.V().both().dedup().shortestPath())], 
@@ -600,9 +630,13 @@ world.gremlins = {
     'g_V_foo_fold_sumXlocalX': [(lambda g:g.V().foo.fold().sum_(Scope.local))], 
     'g_V_hasLabelXsoftwareX_group_byXnameX_byXbothE_weight_sumX': [(lambda g:g.V().hasLabel('software').group().by('name').by(__.bothE().weight.sum_()))], 
     'g_V_aggregateXaX_byXageX_sumXlocalX': [(lambda g:g.V().aggregate('a').by('age').cap('a').sum_(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').sum_(Scope.local))], 
     'g_V_aggregateXaX_byXageX_capXaX_unfold_sum': [(lambda g:g.V().aggregate('a').by('age').cap('a').unfold().sum_())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('age').cap('a').unfold().sum_())], 
     'g_V_aggregateXaX_byXfooX_sumXlocalX': [(lambda g:g.V().aggregate('a').by('foo').cap('a').sum_(Scope.local))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').sum_(Scope.local))], 
     'g_V_aggregateXaX_byXfooX_capXaX_unfold_sum': [(lambda g:g.V().aggregate('a').by('foo').cap('a').unfold().sum_())], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('a').by('foo').cap('a').unfold().sum_())], 
     'g_injectXnull_10_5_nullX_sum': [(lambda g, xx1=None,xx2=None:g.inject(None,xx1,xx2,None).sum_())], 
     'g_injectXlistXnull_10_5_nullXX_sumXlocalX': [(lambda g, xx1=None:g.inject(xx1).sum_(Scope.local))], 
     'g_V_localXoutE_foldX_unfold': [(lambda g:g.V().local(__.outE().fold()).unfold())], 
@@ -621,6 +655,7 @@ world.gremlins = {
     'g_V_hasLabelXpersonX_filterXoutEXcreatedXX_valueMap_withXtokensX': [(lambda g:g.V().hasLabel('person').filter_(__.outE('created')).valueMap().with_('~tinkerpop.valueMap.tokens'))], 
     'g_VX1X_valueMapXname_locationX_byXunfoldX_by': [(lambda g, vid1=None:g.V(vid1).valueMap('name','location').by(__.unfold()).by())], 
     'g_V_valueMapXname_age_nullX': [(lambda g:g.V().valueMap('name','age',None))], 
+    'g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX': [(lambda g:g.V().valueMap('name','age').by(__.is_('x')).by(__.unfold()))], 
     'g_VXnullX': [(lambda g:g.V(None))], 
     'g_VXlistXnullXX': [(lambda g, xx1=None:g.V(xx1))], 
     'g_VX1_nullX': [(lambda g, vid1=None:g.V(vid1,None))], 
@@ -682,17 +717,24 @@ world.gremlins = {
     'g_V_aggregateXxX_byXnameX_capXxX': [(lambda g:g.V().aggregate('x').by('name').cap('x'))], 
     'g_V_out_aggregateXaX_path': [(lambda g:g.V().out().aggregate('a').path())], 
     'g_V_hasLabelXpersonX_aggregateXxX_byXageX_capXxX_asXyX_selectXyX': [(lambda g:g.V().hasLabel('person').aggregate('x').by('age').cap('x').as_('y').select('y'))], 
+    'g_V_aggregateXxX_byXageX_capXxX': [(lambda g:g.V().aggregate('x').by('age').cap('x'))], 
+    'g_V_aggregateXlocal_xX_byXageX_capXxX': [(lambda g:g.V().aggregate(Scope.local,'x').by('age').cap('x'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate(Scope.local,'x').by('age').cap('x'))], 
     'g_V_aggregateXlocal_a_nameX_out_capXaX': [(lambda g:g.V().aggregate(Scope.local,'a').by('name').out().cap('a'))], 
     'g_VX1X_aggregateXlocal_aX_byXnameX_out_aggregateXlocal_aX_byXnameX_name_capXaX': [(lambda g, vid1=None:g.V(vid1).aggregate(Scope.local,'a').by('name').out().aggregate(Scope.local,'a').by('name').name.cap('a'))], 
     'g_withSideEffectXa_setX_V_both_name_aggregateXlocal_aX_capXaX': [(lambda g, xx1=None:g.withSideEffect('a',xx1).V().both().name.aggregate(Scope.local,'a').cap('a'))], 
     'g_V_aggregateXlocal_aX_byXoutEXcreatedX_countX_out_out_aggregateXlocal_aX_byXinEXcreatedX_weight_sumX': [(lambda g:g.V().aggregate(Scope.local,'a').by(__.outE('created').count()).out().out().aggregate(Scope.local,'a').by(__.inE('created').weight.sum_()).cap('a'))], 
     'g_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX': [(lambda g:g.V().aggregate('x').by(__.age.is_(P.gt(29))).cap('x'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('x').by(__.age.is_(P.gt(29))).cap('x'))], 
     'g_V_aggregateXxX_byXout_order_byXnameXX_capXxX': [(lambda g:g.V().aggregate('x').by(__.out().order().by('name')).cap('x'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().aggregate('x').by(__.out().order().by('name')).cap('x'))], 
     'g_V_fail': [(lambda g:g.V().fail())], 
     'g_V_failXmsgX': [(lambda g:g.V().fail('msg'))], 
     'g_V_unionXout_failX': [(lambda g:g.V().union(__.out(),__.fail()))], 
     'g_V_group_byXnameX': [(lambda g:g.V().group().by('name'))], 
     'g_V_group_byXageX': [(lambda g:g.V().group().by('age'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_group_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().group().by('age'))], 
+    'g_V_group_byXnameX_byXageX': [(lambda g:g.V().group().by('name').by('age'))], 
     'g_V_group_byXnameX_by': [(lambda g:g.V().group().by('name').by())], 
     'g_V_groupXaX_byXnameX_capXaX': [(lambda g:g.V().group('a').by('name').cap('a'))], 
     'g_V_hasXlangX_groupXaX_byXlangX_byXnameX_out_capXaX': [(lambda g:g.V().has('lang').group('a').by('lang').by('name').out().cap('a'))], 
@@ -716,6 +758,8 @@ world.gremlins = {
     'g_V_group_byXlabelX_byXlabel_countX': [(lambda g:g.V().group().by(__.label()).by(__.label().count()))], 
     'g_V_groupXmX_byXlabelX_byXlabel_countX_capXmX': [(lambda g:g.V().group('m').by(__.label()).by(__.label().count()).cap('m'))], 
     'g_V_outXcreatedX_groupCount_byXnameX': [(lambda g:g.V().out('created').groupCount().by('name'))], 
+    'g_V_groupCount_byXageX': [(lambda g:g.V().groupCount().by('age'))], 
+    'g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX': [(lambda g:g.withStrategies(*[TraversalStrategy('ProductiveByStrategy',{'productiveKeys':[],'strategy':'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy'}, 'org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.ProductiveByStrategy')]).V().groupCount().by('age'))], 
     'g_V_outXcreatedX_name_groupCount': [(lambda g:g.V().out('created').name.groupCount())], 
     'g_V_outXcreatedX_groupCountXaX_byXnameX_capXaX': [(lambda g:g.V().out('created').groupCount('a').by('name').cap('a'))], 
     'g_V_outXcreatedX_name_groupCountXaX_capXaX': [(lambda g:g.V().out('created').name.groupCount('a').cap('a'))], 
@@ -754,6 +798,7 @@ world.gremlins = {
     'g_withBulkXfalseX_withSackX1_sumX_VX1X_localXoutEXknowsX_barrierXnormSackX_inVX_inXknowsX_barrier_sack': [(lambda g, vid1=None:g.withBulk(False).withSack(float(1.0),Operator.sum_).V(vid1).local(__.outE('knows').barrier(Barrier.normSack).inV()).in_('knows').barrier().sack())], 
     'g_withBulkXfalseX_withSackX1_sumX_V_out_barrier_sack': [(lambda g:g.withBulk(False).withSack(1,Operator.sum_).V().out().barrier().sack())], 
     'g_withSackX1_sumX_VX1X_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack': [(lambda g, vid1=None:g.withSack(float(1.0),Operator.sum_).V(vid1).local(__.out('knows').barrier(Barrier.normSack)).in_('knows').barrier().sack())], 
+    'g_V_sackXassignX_byXageX_sack': [(lambda g:g.V().sack(Operator.assign).by('age').sack())], 
     'g_V_hasXageX_groupCountXaX_byXnameX_out_capXaX': [(lambda g:g.V().has('age').groupCount('a').by('name').out().cap('a'))], 
     'g_V_storeXa_nameX_out_capXaX': [(lambda g:g.V().store('a').by('name').out().cap('a'))], 
     'g_VX1X_storeXaX_byXnameX_out_storeXaX_byXnameX_name_capXaX': [(lambda g, vid1=None:g.V(vid1).store('a').by('name').out().store('a').by('name').name.cap('a'))], 
diff --git a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
index a5df693..101acbb 100644
--- a/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
+++ b/gremlin-server/src/main/java/org/apache/tinkerpop/gremlin/server/op/session/SessionOpProcessor.java
@@ -363,7 +363,6 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
         final String traversalSourceName = aliases.entrySet().iterator().next().getValue();
         final TraversalSource g = graphManager.getTraversalSource(traversalSourceName);
 
-        // todo: should session be grabbed here???
         final Session session = getSession(context, msg);
 
         // handle bytecode based graph operations like commit/rollback commands
@@ -504,6 +503,8 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
         if (graph.features().graph().supportsTransactions()) {
             if (TX_COMMIT.equals(bytecode) || TX_ROLLBACK.equals(bytecode)) {
                 final boolean commit = TX_COMMIT.equals(bytecode);
+
+                // there is no timeout on a commit/rollback
                 submitToGremlinExecutor(context, 0, session, new FutureTask<>(() -> {
                     try {
                         if (graph.tx().isOpen()) {
@@ -540,7 +541,8 @@ public class SessionOpProcessor extends AbstractEvalOpProcessor {
                             }
                             context.writeAndFlush(specialResponseMsg.create());
                         } else {
-                            logger.warn(String.format("Exception processing a Traversal on request [%s].", msg.getRequestId()), ex);
+                            logger.warn(String.format("Exception processing a Traversal on request [%s] to %s the transaction.",
+                                    msg.getRequestId(), commit ? "commit" : "rollback"), ex);
                             context.writeAndFlush(ResponseMessage.build(msg).code(ResponseStatusCode.SERVER_ERROR)
                                     .statusMessage(ex.getMessage())
                                     .statusAttributeException(ex).create());
diff --git a/gremlin-test/features/filter/CyclicPath.feature b/gremlin-test/features/filter/CyclicPath.feature
index 2de63ef..9deea88 100644
--- a/gremlin-test/features/filter/CyclicPath.feature
+++ b/gremlin-test/features/filter/CyclicPath.feature
@@ -30,6 +30,20 @@ Feature: Step - cyclicPath()
       | result |
       | v[marko] |
 
+  @GraphComputerVerificationReferenceOnly
+  Scenario: g_VX1X_both_both_cyclicPath_byXageX
+    Given the modern graph
+    And using the parameter vid1 defined as "v[marko].id"
+    And the traversal of
+      """
+      g.V(vid1).both().both().cyclicPath().by('age')
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[marko] |
+      | v[marko] |
+
   Scenario: g_VX1X_outXcreatedX_inXcreatedX_cyclicPath_path
     Given the modern graph
     And using the parameter vid1 defined as "v[marko].id"
diff --git a/gremlin-test/features/filter/Dedup.feature b/gremlin-test/features/filter/Dedup.feature
index 0cf9c21..c08f133 100644
--- a/gremlin-test/features/filter/Dedup.feature
+++ b/gremlin-test/features/filter/Dedup.feature
@@ -299,15 +299,29 @@ Feature: Step - dedup()
       | result |
       | d[21].l |
 
+  Scenario: g_V_order_byXname_descX_barrier_dedup_age_name
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().order().by("name",desc).barrier().dedup().by("age").values("name")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | vadas |
+      | peter |
+      | marko |
+      | josh  |
+
   # ensures that dedup() returns the first item encountered. the ordering supplied will put "ripple" in front of
   # "lop" and make it the first to hit dedup() and as "age" is not a property of either of those only "ripple" will
   # win. the barrier() is required to trick out FilterRankingStrategy which will optimize the traversal placing the
   # dedup() prior to the order() and sorta ruin the test semantics
-  Scenario: g_V_order_byXname_descX_barrier_dedup_age_name
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_order_byXname_descX_barrier_dedup_age_name
     Given the modern graph
     And the traversal of
       """
-      g.V().order().by("name",desc).barrier().dedup().by("age").values("name")
+      g.withStrategies(ProductiveByStrategy).V().order().by("name",desc).barrier().dedup().by("age").values("name")
       """
     When iterated to list
     Then the result should be unordered
@@ -316,4 +330,32 @@ Feature: Step - dedup()
       | ripple |
       | peter |
       | marko |
-      | josh  |
\ No newline at end of file
+      | josh  |
+
+  Scenario: g_V_both_dedup_age_name
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().both().dedup().by("age").values("name")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | vadas |
+      | peter |
+      | marko |
+      | josh  |
+
+  @GraphComputerVerificationReferenceOnly
+  Scenario: g_VX1X_asXaX_both_asXbX_both_asXcX_dedupXa_bX_age_selectXa_b_cX_name
+    Given the modern graph
+    And using the parameter vid1 defined as "v[marko].id"
+    And the traversal of
+      """
+      g.V(vid1).as("a").both().as("b").both().as("c").dedup("a","b").by("age").select("a","b","c").by("name")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"a":"marko", "b":"vadas", "c":"marko"}] |
+      | m[{"a":"marko", "b":"josh", "c":"ripple"}] |
diff --git a/gremlin-test/features/filter/Sample.feature b/gremlin-test/features/filter/Sample.feature
index 44aa971..0319637 100644
--- a/gremlin-test/features/filter/Sample.feature
+++ b/gremlin-test/features/filter/Sample.feature
@@ -68,3 +68,14 @@ Feature: Step - sample()
       | result |
       | m[{"software":"l[d[0.2].d,d[0.4].d,d[0.4].d,d[1.0].d]"}] |
       | m[{"person":"l[d[0.5].d,d[1.0].d,d[0.4].d,d[0.2].d,d[1.0].d]"}] |
+
+  Scenario: g_withStrategiesXSeedStrategyX_V_order_byXlabel_descX_sampleX1X_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(new SeedStrategy(seed: 999999)).V().order().by(T.label, Order.desc).sample(1).by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | v[peter] |
\ No newline at end of file
diff --git a/gremlin-test/features/filter/SimplePath.feature b/gremlin-test/features/filter/SimplePath.feature
index 0020651..1555244 100644
--- a/gremlin-test/features/filter/SimplePath.feature
+++ b/gremlin-test/features/filter/SimplePath.feature
@@ -88,3 +88,20 @@ Feature: Step - simplePath()
       | p[d[0].i,v[lop],v[marko],v[josh]] |
       | p[d[0].i,v[josh],v[marko],v[lop]] |
       | p[d[0].i,v[josh],v[marko],v[vadas]] |
+
+  @GraphComputerVerificationInjectionNotSupported
+  Scenario: g_V_both_asXaX_both_asXbX_simplePath_path_byXageX__fromXaX_toXbX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().both().as('a').both().as('b').simplePath().path().by('age').from('a').to('b')
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | p[d[29].i,d[32].i] |
+      | p[d[29].i,d[27].i] |
+      | p[d[29].i,d[32].i] |
+      | p[d[32].i,d[29].i] |
+      | p[d[29].i,d[27].i] |
+      | p[d[32].i,d[29].i] |
diff --git a/gremlin-test/features/filter/Where.feature b/gremlin-test/features/filter/Where.feature
index 156d124..137ed5c 100644
--- a/gremlin-test/features/filter/Where.feature
+++ b/gremlin-test/features/filter/Where.feature
@@ -333,7 +333,6 @@ Feature: Step - where()
       | result |
       | josh |
 
-  # comparison of null "age" values in where()
   @GraphComputerVerificationReferenceOnly
   Scenario: g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name
     Given the modern graph
@@ -343,6 +342,18 @@ Feature: Step - where()
       g.V(vid3).as("a").in().out().as("b").where("a", P.eq("b")).by("age").values("name")
       """
     When iterated to list
+    Then the result should be empty
+
+  # comparison of null "age" values in where()
+  @GraphComputerVerificationReferenceOnly
+  Scenario: g_withStrategiesXProductiveByStrategyX_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name
+    Given the modern graph
+    And using the parameter vid3 defined as "v[lop].id"
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V(vid3).as("a").in().out().as("b").where("a", P.eq("b")).by("age").values("name")
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | lop |
diff --git a/gremlin-test/features/map/Math.feature b/gremlin-test/features/map/Math.feature
index 768f37c..06cbd93 100644
--- a/gremlin-test/features/map/Math.feature
+++ b/gremlin-test/features/map/Math.feature
@@ -132,3 +132,31 @@ Feature: Step - math()
       | vadas |
       | lop   |
       | peter |
+
+  Scenario: g_V_mathXit_plus_itXbyXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().math("_+_").by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[64.0].d |
+      | d[58.0].d |
+      | d[54.0].d |
+      | d[70.0].d |
+
+  Scenario: g_V_valueMap_mathXit_plus_itXbyXselectXageX_unfoldXX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().valueMap().math("_+_").by(__.select("age").unfold())
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[64.0].d |
+      | d[58.0].d |
+      | d[54.0].d |
+      | d[70.0].d |
\ No newline at end of file
diff --git a/gremlin-test/features/map/Max.feature b/gremlin-test/features/map/Max.feature
index 0d85cce..ef5a127 100644
--- a/gremlin-test/features/map/Max.feature
+++ b/gremlin-test/features/map/Max.feature
@@ -71,6 +71,17 @@ Feature: Step - max()
       | result |
       | d[35].i |
 
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_maxXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").max(Scope.local)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[35].i |
+
   Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_max
     Given the modern graph
     And the traversal of
@@ -82,6 +93,17 @@ Feature: Step - max()
       | result |
       | d[35].i |
 
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_max
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().max()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[35].i |
+
   Scenario: g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX
     Given the modern graph
     And the traversal of
@@ -89,6 +111,15 @@ Feature: Step - max()
       g.V().aggregate("a").by("foo").cap("a").max(Scope.local)
       """
     When iterated to list
+    Then the result should be empty
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_maxXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").max(Scope.local)
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
@@ -100,6 +131,15 @@ Feature: Step - max()
       g.V().aggregate("a").by("foo").cap("a").unfold().max()
       """
     When iterated to list
+    Then the result should be empty
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_max
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().max()
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
diff --git a/gremlin-test/features/map/Mean.feature b/gremlin-test/features/map/Mean.feature
index cb1b2de..1b1de2f 100644
--- a/gremlin-test/features/map/Mean.feature
+++ b/gremlin-test/features/map/Mean.feature
@@ -82,6 +82,18 @@ Feature: Step - mean()
       | d[30.75].d |
 
   # null values are ignored in mean() which is similar to sum aggregation works in SQL
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_meanXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").mean(Scope.local)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[30.75].d |
+
+  # null values are ignored in mean() which is similar to sum aggregation works in SQL
   Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_mean
     Given the modern graph
     And the traversal of
@@ -93,6 +105,18 @@ Feature: Step - mean()
       | result |
       | d[30.75].d |
 
+  # null values are ignored in mean() which is similar to sum aggregation works in SQL
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_mean
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().mean()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[30.75].d |
+
   # if all values are null then the result is null
   Scenario: g_V_aggregateXaX_byXfooX_meanXlocalX
     Given the modern graph
@@ -101,6 +125,16 @@ Feature: Step - mean()
       g.V().aggregate("a").by("foo").cap("a").mean(Scope.local)
       """
     When iterated to list
+    Then the result should be empty
+
+  # if all values are null then the result is null
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_meanXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").mean(Scope.local)
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
@@ -113,6 +147,16 @@ Feature: Step - mean()
       g.V().aggregate("a").by("foo").cap("a").unfold().mean()
       """
     When iterated to list
+    Then the result should be empty
+
+  # if all values are null then the result is null
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_mean
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().mean()
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
diff --git a/gremlin-test/features/map/Min.feature b/gremlin-test/features/map/Min.feature
index 193e340..3146aa9 100644
--- a/gremlin-test/features/map/Min.feature
+++ b/gremlin-test/features/map/Min.feature
@@ -71,6 +71,17 @@ Feature: Step - min()
       | result |
       | d[27].i |
 
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_minXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").min(Scope.local)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[27].i |
+
   Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_min
     Given the modern graph
     And the traversal of
@@ -82,6 +93,17 @@ Feature: Step - min()
       | result |
       | d[27].i |
 
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_min
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().min()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[27].i |
+
   Scenario: g_V_aggregateXaX_byXfooX_capXaX_minXlocalX
     Given the modern graph
     And the traversal of
@@ -89,6 +111,15 @@ Feature: Step - min()
       g.V().aggregate("a").by("foo").cap("a").min(Scope.local)
       """
     When iterated to list
+    Then the result should be empty
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_minXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").min(Scope.local)
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
@@ -100,6 +131,15 @@ Feature: Step - min()
       g.V().aggregate("a").by("foo").cap("a").unfold().min()
       """
     When iterated to list
+    Then the result should be empty
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_min
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().min()
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
diff --git a/gremlin-test/features/map/Order.feature b/gremlin-test/features/map/Order.feature
index 7fb57b2..e1298e6 100644
--- a/gremlin-test/features/map/Order.feature
+++ b/gremlin-test/features/map/Order.feature
@@ -310,7 +310,49 @@ Feature: Step - order()
       | v[josh]   |
       | v[peter] |
 
-  # tests order().by() where a property isn't present to ensure null comes first
+  Scenario: g_V_order_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().order().by("age")
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | v[vadas] |
+      | v[marko] |
+      | v[josh]   |
+      | v[peter] |
+
+  Scenario: g_V_fold_orderXlocalX_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().fold().order(local).by("age")
+      """
+    When iterated next
+    Then the result should be ordered
+      | result |
+      | v[vadas] |
+      | v[marko] |
+      | v[josh]   |
+      | v[peter] |
+
+
+  Scenario: g_V_fold_orderXlocalX_byXage_descX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().fold().order(local).by("age", desc)
+      """
+    When iterated next
+    Then the result should be ordered
+      | result |
+      | v[peter] |
+      | v[josh] |
+      | v[marko] |
+      | v[vadas] |
+
   Scenario: g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX
     Given the modern graph
     And the traversal of
@@ -320,6 +362,21 @@ Feature: Step - order()
     When iterated to list
     Then the result should be ordered
       | result |
+      | v[vadas] |
+      | v[marko] |
+      | v[josh]   |
+      | v[peter] |
+
+  # tests order().by() where a property isn't present to ensure null comes first
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().or(hasLabel("person"),has("software","name","lop")).order().by("age")
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
       | v[lop] |
       | v[vadas] |
       | v[marko] |
@@ -526,4 +583,19 @@ Feature: Step - order()
       | m[{"name":"marko"}] |
       | m[{"t[label]":"person"}] |
       | m[{"t[id]":"v[marko].id"}] |
-      | m[{"age":29}] |
\ No newline at end of file
+      | m[{"age":29}] |
+
+  Scenario: g_VX1X_elementMap_orderXlocalX_byXkeys_ascXunfold
+    Given the modern graph
+    And using the parameter vid1 defined as "v[marko].id"
+    And the traversal of
+      """
+      g.V(vid1).elementMap().order(Scope.local).by(Column.keys, Order.asc).unfold()
+      """
+    When iterated to list
+    Then the result should be ordered
+      | result |
+      | m[{"age":29}] |
+      | m[{"t[id]":"v[marko].id"}] |
+      | m[{"t[label]":"person"}] |
+      | m[{"name":"marko"}] |
\ No newline at end of file
diff --git a/gremlin-test/features/map/Path.feature b/gremlin-test/features/map/Path.feature
index e4e9f2e..a5e5605 100644
--- a/gremlin-test/features/map/Path.feature
+++ b/gremlin-test/features/map/Path.feature
@@ -120,6 +120,20 @@ Feature: Step - path()
     When iterated to list
     Then the result should be unordered
       | result |
+      | p[d[29].i,d[27].i] |
+      | p[d[29].i,d[32].i] |
+
+  @GraphComputerVerificationReferenceOnly
+  Scenario: g_withStrategiesXProductiveByStrategyX_VX1X_out_path_byXageX
+    Given the modern graph
+    And using the parameter vid1 defined as "v[marko].id"
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V(vid1).out().path().by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
       | p[d[29].i,null] |
       | p[d[29].i,d[27].i] |
       | p[d[29].i,d[32].i] |
diff --git a/gremlin-test/features/map/Project.feature b/gremlin-test/features/map/Project.feature
index bbcf9a4..645450f 100644
--- a/gremlin-test/features/map/Project.feature
+++ b/gremlin-test/features/map/Project.feature
@@ -82,6 +82,24 @@ Feature: Step - project()
     When iterated to list
     Then the result should be unordered
       | result |
+      | m[{"a":"d[1].l"}] |
+      | m[{"a":"d[3].l"}] |
+      | m[{"a":"d[0].l", "b":"d[29].i"}] |
+      | m[{"a":"d[1].l", "b":"d[27].i"}] |
+      | m[{"a":"d[1].l", "b":"d[32].i"}] |
+      | m[{"a":"d[0].l", "b":"d[35].i"}] |
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_projectXa_bX_byXinE_countX_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().project("a", "b").
+          by(__.inE().count()).
+          by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
       | m[{"a":"d[1].l", "b":null}] |
       | m[{"a":"d[3].l", "b":null}] |
       | m[{"a":"d[0].l", "b":"d[29].i"}] |
diff --git a/gremlin-test/features/map/Select.feature b/gremlin-test/features/map/Select.feature
index d334cbc..de599f2 100644
--- a/gremlin-test/features/map/Select.feature
+++ b/gremlin-test/features/map/Select.feature
@@ -819,8 +819,6 @@ Feature: Step - select()
       | result |
       | d[0.4].d |
 
-  # ProductiveBy
-  @GraphComputerVerificationReferenceOnly
   Scenario: g_V_asXaX_selectXaX_byXageX
     Given the modern graph
     And the traversal of
@@ -832,6 +830,35 @@ Feature: Step - select()
       | result |
       | d[29].i |
       | d[27].i |
+      | d[32].i |
+      | d[35].i |
+
+  Scenario: g_V_asXa_nX_selectXa_nX_byXageX_byXnameX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().as("a","n").select("a","n").by("age").by("name")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"a":"d[29].i","n":"marko"}] |
+      | m[{"a":"d[27].i","n":"vadas"}] |
+      | m[{"a":"d[32].i","n":"josh"}] |
+      | m[{"a":"d[35].i","n":"peter"}] |
+
+  @GraphComputerVerificationReferenceOnly
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_asXaX_selectXaX_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().as("a").select("a").by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[29].i |
+      | d[27].i |
       | null |
       | d[32].i |
       | null |
diff --git a/gremlin-test/features/map/Sum.feature b/gremlin-test/features/map/Sum.feature
index 44e59f7..cf1c3c9 100644
--- a/gremlin-test/features/map/Sum.feature
+++ b/gremlin-test/features/map/Sum.feature
@@ -82,6 +82,18 @@ Feature: Step - sum()
       | d[123].i |
 
   # null values are ignored in sum() which is similar to sum aggregation works in SQL
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_sumXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").sum(Scope.local)
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[123].i |
+
+  # null values are ignored in sum() which is similar to sum aggregation works in SQL
   Scenario: g_V_aggregateXaX_byXageX_capXaX_unfold_sum
     Given the modern graph
     And the traversal of
@@ -93,7 +105,18 @@ Feature: Step - sum()
       | result |
       | d[123].l |
 
-  # if all values are null then the result is null
+  # null values are ignored in sum() which is similar to sum aggregation works in SQL
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXageX_capXaX_unfold_sum
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("age").cap("a").unfold().sum()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[123].l |
+
   Scenario: g_V_aggregateXaX_byXfooX_sumXlocalX
     Given the modern graph
     And the traversal of
@@ -101,6 +124,16 @@ Feature: Step - sum()
       g.V().aggregate("a").by("foo").cap("a").sum(Scope.local)
       """
     When iterated to list
+    Then the result should be empty
+
+  # if all values are null then the result is null
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_sumXlocalX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").sum(Scope.local)
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
@@ -113,6 +146,16 @@ Feature: Step - sum()
       g.V().aggregate("a").by("foo").cap("a").unfold().sum()
       """
     When iterated to list
+    Then the result should be empty
+
+  # if all values are null then the result is null
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXaX_byXfooX_capXaX_unfold_sum
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("a").by("foo").cap("a").unfold().sum()
+      """
+    When iterated to list
     Then the result should be unordered
       | result |
       | null |
diff --git a/gremlin-test/features/map/ValueMap.feature b/gremlin-test/features/map/ValueMap.feature
index bedd50a..8a985d2 100644
--- a/gremlin-test/features/map/ValueMap.feature
+++ b/gremlin-test/features/map/ValueMap.feature
@@ -211,4 +211,20 @@ Feature: Step - valueMap()
       | m[{"name": ["peter"], "age": [35]}] |
       | m[{"name": ["vadas"], "age": [27]}] |
       | m[{"name": ["lop"]}] |
-      | m[{"name": ["ripple"]}] |
\ No newline at end of file
+      | m[{"name": ["ripple"]}] |
+
+  Scenario: g_V_valueMapXname_ageX_byXisXxXXbyXunfoldX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().valueMap("name", "age").by(__.is("x")).by(__.unfold())
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"age": 29}] |
+      | m[{"age": 32}] |
+      | m[{"age": 35}] |
+      | m[{"age": 27}] |
+      | m[{}] |
+      | m[{}] |
\ No newline at end of file
diff --git a/gremlin-test/features/sideEffect/Aggregate.feature b/gremlin-test/features/sideEffect/Aggregate.feature
index 2f86692..b3de3ce 100644
--- a/gremlin-test/features/sideEffect/Aggregate.feature
+++ b/gremlin-test/features/sideEffect/Aggregate.feature
@@ -96,6 +96,50 @@ Feature: Step - aggregate()
       | d[32].i |
       | d[35].i |
 
+  Scenario: g_V_aggregateXxX_byXageX_capXxX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().aggregate("x").by("age").cap("x")
+      """
+    When iterated next
+    Then the result should be unordered
+      | result |
+      | d[29].i |
+      | d[27].i |
+      | d[32].i |
+      | d[35].i |
+
+  Scenario: g_V_aggregateXlocal_xX_byXageX_capXxX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().aggregate(Scope.local, "x").by("age").cap("x")
+      """
+    When iterated next
+    Then the result should be unordered
+      | result |
+      | d[29].i |
+      | d[27].i |
+      | d[32].i |
+      | d[35].i |
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXlocal_xX_byXageX_capXxX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate(Scope.local, "x").by("age").cap("x")
+      """
+    When iterated next
+    Then the result should be unordered
+      | result |
+      | d[29].i |
+      | d[27].i |
+      | d[32].i |
+      | d[35].i |
+      | null    |
+      | null    |
+
   Scenario: g_V_aggregateXlocal_a_nameX_out_capXaX
     Given the modern graph
     And the traversal of
@@ -177,13 +221,24 @@ Feature: Step - aggregate()
       | result |
       | d[32].i |
       | d[35].i |
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXvaluesXageX_isXgtX29XXX_capXxX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("x").by(__.values("age").is(P.gt(29))).cap("x")
+      """
+    When iterated next
+    Then the result should be unordered
+      | result |
+      | d[32].i |
+      | d[35].i |
       | null |
       | null |
       | null |
       | null |
 
-  # ProductiveBy
-  @GraphComputerVerificationReferenceOnly
+  @GraphComputerVerificationStarGraphExceeded
   Scenario: g_V_aggregateXxX_byXout_order_byXnameXX_capXxX
     Given the modern graph
     And the traversal of
@@ -196,6 +251,20 @@ Feature: Step - aggregate()
       | v[josh] |
       | v[lop] |
       | v[lop] |
+
+  @GraphComputerVerificationReferenceOnly
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_aggregateXxX_byXout_order_byXnameXX_capXxX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().aggregate("x").by(__.out().order().by("name")).cap("x")
+      """
+    When iterated next
+    Then the result should be unordered
+      | result |
+      | v[josh] |
+      | v[lop] |
+      | v[lop] |
       | null |
       | null |
       | null |
\ No newline at end of file
diff --git a/gremlin-test/features/sideEffect/Group.feature b/gremlin-test/features/sideEffect/Group.feature
index e7c83a7..c33ab11 100644
--- a/gremlin-test/features/sideEffect/Group.feature
+++ b/gremlin-test/features/sideEffect/Group.feature
@@ -38,8 +38,30 @@ Feature: Step - group()
     When iterated to list
     Then the result should be unordered
       | result |
+      | m[{"d[35].i":"l[v[peter]]", "d[27].i":"l[v[vadas]]", "d[32].i": "l[v[josh]]", "d[29].i":"l[v[marko]]"}] |
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_group_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().group().by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
       | m[{"null":"l[v[lop],v[ripple]]", "d[35].i":"l[v[peter]]", "d[27].i":"l[v[vadas]]", "d[32].i": "l[v[josh]]", "d[29].i":"l[v[marko]]"}] |
 
+  Scenario: g_V_group_byXnameX_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().group().by("name").by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"ripple":[], "peter":"l[d[35].i]", "vadas":"l[d[27].i]", "josh": "l[d[32].i]", "lop":[], "marko":"l[d[29].i]"}] |
+
   Scenario: g_V_group_byXnameX_by
     Given the modern graph
     And the traversal of
diff --git a/gremlin-test/features/sideEffect/GroupCount.feature b/gremlin-test/features/sideEffect/GroupCount.feature
index 98de286..3545c23 100644
--- a/gremlin-test/features/sideEffect/GroupCount.feature
+++ b/gremlin-test/features/sideEffect/GroupCount.feature
@@ -29,6 +29,28 @@ Feature: Step - groupCount()
       | result |
       | m[{"ripple":"d[1].l", "lop":"d[3].l"}] |
 
+  Scenario: g_V_groupCount_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().groupCount().by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"d[27].i":"d[1].l", "d[29].i":"d[1].l", "d[32].i":"d[1].l", "d[35].i":"d[1].l"}] |
+
+  Scenario: g_withStrategiesXProductiveByStrategyX_V_groupCount_byXageX
+    Given the modern graph
+    And the traversal of
+      """
+      g.withStrategies(ProductiveByStrategy).V().groupCount().by("age")
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | m[{"null":"d[2].l", "d[27].i":"d[1].l", "d[29].i":"d[1].l", "d[32].i":"d[1].l", "d[35].i":"d[1].l"}] |
+
   Scenario: g_V_outXcreatedX_name_groupCount
     Given the modern graph
     And the traversal of
diff --git a/gremlin-test/features/sideEffect/Sack.feature b/gremlin-test/features/sideEffect/Sack.feature
index 0ce1ad0..0e18d5c 100644
--- a/gremlin-test/features/sideEffect/Sack.feature
+++ b/gremlin-test/features/sideEffect/Sack.feature
@@ -98,6 +98,20 @@ Feature: Step - sack()
       | d[1.0].m |
       | d[1.0].m |
 
+  Scenario: g_V_sackXassignX_byXageX_sack
+    Given the modern graph
+    And the traversal of
+      """
+      g.V().sack(assign).by("age").sack()
+      """
+    When iterated to list
+    Then the result should be unordered
+      | result |
+      | d[29].i |
+      | d[27].i |
+      | d[32].i |
+      | d[35].i |
+
   Scenario: g_withSackXBigInteger_TEN_powX1000X_assignX_V_localXoutXknowsX_barrierXnormSackXX_inXknowsX_barrier_sack
     Given an unsupported test
     Then nothing should happen because
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
index 35bb75e..161f787 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/DedupTest.java
@@ -150,11 +150,10 @@ public abstract class DedupTest extends AbstractGremlinProcessTest {
         final Traversal<Vertex, String> traversal = get_g_V_order_byXname_descX_barrier_dedup_age_name();
         printTraversalForm(traversal);
         final List<String> names = traversal.toList();
-        assertEquals(5, names.size());
+        assertEquals(4, names.size());
         assertTrue(names.contains("marko"));
         assertTrue(names.contains("vadas"));
         assertTrue(names.contains("josh"));
-        assertTrue(names.contains("ripple"));
         assertTrue(names.contains("peter"));
         assertFalse(traversal.hasNext());
     }
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
index dd02b59..0dc5d10 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/filter/WhereTest.java
@@ -50,6 +50,8 @@ import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.not;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.or;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.out;
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.core.Is.is;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotEquals;
@@ -413,7 +415,7 @@ public abstract class WhereTest extends AbstractGremlinProcessTest {
     public void g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name() {
         final Traversal<Vertex, String> traversal = get_g_VX3X_asXaX_in_out_asXbX_whereXa_eqXbXX_byXageX_name(convertToVertexId(graph, "lop"));
         printTraversalForm(traversal);
-        checkResults(Arrays.asList("lop", "lop", "lop", "ripple"), traversal);
+        assertThat(traversal.hasNext(), is(false));
     }
 
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java
index bb85fa2..1bfc79e 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MaxTest.java
@@ -105,7 +105,6 @@ public abstract class MaxTest extends AbstractGremlinProcessTest {
     public void g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX() {
         final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_maxXlocalX();
         printTraversalForm(traversal);
-        assertNull(traversal.next());
         assertFalse(traversal.hasNext());
     }
 
@@ -114,7 +113,6 @@ public abstract class MaxTest extends AbstractGremlinProcessTest {
     public void g_V_aggregateXaX_byXfooX_capXaX_unfold_max() {
         final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_max();
         printTraversalForm(traversal);
-        assertNull(traversal.next());
         assertFalse(traversal.hasNext());
     }
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java
index 0908646..a55918b 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MeanTest.java
@@ -91,7 +91,6 @@ public abstract class MeanTest extends AbstractGremlinProcessTest {
     public void g_V_aggregateXaX_byXfooX_meanXlocalX() {
         final Traversal<Vertex, Double> traversal = get_g_V_aggregateXaX_byXfooX_meanXlocalX();
         printTraversalForm(traversal);
-        assertNull(traversal.next());
         assertFalse(traversal.hasNext());
     }
 
@@ -100,7 +99,6 @@ public abstract class MeanTest extends AbstractGremlinProcessTest {
     public void g_V_aggregateXaX_byXfooX_capXaX_unfold_mean() {
         final Traversal<Vertex, Double> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_mean();
         printTraversalForm(traversal);
-        assertNull(traversal.next());
         assertFalse(traversal.hasNext());
     }
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java
index 51c2e2a..383a833 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MinTest.java
@@ -131,7 +131,6 @@ public abstract class MinTest extends AbstractGremlinProcessTest {
     public void g_V_aggregateXaX_byXfooX_capXaX_minXlocalX() {
         final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_minXlocalX();
         printTraversalForm(traversal);
-        assertNull(traversal.next());
         assertFalse(traversal.hasNext());
     }
 
@@ -140,7 +139,6 @@ public abstract class MinTest extends AbstractGremlinProcessTest {
     public void g_V_aggregateXaX_byXfooX_capXaX_unfold_min() {
         final Traversal<Vertex, Comparable> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_min();
         printTraversalForm(traversal);
-        assertNull(traversal.next());
         assertFalse(traversal.hasNext());
     }
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
index b41fe70..088273f 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/OrderTest.java
@@ -311,7 +311,7 @@ public abstract class OrderTest extends AbstractGremlinProcessTest {
     public void g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX() {
         final Traversal<Vertex, Vertex> traversal = get_g_V_orXhasLabelXpersonX_hasXsoftware_name_lopXX_order_byXageX();
         printTraversalForm(traversal);
-        checkResults(Arrays.asList(convertToVertex(graph, "lop"), convertToVertex(graph, "vadas"), convertToVertex(graph, "marko"), convertToVertex(graph, "josh"), convertToVertex(graph, "peter")), traversal);
+        checkResults(Arrays.asList(convertToVertex(graph, "vadas"), convertToVertex(graph, "marko"), convertToVertex(graph, "josh"), convertToVertex(graph, "peter")), traversal);
     }
 
     @Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java
index d60b2cf..e4b0640 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/PathTest.java
@@ -95,8 +95,8 @@ public abstract class PathTest extends AbstractGremlinProcessTest {
             assertTrue(path.get(1) == null || path.get(1).equals(27) || path.get(1).equals(32));
             ages.add(path.get(1));
         }
-        assertEquals(3, counter);
-        assertEquals(3, ages.size());
+        assertEquals(2, counter);
+        assertEquals(2, ages.size());
     }
 
     @Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
index c073eb1..11c49c2 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProjectTest.java
@@ -27,9 +27,13 @@ import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.structure.Vertex;
 import org.junit.Test;
 
+import java.util.ArrayList;
 import java.util.Collections;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
 
 import static org.apache.tinkerpop.gremlin.LoadGraphWith.GraphData.MODERN;
 import static org.junit.Assert.assertEquals;
@@ -64,13 +68,32 @@ public abstract class ProjectTest extends AbstractGremlinProcessTest {
     public void g_V_projectXa_bX_byXinE_countX_byXageX() {
         final Traversal<Vertex, Map<String, Number>> traversal = get_g_V_projectXa_bX_byXinE_countX_byXageX();
         printTraversalForm(traversal);
-        checkResults(makeMapList(2,
-                "a", 3l, "b", null,
-                "a", 1L, "b", null,
-                "a", 0L, "b", 29,
-                "a", 1L, "b", 27,
-                "a", 1L, "b", 32,
-                "a", 0L, "b", 35), traversal);
+
+        final List<Map<String, Number>> a = new ArrayList<>();
+        a.add(new HashMap<String,Number>() {{
+            put("a", 3L);
+        }});
+        a.add(new HashMap<String,Number>() {{
+            put("a", 1L);
+        }});
+        a.add(new HashMap<String,Number>() {{
+            put("a", 0L);
+            put("b", 29);
+        }});
+        a.add(new HashMap<String,Number>() {{
+            put("a", 1L);
+            put("b", 27);
+        }});
+        a.add(new HashMap<String,Number>() {{
+            put("a", 1L);
+            put("b", 32);
+        }});
+        a.add(new HashMap<String,Number>() {{
+            put("a", 0L);
+            put("b", 35);
+        }});
+
+        checkResults(a, traversal);
     }
 
     @Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
index 4b450ca..dd8b7ca 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SelectTest.java
@@ -898,7 +898,7 @@ public abstract class SelectTest extends AbstractGremlinProcessTest {
     public void g_V_asXaX_selectXaX_byXageX() {
         final Traversal<Vertex, Object> traversal = get_g_V_asXaX_selectXaX_byXageX();
         printTraversalForm(traversal);
-        checkResults(Arrays.asList(29, 27, null, 32, null, 35), traversal);
+        checkResults(Arrays.asList(29, 27, 32, 35), traversal);
     }
 
     @Test
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java
index 6d45fed..ccee6a8 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/SumTest.java
@@ -119,7 +119,6 @@ public abstract class SumTest extends AbstractGremlinProcessTest {
     public void g_V_aggregateXaX_byXfooX_sumXlocalX() {
         final Traversal<Vertex, Number> traversal = get_g_V_aggregateXaX_byXfooX_sumXlocalX();
         printTraversalForm(traversal);
-        assertNull(traversal.next());
         assertFalse(traversal.hasNext());
     }
 
@@ -127,8 +126,7 @@ public abstract class SumTest extends AbstractGremlinProcessTest {
     @LoadGraphWith(MODERN)
     public void g_V_aggregateXaX_byXfooX_capXaX_unfold_sum() {
         final Traversal<Vertex, Number> traversal = get_g_V_aggregateXaX_byXfooX_capXaX_unfold_sum();
-        printTraversalForm(traversal);
-        assertNull(traversal.next());
+        printTraversalForm(traversal);;
         assertFalse(traversal.hasNext());
     }
 
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java
index f3661e9..cf5eb31 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/AggregateTest.java
@@ -242,7 +242,7 @@ public abstract class AggregateTest extends AbstractGremlinProcessTest {
         printTraversalForm(traversal);
         final Collection<Integer> ages = traversal.next();
         assertFalse(traversal.hasNext());
-        assertThat(ages, containsInAnyOrder(null, null, null, null, 32, 35));
+        assertThat(ages, containsInAnyOrder(32, 35));
     }
 
     @Test
@@ -252,7 +252,7 @@ public abstract class AggregateTest extends AbstractGremlinProcessTest {
         printTraversalForm(traversal);
         final Collection<Vertex> ages = traversal.next();
         assertFalse(traversal.hasNext());
-        assertThat(ages, containsInAnyOrder(null, null, null, convertToVertex("lop"), convertToVertex("josh"), convertToVertex("lop")));
+        assertThat(ages, containsInAnyOrder(convertToVertex("lop"), convertToVertex("josh"), convertToVertex("lop")));
     }
 
     public static class Traversals extends AggregateTest {
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
index c7f86d7..897f2d2 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/GroupTest.java
@@ -123,7 +123,7 @@ public abstract class GroupTest extends AbstractGremlinProcessTest {
         printTraversalForm(traversal);
 
         final Map<Integer, Collection<Vertex>> map = traversal.next();
-        assertEquals(5, map.size());
+        assertEquals(4, map.size());
         map.forEach((key, values) -> {
             if (null == key)
                 assertEquals(2, values.size());
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java
index a9a4b1b..72ee0f9 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/sideEffect/TreeTest.java
@@ -52,6 +52,8 @@ public abstract class TreeTest extends AbstractGremlinProcessTest {
 
     public abstract Traversal<Vertex, Tree> get_g_VX1X_out_out_tree_byXnameX(final Object v1Id);
 
+    public abstract Traversal<Vertex, Tree> get_g_V_out_tree_byXageX();
+
     public abstract Traversal<Vertex, Tree> get_g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX(final Object v1Id);
 
     public abstract Traversal<Vertex, Tree> get_g_V_out_out_out_tree();
@@ -66,6 +68,25 @@ public abstract class TreeTest extends AbstractGremlinProcessTest {
 
     @Test
     @LoadGraphWith(MODERN)
+    public void g_V_out_tree_byXageX() {
+        final Traversal<Vertex, Tree> traversal = get_g_V_out_tree_byXageX();
+        printTraversalForm(traversal);
+
+        final Tree tree = traversal.next();
+        assertFalse(traversal.hasNext());
+        assertEquals(3, tree.size());
+        assertTrue(tree.containsKey(29));
+        assertEquals(2, ((Map) tree.get(29)).size());
+        assertTrue(((Map) tree.get(29)).containsKey(32));
+        assertTrue(((Map) tree.get(29)).containsKey(27));
+        assertTrue(tree.containsKey(35));
+        assertEquals(0, ((Map) tree.get(35)).size());
+        assertTrue(tree.containsKey(32));
+        assertEquals(0, ((Map) tree.get(32)).size());
+    }
+
+    @Test
+    @LoadGraphWith(MODERN)
     public void g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX() {
         final Traversal<Vertex, Tree> traversal = get_g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX(convertToVertexId("marko"));
         printTraversalForm(traversal);
@@ -153,6 +174,10 @@ public abstract class TreeTest extends AbstractGremlinProcessTest {
             return g.V(v1Id).out().out().tree().by("name");
         }
 
+        public Traversal<Vertex, Tree> get_g_V_out_tree_byXageX() {
+            return g.V().out().tree().by("age");
+        }
+
         @Override
         public Traversal<Vertex, Tree> get_g_VX1X_out_out_treeXaX_byXnameX_both_both_capXaX(final Object v1Id) {
             return g.V(v1Id).out().out().tree("a").by("name").both().both().cap("a");