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:01 UTC

[tinkerpop] branch TINKERPOP-2635 updated (517dc06 -> 02533bc)

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

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


 discard 517dc06  TINKERPOP-2635 filtering for unproductive by() WIP
     new 02533bc  TINKERPOP-2635 filtering for unproductive by() WIP

This update added new revisions after undoing existing revisions.
That is to say, some revisions that were in the old version of the
branch are not in the new version.  This situation occurs
when a user --force pushes a change and generates a repository
containing something like this:

 * -- * -- B -- O -- O -- O   (517dc06)
            \
             N -- N -- N   refs/heads/TINKERPOP-2635 (02533bc)

You should already have received notification emails for all of the O
revisions, and so the following emails describe only the N revisions
from the common base, B.

Any revisions marked "omit" are not gone; other references still
refer to them.  Any revisions marked "discard" are gone forever.

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 gremlin-test/features/filter/Dedup.feature | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

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

Posted by sp...@apache.org.
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");