You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by dk...@apache.org on 2017/04/13 19:22:56 UTC

tinkerpop git commit: Renamed `RangeByIsCountStrategy` to `CountStrategy`.

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1313 [created] f08d44fc5


Renamed `RangeByIsCountStrategy` to `CountStrategy`.


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

Branch: refs/heads/TINKERPOP-1313
Commit: f08d44fc5c8649658fd775289f0a49ec1816306d
Parents: 72b5186
Author: Daniel Kuppitz <da...@hotmail.com>
Authored: Thu Apr 13 21:21:36 2017 +0200
Committer: Daniel Kuppitz <da...@hotmail.com>
Committed: Thu Apr 13 21:21:36 2017 +0200

----------------------------------------------------------------------
 CHANGELOG.asciidoc                              |   1 +
 docs/src/reference/the-traversal.asciidoc       |   2 +-
 .../tinkerpop/gremlin/jsr223/CoreImports.java   |   4 +-
 .../process/traversal/TraversalStrategies.java  |   4 +-
 .../process/traversal/TraversalStrategy.java    |   4 +-
 .../strategy/optimization/CountStrategy.java    | 191 +++++++++++++++++++
 .../optimization/LazyBarrierStrategy.java       |   2 +-
 .../optimization/RangeByIsCountStrategy.java    | 191 -------------------
 .../structure/io/graphson/GraphSONModule.java   |  10 +-
 .../gremlin/structure/io/gryo/GryoVersion.java  |   6 +-
 .../tinkerpop/gremlin/util/CoreImports.java     |   4 +-
 .../optimization/CountStrategyTest.java         | 113 +++++++++++
 .../optimization/LazyBarrierStrategyTest.java   |   4 +-
 .../RangeByIsCountStrategyTest.java             | 113 -----------
 .../util/TraversalExplanationTest.java          |   4 +-
 .../jython/gremlin_python/process/strategies.py |   2 +-
 .../process/traversal/step/map/ProfileTest.java |   4 +-
 .../TinkerGraphNoStrategyComputerProvider.java  |   4 +-
 18 files changed, 332 insertions(+), 331 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/CHANGELOG.asciidoc
----------------------------------------------------------------------
diff --git a/CHANGELOG.asciidoc b/CHANGELOG.asciidoc
index cedfda7..42479a2 100644
--- a/CHANGELOG.asciidoc
+++ b/CHANGELOG.asciidoc
@@ -26,6 +26,7 @@ image::https://raw.githubusercontent.com/apache/tinkerpop/master/docs/static/ima
 TinkerPop 3.3.0 (Release Date: NOT OFFICIALLY RELEASED YET)
 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 
+* Renamed `RangeByIsCountStrategy` to `CountStrategy`.
 * Added more specific typing to various `__` traversal steps. E.g. `<A,Vertex>out()` is `<Vertex,Vertex>out()`.
 * Updated Docker build scripts to include Python dependencies (NOTE: users should remove any previously generated TinkerPop Docker images).
 * Added "attachment requisite" `VertexProperty.element()` and `Property.element()` data in GraphSON serialization.

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/docs/src/reference/the-traversal.asciidoc
----------------------------------------------------------------------
diff --git a/docs/src/reference/the-traversal.asciidoc b/docs/src/reference/the-traversal.asciidoc
index 1303a22..ba94e8b 100644
--- a/docs/src/reference/the-traversal.asciidoc
+++ b/docs/src/reference/the-traversal.asciidoc
@@ -2797,7 +2797,7 @@ g.V().hasLabel('person'). <1>
 <4> `InlineFilterStrategy` pulls out named predicates from `match()`-step to more easily allow provider strategies to use indices.
 <5> `RepeatUnrollStrategy` will unroll loops and `IncidentToAdjacentStrategy` will turn `outE().inV()`-patterns into `out()`.
 <6> `MatchPredicateStrategy` will pull in `where()`-steps so that they can be subjected to `match()`-steps runtime query optimizer.
-<7> `RangeByIsCountStrategy` will limit the traversal to only the number of traversers required for the `count().is(x)`-check.
+<7> `CountStrategy` will limit the traversal to only the number of traversers required for the `count().is(x)`-check.
 <8> `PathRetractionStrategy` will remove paths from the traversers and increase the likelihood of bulking as path data is not required after `select('b')`.
 <9> `AdjacentToIncidentStrategy` will turn `out()` into `outE()` to increase data access locality.
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
index 5701e47..1296cfe 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/jsr223/CoreImports.java
@@ -80,7 +80,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Lazy
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -228,7 +228,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(MatchPredicateStrategy.class);
         CLASS_IMPORTS.add(OrderLimitStrategy.class);
         CLASS_IMPORTS.add(PathProcessorStrategy.class);
-        CLASS_IMPORTS.add(RangeByIsCountStrategy.class);
+        CLASS_IMPORTS.add(CountStrategy.class);
         CLASS_IMPORTS.add(ComputerVerificationStrategy.class);
         CLASS_IMPORTS.add(LambdaRestrictionStrategy.class);
         CLASS_IMPORTS.add(ReadOnlyStrategy.class);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategies.java
----------------------------------------------------------------------
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 63ae23f..972384c 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
@@ -33,7 +33,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Matc
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.StandardVerificationStrategy;
@@ -211,7 +211,7 @@ public interface TraversalStrategies extends Serializable, Cloneable {
                     FilterRankingStrategy.instance(),
                     MatchPredicateStrategy.instance(),
                     RepeatUnrollStrategy.instance(),
-                    RangeByIsCountStrategy.instance(),
+                    CountStrategy.instance(),
                     PathRetractionStrategy.instance(),
                     LazyBarrierStrategy.instance(),
                     ProfileStrategy.instance(),

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
index be9fc99..03c31ab 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/TraversalStrategy.java
@@ -22,7 +22,7 @@ import org.apache.commons.configuration.BaseConfiguration;
 import org.apache.commons.configuration.Configuration;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.PartitionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
 
 import java.io.Serializable;
@@ -122,7 +122,7 @@ public interface TraversalStrategy<S extends TraversalStrategy> extends Serializ
 
     /**
      * Implemented by strategies that rewrite the traversal to be more efficient, but with the same semantics
-     * (e.g. {@link RangeByIsCountStrategy}). During a re-write ONLY TinkerPop steps should be used.
+     * (e.g. {@link CountStrategy}). During a re-write ONLY TinkerPop steps should be used.
      * For strategies that utilize provider specific steps, use {@link ProviderOptimizationStrategy}.
      */
     public interface OptimizationStrategy extends TraversalStrategy<OptimizationStrategy> {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java
new file mode 100644
index 0000000..ecddd2c
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategy.java
@@ -0,0 +1,191 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Compare;
+import org.apache.tinkerpop.gremlin.process.traversal.Contains;
+import org.apache.tinkerpop.gremlin.process.traversal.P;
+import org.apache.tinkerpop.gremlin.process.traversal.Step;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
+import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
+import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.function.BiPredicate;
+
+/**
+ * This strategy optimizes any occurrence of {@link CountGlobalStep} followed by an {@link IsStep}. The idea is to limit
+ * the number of incoming elements in a way that it's enough for the {@link IsStep} to decide whether it evaluates
+ * {@code true} or {@code false}. If the traversal already contains a user supplied limit, the strategy won't
+ * modify it.
+ *
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ * @example <pre>
+ * __.outE().count().is(0)      // is replaced by __.not(outE())
+ * __.outE().count().is(lt(3))  // is replaced by __.outE().limit(3).count().is(lt(3))
+ * __.outE().count().is(gt(3))  // is replaced by __.outE().limit(4).count().is(gt(3))
+ * </pre>
+ */
+public final class CountStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
+
+    private static final Map<BiPredicate, Long> RANGE_PREDICATES = new HashMap<BiPredicate, Long>() {{
+        put(Contains.within, 1L);
+        put(Contains.without, 0L);
+    }};
+    private static final Set<Compare> INCREASED_OFFSET_SCALAR_PREDICATES =
+            EnumSet.of(Compare.eq, Compare.neq, Compare.lte, Compare.gt);
+
+    private static final CountStrategy INSTANCE = new CountStrategy();
+
+    private CountStrategy() {
+    }
+
+    public static CountStrategy instance() {
+        return INSTANCE;
+    }
+
+    @Override
+    public void apply(final Traversal.Admin<?, ?> traversal) {
+        final TraversalParent parent = traversal.getParent();
+        int size = traversal.getSteps().size();
+        Step prev = null;
+        for (int i = 0; i < size; i++) {
+            final Step curr = traversal.getSteps().get(i);
+            if (i < size - 1 && doStrategy(curr)) {
+                final IsStep isStep = (IsStep) traversal.getSteps().get(i + 1);
+                final P isStepPredicate = isStep.getPredicate();
+                Long highRange = null;
+                boolean useNotStep = false, dismissCountIs = false;
+                for (P p : isStepPredicate instanceof ConnectiveP ? ((ConnectiveP<?>) isStepPredicate).getPredicates() : Collections.singletonList(isStepPredicate)) {
+                    final Object value = p.getValue();
+                    final BiPredicate predicate = p.getBiPredicate();
+                    if (value instanceof Number) {
+                        final long highRangeOffset = INCREASED_OFFSET_SCALAR_PREDICATES.contains(predicate) ? 1L : 0L;
+                        final Long highRangeCandidate = ((Number) value).longValue() + highRangeOffset;
+                        final boolean update = highRange == null || highRangeCandidate > highRange;
+                        if (update) {
+                            if (parent instanceof EmptyStep) {
+                                useNotStep = false;
+                            } else {
+                                if (parent instanceof RepeatStep) {
+                                    final RepeatStep repeatStep = (RepeatStep) parent;
+                                    dismissCountIs = useNotStep = Objects.equals(traversal, repeatStep.getUntilTraversal())
+                                            || Objects.equals(traversal, repeatStep.getEmitTraversal());
+                                } else {
+                                    dismissCountIs = useNotStep = parent instanceof FilterStep || parent instanceof SideEffectStep;
+                                }
+                            }
+                            highRange = highRangeCandidate;
+                            useNotStep &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
+                                    && isStep.getNextStep() instanceof EmptyStep
+                                    && ((highRange <= 1L && predicate.equals(Compare.lt))
+                                    || (highRange == 1L && (predicate.equals(Compare.eq) || predicate.equals(Compare.lte))));
+                            dismissCountIs &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
+                                    && isStep.getNextStep() instanceof EmptyStep
+                                    && (highRange == 1L && (predicate.equals(Compare.gt) || predicate.equals(Compare.gte)));
+                        }
+                    } else {
+                        final Long highRangeOffset = RANGE_PREDICATES.get(predicate);
+                        if (value instanceof Collection && highRangeOffset != null) {
+                            final Object high = Collections.max((Collection) value);
+                            if (high instanceof Number) {
+                                final Long highRangeCandidate = ((Number) high).longValue() + highRangeOffset;
+                                final boolean update = highRange == null || highRangeCandidate > highRange;
+                                if (update) highRange = highRangeCandidate;
+                            }
+                        }
+                    }
+                }
+                if (highRange != null) {
+                    if (useNotStep || dismissCountIs) {
+                        traversal.asAdmin().removeStep(isStep); // IsStep
+                        traversal.asAdmin().removeStep(curr); // CountStep
+                        size -= 2;
+                        if (!dismissCountIs) {
+                            if (traversal.getParent() instanceof FilterStep) {
+                                final Step<?, ?> filterStep = parent.asStep();
+                                final Traversal.Admin parentTraversal = filterStep.getTraversal();
+                                final Step notStep = new NotStep<>(parentTraversal,
+                                        traversal.getSteps().isEmpty() ? __.identity() : traversal);
+                                filterStep.getLabels().forEach(notStep::addLabel);
+                                TraversalHelper.replaceStep(filterStep, notStep, parentTraversal);
+                            } else {
+                                final Traversal.Admin inner;
+                                if (prev != null) {
+                                    inner = __.start().asAdmin();
+                                    for (; ; ) {
+                                        final Step pp = prev.getPreviousStep();
+                                        inner.addStep(0, prev);
+                                        if (pp instanceof EmptyStep || pp instanceof GraphStep ||
+                                                !(prev instanceof FilterStep || prev instanceof SideEffectStep)) break;
+                                        traversal.removeStep(prev);
+                                        prev = pp;
+                                        size--;
+                                    }
+                                } else {
+                                    inner = __.identity().asAdmin();
+                                }
+                                if (prev != null)
+                                    TraversalHelper.replaceStep(prev, new NotStep<>(traversal, inner), traversal);
+                                else
+                                    traversal.asAdmin().addStep(new NotStep<>(traversal, inner));
+                            }
+                        }
+                    } else {
+                        TraversalHelper.insertBeforeStep(new RangeGlobalStep<>(traversal, 0L, highRange), curr, traversal);
+                    }
+                    i++;
+                }
+            }
+            prev = curr;
+        }
+    }
+
+    private boolean doStrategy(final Step step) {
+        if (!(step instanceof CountGlobalStep) ||
+                !(step.getNextStep() instanceof IsStep) ||
+                step.getPreviousStep() instanceof RangeGlobalStep) // if a RangeStep was provided, assume that the user knows what he's doing
+            return false;
+
+        final Step parent = step.getTraversal().getParent().asStep();
+        return (parent instanceof FilterStep || parent.getLabels().isEmpty()) && // if the parent is labeled, then the count matters
+                !(parent.getNextStep() instanceof MatchStep.MatchEndStep && // if this is in a pattern match, then don't do it.
+                        ((MatchStep.MatchEndStep) parent.getNextStep()).getMatchKey().isPresent());
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
index 29c04a7..9c8f931 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategy.java
@@ -47,7 +47,7 @@ public final class LazyBarrierStrategy extends AbstractTraversalStrategy<Travers
     private final boolean IS_TESTING = Boolean.valueOf(System.getProperty("is.testing", "false"));
     private static final LazyBarrierStrategy INSTANCE = new LazyBarrierStrategy();
     private static final Set<Class<? extends OptimizationStrategy>> PRIORS = new HashSet<>(Arrays.asList(
-            RangeByIsCountStrategy.class,
+            CountStrategy.class,
             PathRetractionStrategy.class,
             IncidentToAdjacentStrategy.class,
             AdjacentToIncidentStrategy.class,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java
deleted file mode 100644
index b0cdb39..0000000
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategy.java
+++ /dev/null
@@ -1,191 +0,0 @@
-/*
- * 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.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Compare;
-import org.apache.tinkerpop.gremlin.process.traversal.Contains;
-import org.apache.tinkerpop.gremlin.process.traversal.P;
-import org.apache.tinkerpop.gremlin.process.traversal.Step;
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.step.TraversalParent;
-import org.apache.tinkerpop.gremlin.process.traversal.step.branch.RepeatStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.FilterStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.IsStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.NotStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.filter.RangeGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.CountGlobalStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.GraphStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.sideEffect.SideEffectStep;
-import org.apache.tinkerpop.gremlin.process.traversal.step.util.EmptyStep;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.AbstractTraversalStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.util.ConnectiveP;
-import org.apache.tinkerpop.gremlin.process.traversal.util.TraversalHelper;
-
-import java.util.Collection;
-import java.util.Collections;
-import java.util.EnumSet;
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.function.BiPredicate;
-
-/**
- * This strategy optimizes any occurrence of {@link CountGlobalStep} followed by an {@link IsStep}. The idea is to limit
- * the number of incoming elements in a way that it's enough for the {@link IsStep} to decide whether it evaluates
- * {@code true} or {@code false}. If the traversal already contains a user supplied limit, the strategy won't
- * modify it.
- *
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @example <pre>
- * __.outE().count().is(0)      // is replaced by __.not(outE())
- * __.outE().count().is(lt(3))  // is replaced by __.outE().limit(3).count().is(lt(3))
- * __.outE().count().is(gt(3))  // is replaced by __.outE().limit(4).count().is(gt(3))
- * </pre>
- */
-public final class RangeByIsCountStrategy extends AbstractTraversalStrategy<TraversalStrategy.OptimizationStrategy> implements TraversalStrategy.OptimizationStrategy {
-
-    private static final Map<BiPredicate, Long> RANGE_PREDICATES = new HashMap<BiPredicate, Long>() {{
-        put(Contains.within, 1L);
-        put(Contains.without, 0L);
-    }};
-    private static final Set<Compare> INCREASED_OFFSET_SCALAR_PREDICATES =
-            EnumSet.of(Compare.eq, Compare.neq, Compare.lte, Compare.gt);
-
-    private static final RangeByIsCountStrategy INSTANCE = new RangeByIsCountStrategy();
-
-    private RangeByIsCountStrategy() {
-    }
-
-    public static RangeByIsCountStrategy instance() {
-        return INSTANCE;
-    }
-
-    @Override
-    public void apply(final Traversal.Admin<?, ?> traversal) {
-        final TraversalParent parent = traversal.getParent();
-        int size = traversal.getSteps().size();
-        Step prev = null;
-        for (int i = 0; i < size; i++) {
-            final Step curr = traversal.getSteps().get(i);
-            if (i < size - 1 && doStrategy(curr)) {
-                final IsStep isStep = (IsStep) traversal.getSteps().get(i + 1);
-                final P isStepPredicate = isStep.getPredicate();
-                Long highRange = null;
-                boolean useNotStep = false, dismissCountIs = false;
-                for (P p : isStepPredicate instanceof ConnectiveP ? ((ConnectiveP<?>) isStepPredicate).getPredicates() : Collections.singletonList(isStepPredicate)) {
-                    final Object value = p.getValue();
-                    final BiPredicate predicate = p.getBiPredicate();
-                    if (value instanceof Number) {
-                        final long highRangeOffset = INCREASED_OFFSET_SCALAR_PREDICATES.contains(predicate) ? 1L : 0L;
-                        final Long highRangeCandidate = ((Number) value).longValue() + highRangeOffset;
-                        final boolean update = highRange == null || highRangeCandidate > highRange;
-                        if (update) {
-                            if (parent instanceof EmptyStep) {
-                                useNotStep = false;
-                            } else {
-                                if (parent instanceof RepeatStep) {
-                                    final RepeatStep repeatStep = (RepeatStep) parent;
-                                    dismissCountIs = useNotStep = Objects.equals(traversal, repeatStep.getUntilTraversal())
-                                            || Objects.equals(traversal, repeatStep.getEmitTraversal());
-                                } else {
-                                    dismissCountIs = useNotStep = parent instanceof FilterStep || parent instanceof SideEffectStep;
-                                }
-                            }
-                            highRange = highRangeCandidate;
-                            useNotStep &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
-                                    && isStep.getNextStep() instanceof EmptyStep
-                                    && ((highRange <= 1L && predicate.equals(Compare.lt))
-                                    || (highRange == 1L && (predicate.equals(Compare.eq) || predicate.equals(Compare.lte))));
-                            dismissCountIs &= curr.getLabels().isEmpty() && isStep.getLabels().isEmpty()
-                                    && isStep.getNextStep() instanceof EmptyStep
-                                    && (highRange == 1L && (predicate.equals(Compare.gt) || predicate.equals(Compare.gte)));
-                        }
-                    } else {
-                        final Long highRangeOffset = RANGE_PREDICATES.get(predicate);
-                        if (value instanceof Collection && highRangeOffset != null) {
-                            final Object high = Collections.max((Collection) value);
-                            if (high instanceof Number) {
-                                final Long highRangeCandidate = ((Number) high).longValue() + highRangeOffset;
-                                final boolean update = highRange == null || highRangeCandidate > highRange;
-                                if (update) highRange = highRangeCandidate;
-                            }
-                        }
-                    }
-                }
-                if (highRange != null) {
-                    if (useNotStep || dismissCountIs) {
-                        traversal.asAdmin().removeStep(isStep); // IsStep
-                        traversal.asAdmin().removeStep(curr); // CountStep
-                        size -= 2;
-                        if (!dismissCountIs) {
-                            if (traversal.getParent() instanceof FilterStep) {
-                                final Step<?, ?> filterStep = parent.asStep();
-                                final Traversal.Admin parentTraversal = filterStep.getTraversal();
-                                final Step notStep = new NotStep<>(parentTraversal,
-                                        traversal.getSteps().isEmpty() ? __.identity() : traversal);
-                                filterStep.getLabels().forEach(notStep::addLabel);
-                                TraversalHelper.replaceStep(filterStep, notStep, parentTraversal);
-                            } else {
-                                final Traversal.Admin inner;
-                                if (prev != null) {
-                                    inner = __.start().asAdmin();
-                                    for (; ; ) {
-                                        final Step pp = prev.getPreviousStep();
-                                        inner.addStep(0, prev);
-                                        if (pp instanceof EmptyStep || pp instanceof GraphStep ||
-                                                !(prev instanceof FilterStep || prev instanceof SideEffectStep)) break;
-                                        traversal.removeStep(prev);
-                                        prev = pp;
-                                        size--;
-                                    }
-                                } else {
-                                    inner = __.identity().asAdmin();
-                                }
-                                if (prev != null)
-                                    TraversalHelper.replaceStep(prev, new NotStep<>(traversal, inner), traversal);
-                                else
-                                    traversal.asAdmin().addStep(new NotStep<>(traversal, inner));
-                            }
-                        }
-                    } else {
-                        TraversalHelper.insertBeforeStep(new RangeGlobalStep<>(traversal, 0L, highRange), curr, traversal);
-                    }
-                    i++;
-                }
-            }
-            prev = curr;
-        }
-    }
-
-    private boolean doStrategy(final Step step) {
-        if (!(step instanceof CountGlobalStep) ||
-                !(step.getNextStep() instanceof IsStep) ||
-                step.getPreviousStep() instanceof RangeGlobalStep) // if a RangeStep was provided, assume that the user knows what he's doing
-            return false;
-
-        final Step parent = step.getTraversal().getParent().asStep();
-        return (parent instanceof FilterStep || parent.getLabels().isEmpty()) && // if the parent is labeled, then the count matters
-                !(parent.getNextStep() instanceof MatchStep.MatchEndStep && // if this is in a pattern match, then don't do it.
-                        ((MatchStep.MatchEndStep) parent.getNextStep()).getMatchKey().isPresent());
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
index 91df42a..019112b 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/graphson/GraphSONModule.java
@@ -50,7 +50,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Matc
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
@@ -167,7 +167,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                             OrderLimitStrategy.class,
                             PathProcessorStrategy.class,
                             PathRetractionStrategy.class,
-                            RangeByIsCountStrategy.class,
+                            CountStrategy.class,
                             RepeatUnrollStrategy.class,
                             ComputerVerificationStrategy.class,
                             LambdaRestrictionStrategy.class,
@@ -275,7 +275,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     OrderLimitStrategy.class,
                     PathProcessorStrategy.class,
                     PathRetractionStrategy.class,
-                    RangeByIsCountStrategy.class,
+                    CountStrategy.class,
                     RepeatUnrollStrategy.class,
                     ComputerVerificationStrategy.class,
                     LambdaRestrictionStrategy.class,
@@ -373,7 +373,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                             OrderLimitStrategy.class,
                             PathProcessorStrategy.class,
                             PathRetractionStrategy.class,
-                            RangeByIsCountStrategy.class,
+                            CountStrategy.class,
                             RepeatUnrollStrategy.class,
                             ComputerVerificationStrategy.class,
                             LambdaRestrictionStrategy.class,
@@ -481,7 +481,7 @@ abstract class GraphSONModule extends TinkerPopJacksonModule {
                     OrderLimitStrategy.class,
                     PathProcessorStrategy.class,
                     PathRetractionStrategy.class,
-                    RangeByIsCountStrategy.class,
+                    CountStrategy.class,
                     RepeatUnrollStrategy.class,
                     ComputerVerificationStrategy.class,
                     LambdaRestrictionStrategy.class,

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
index 54af562..f23095c 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/structure/io/gryo/GryoVersion.java
@@ -61,7 +61,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Matc
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathRetractionStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -305,7 +305,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(OrderLimitStrategy.class, 152));
             add(GryoTypeReg.of(PathProcessorStrategy.class, 153));
             add(GryoTypeReg.of(PathRetractionStrategy.class, 154));
-            add(GryoTypeReg.of(RangeByIsCountStrategy.class, 155));
+            add(GryoTypeReg.of(CountStrategy.class, 155));
             add(GryoTypeReg.of(RepeatUnrollStrategy.class, 156));
             add(GryoTypeReg.of(GraphFilterStrategy.class, 157));
             add(GryoTypeReg.of(LambdaRestrictionStrategy.class, 158));
@@ -517,7 +517,7 @@ public enum GryoVersion {
             add(GryoTypeReg.of(OrderLimitStrategy.class, 152));
             add(GryoTypeReg.of(PathProcessorStrategy.class, 153));
             add(GryoTypeReg.of(PathRetractionStrategy.class, 154));
-            add(GryoTypeReg.of(RangeByIsCountStrategy.class, 155));
+            add(GryoTypeReg.of(CountStrategy.class, 155));
             add(GryoTypeReg.of(RepeatUnrollStrategy.class, 156));
             add(GryoTypeReg.of(GraphFilterStrategy.class, 157));
             add(GryoTypeReg.of(LambdaRestrictionStrategy.class, 158));

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
index 597facf..1383fac 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/util/CoreImports.java
@@ -80,7 +80,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.Lazy
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.MatchPredicateStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.OrderLimitStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.PathProcessorStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.LambdaRestrictionStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ReadOnlyStrategy;
@@ -191,7 +191,7 @@ public final class CoreImports {
         CLASS_IMPORTS.add(MatchPredicateStrategy.class);
         CLASS_IMPORTS.add(OrderLimitStrategy.class);
         CLASS_IMPORTS.add(PathProcessorStrategy.class);
-        CLASS_IMPORTS.add(RangeByIsCountStrategy.class);
+        CLASS_IMPORTS.add(CountStrategy.class);
         CLASS_IMPORTS.add(ComputerVerificationStrategy.class);
         CLASS_IMPORTS.add(LambdaRestrictionStrategy.class);
         CLASS_IMPORTS.add(ReadOnlyStrategy.class);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java
new file mode 100644
index 0000000..8408c07
--- /dev/null
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/CountStrategyTest.java
@@ -0,0 +1,113 @@
+/*
+ * 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.strategy.optimization;
+
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
+import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
+import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.Parameterized;
+
+import java.util.Arrays;
+
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.gte;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.inside;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.lte;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.outside;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.within;
+import static org.apache.tinkerpop.gremlin.process.traversal.P.without;
+import static org.junit.Assert.assertEquals;
+
+/**
+ * @author Daniel Kuppitz (http://gremlin.guru)
+ * @author Stephen Mallette (http://stephen.genoprime.com)
+ */
+@RunWith(Parameterized.class)
+public class CountStrategyTest {
+
+    @Parameterized.Parameter(value = 0)
+    public Traversal original;
+
+    @Parameterized.Parameter(value = 1)
+    public Traversal optimized;
+
+    @Parameterized.Parameters(name = "{0}")
+    public static Iterable<Object[]> generateTestParameters() {
+
+        return Arrays.asList(new Traversal[][]{
+                {__.count().is(0), __.limit(1).count().is(0)},
+                {__.count().is(1), __.limit(2).count().is(1)},
+                {__.out().count().is(0), __.out().limit(1).count().is(0)},
+                {__.outE().count().is(lt(1)), __.outE().limit(1).count().is(lt(1))},
+                {__.both().count().is(lte(0)), __.both().limit(1).count().is(lte(0))},
+                {__.map(__.out().count().is(0)), __.map(__.out().limit(1).count().is(0))},
+                {__.map(__.outE().count().is(lt(1))), __.map(__.outE().limit(1).count().is(lt(1)))},
+                {__.map(__.both().count().is(lte(0))), __.map(__.both().limit(1).count().is(lte(0)))},
+                {__.filter(__.out().count().is(0)), __.not(__.out())},
+                {__.filter(__.outE().count().is(lt(1))), __.not(__.outE())},
+                {__.filter(__.both().count().is(lte(0))), __.not(__.both())},
+                {__.store("x").count().is(0).as("a"), __.store("x").limit(1).count().is(0).as("a")},
+                {__.out().count().as("a").is(0), __.out().limit(1).count().as("a").is(0)},
+                {__.out().count().is(neq(4)), __.out().limit(5).count().is(neq(4))},
+                {__.out().count().is(lte(3)), __.out().limit(4).count().is(lte(3))},
+                {__.out().count().is(lt(3)), __.out().limit(3).count().is(lt(3))},
+                {__.out().count().is(gt(2)), __.out().limit(3).count().is(gt(2))},
+                {__.out().count().is(gte(2)), __.out().limit(2).count().is(gte(2))},
+                {__.out().count().is(inside(2, 4)), __.out().limit(4).count().is(inside(2, 4))},
+                {__.out().count().is(outside(2, 4)), __.out().limit(5).count().is(outside(2, 4))},
+                {__.out().count().is(within(2, 6, 4)), __.out().limit(7).count().is(within(2, 6, 4))},
+                {__.out().count().is(without(2, 6, 4)), __.out().limit(6).count().is(without(2, 6, 4))},
+                {__.map(__.count().is(0)), __.map(__.limit(1).count().is(0))},
+                {__.flatMap(__.count().is(0)), __.flatMap(__.limit(1).count().is(0))},
+                {__.flatMap(__.count().is(0)).as("a"), __.flatMap(__.count().is(0)).as("a")},
+                {__.filter(__.count().is(0)).as("a"), __.not(__.identity()).as("a")},
+                {__.filter(__.count().is(0)), __.not(__.identity())},
+                {__.sideEffect(__.count().is(0)), __.sideEffect(__.not(__.identity()))},
+                {__.branch(__.count().is(0)), __.branch(__.limit(1).count().is(0))},
+                {__.count().is(0).store("x"), __.limit(1).count().is(0).store("x")},
+                {__.repeat(__.out()).until(__.outE().count().is(0)), __.repeat(__.out()).until(__.not(__.outE()))},
+                {__.repeat(__.out()).emit(__.outE().count().is(0)), __.repeat(__.out()).emit(__.not(__.outE()))},
+                {__.where(__.outE().hasLabel("created").count().is(0)), __.not(__.outE().hasLabel("created"))},
+                {__.where(__.out().outE().hasLabel("created").count().is(0)), __.not(__.out().outE().hasLabel("created"))},
+                {__.where(__.out().outE().hasLabel("created").count().is(0).store("x")), __.where(__.out().outE().hasLabel("created").limit(1).count().is(0).store("x"))},
+                {__.filter(__.bothE().count().is(gt(0))), __.filter(__.bothE())},
+                {__.filter(__.bothE().count().is(gte(1))), __.filter(__.bothE())},
+                {__.filter(__.bothE().count().is(gt(1))), __.filter(__.bothE().limit(2).count().is(gt(1)))},
+                {__.filter(__.bothE().count().is(gte(2))), __.filter(__.bothE().limit(2).count().is(gte(2)))},
+        });
+    }
+
+    void applyCountStrategy(final Traversal traversal) {
+        final TraversalStrategies strategies = new DefaultTraversalStrategies();
+        strategies.addStrategies(CountStrategy.instance());
+        traversal.asAdmin().setStrategies(strategies);
+        traversal.asAdmin().applyStrategies();
+    }
+
+    @Test
+    public void doTest() {
+        applyCountStrategy(original);
+        assertEquals(optimized, original);
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
index f67abd1..b2bbd94 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/LazyBarrierStrategyTest.java
@@ -76,8 +76,8 @@ public class LazyBarrierStrategyTest {
                 {__.out().out().count(), __.out().out().count(), Collections.emptyList()},
                 {__.out().out().out().count(), __.out().out().barrier(LAZY_SIZE).out().count(), Collections.emptyList()},
                 {__.out().out().out().out().count(), __.out().out().barrier(LAZY_SIZE).out().barrier(LAZY_SIZE).out().count(), Collections.emptyList()},
-                {__.out().out().out().count(), __.out().out().barrier(LAZY_SIZE).outE().count(), Arrays.asList(RangeByIsCountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
-                {__.out().out().out().count().is(P.gt(10)), __.out().out().barrier(LAZY_SIZE).outE().limit(11).count().is(P.gt(10)), Arrays.asList(RangeByIsCountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
+                {__.out().out().out().count(), __.out().out().barrier(LAZY_SIZE).outE().count(), Arrays.asList(CountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
+                {__.out().out().out().count().is(P.gt(10)), __.out().out().barrier(LAZY_SIZE).outE().limit(11).count().is(P.gt(10)), Arrays.asList(CountStrategy.instance(), AdjacentToIncidentStrategy.instance())},
                 {__.outE().inV().outE().inV().outE().inV().groupCount(), __.outE().inV().outE().inV().barrier(LAZY_SIZE).outE().inV().groupCount(), Collections.emptyList()},
                 {__.outE().inV().outE().inV().outE().inV().groupCount(), __.out().out().barrier(LAZY_SIZE).out().groupCount(), Collections.singletonList(IncidentToAdjacentStrategy.instance())},
                 {__.out().out().has("age", 32).out().count(), __.out().out().barrier(LAZY_SIZE).has("age", 32).out().count(), Collections.emptyList()},

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java
deleted file mode 100644
index 9f3b97d..0000000
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/strategy/optimization/RangeByIsCountStrategyTest.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.strategy.optimization;
-
-import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
-import org.apache.tinkerpop.gremlin.process.traversal.TraversalStrategies;
-import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
-import org.apache.tinkerpop.gremlin.process.traversal.util.DefaultTraversalStrategies;
-import org.junit.Test;
-import org.junit.runner.RunWith;
-import org.junit.runners.Parameterized;
-
-import java.util.Arrays;
-
-import static org.apache.tinkerpop.gremlin.process.traversal.P.gt;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.gte;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.inside;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.lte;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.outside;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.within;
-import static org.apache.tinkerpop.gremlin.process.traversal.P.without;
-import static org.junit.Assert.assertEquals;
-
-/**
- * @author Daniel Kuppitz (http://gremlin.guru)
- * @author Stephen Mallette (http://stephen.genoprime.com)
- */
-@RunWith(Parameterized.class)
-public class RangeByIsCountStrategyTest {
-
-    @Parameterized.Parameter(value = 0)
-    public Traversal original;
-
-    @Parameterized.Parameter(value = 1)
-    public Traversal optimized;
-
-    @Parameterized.Parameters(name = "{0}")
-    public static Iterable<Object[]> generateTestParameters() {
-
-        return Arrays.asList(new Traversal[][]{
-                {__.count().is(0), __.limit(1).count().is(0)},
-                {__.count().is(1), __.limit(2).count().is(1)},
-                {__.out().count().is(0), __.out().limit(1).count().is(0)},
-                {__.outE().count().is(lt(1)), __.outE().limit(1).count().is(lt(1))},
-                {__.both().count().is(lte(0)), __.both().limit(1).count().is(lte(0))},
-                {__.map(__.out().count().is(0)), __.map(__.out().limit(1).count().is(0))},
-                {__.map(__.outE().count().is(lt(1))), __.map(__.outE().limit(1).count().is(lt(1)))},
-                {__.map(__.both().count().is(lte(0))), __.map(__.both().limit(1).count().is(lte(0)))},
-                {__.filter(__.out().count().is(0)), __.not(__.out())},
-                {__.filter(__.outE().count().is(lt(1))), __.not(__.outE())},
-                {__.filter(__.both().count().is(lte(0))), __.not(__.both())},
-                {__.store("x").count().is(0).as("a"), __.store("x").limit(1).count().is(0).as("a")},
-                {__.out().count().as("a").is(0), __.out().limit(1).count().as("a").is(0)},
-                {__.out().count().is(neq(4)), __.out().limit(5).count().is(neq(4))},
-                {__.out().count().is(lte(3)), __.out().limit(4).count().is(lte(3))},
-                {__.out().count().is(lt(3)), __.out().limit(3).count().is(lt(3))},
-                {__.out().count().is(gt(2)), __.out().limit(3).count().is(gt(2))},
-                {__.out().count().is(gte(2)), __.out().limit(2).count().is(gte(2))},
-                {__.out().count().is(inside(2, 4)), __.out().limit(4).count().is(inside(2, 4))},
-                {__.out().count().is(outside(2, 4)), __.out().limit(5).count().is(outside(2, 4))},
-                {__.out().count().is(within(2, 6, 4)), __.out().limit(7).count().is(within(2, 6, 4))},
-                {__.out().count().is(without(2, 6, 4)), __.out().limit(6).count().is(without(2, 6, 4))},
-                {__.map(__.count().is(0)), __.map(__.limit(1).count().is(0))},
-                {__.flatMap(__.count().is(0)), __.flatMap(__.limit(1).count().is(0))},
-                {__.flatMap(__.count().is(0)).as("a"), __.flatMap(__.count().is(0)).as("a")},
-                {__.filter(__.count().is(0)).as("a"), __.not(__.identity()).as("a")},
-                {__.filter(__.count().is(0)), __.not(__.identity())},
-                {__.sideEffect(__.count().is(0)), __.sideEffect(__.not(__.identity()))},
-                {__.branch(__.count().is(0)), __.branch(__.limit(1).count().is(0))},
-                {__.count().is(0).store("x"), __.limit(1).count().is(0).store("x")},
-                {__.repeat(__.out()).until(__.outE().count().is(0)), __.repeat(__.out()).until(__.not(__.outE()))},
-                {__.repeat(__.out()).emit(__.outE().count().is(0)), __.repeat(__.out()).emit(__.not(__.outE()))},
-                {__.where(__.outE().hasLabel("created").count().is(0)), __.not(__.outE().hasLabel("created"))},
-                {__.where(__.out().outE().hasLabel("created").count().is(0)), __.not(__.out().outE().hasLabel("created"))},
-                {__.where(__.out().outE().hasLabel("created").count().is(0).store("x")), __.where(__.out().outE().hasLabel("created").limit(1).count().is(0).store("x"))},
-                {__.filter(__.bothE().count().is(gt(0))), __.filter(__.bothE())},
-                {__.filter(__.bothE().count().is(gte(1))), __.filter(__.bothE())},
-                {__.filter(__.bothE().count().is(gt(1))), __.filter(__.bothE().limit(2).count().is(gt(1)))},
-                {__.filter(__.bothE().count().is(gte(2))), __.filter(__.bothE().limit(2).count().is(gte(2)))},
-        });
-    }
-
-    void applyRangeByIsCountStrategy(final Traversal traversal) {
-        final TraversalStrategies strategies = new DefaultTraversalStrategies();
-        strategies.addStrategies(RangeByIsCountStrategy.instance());
-        traversal.asAdmin().setStrategies(strategies);
-        traversal.asAdmin().applyStrategies();
-    }
-
-    @Test
-    public void doTest() {
-        applyRangeByIsCountStrategy(original);
-        assertEquals(optimized, original);
-    }
-}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
index 3040fe8..c7eab92 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalExplanationTest.java
@@ -117,7 +117,7 @@ public class TraversalExplanationTest {
                 found++;
             if (line.contains("AdjacentToIncidentStrategy") && line.contains("[VertexStep(BOTH,edge)"))
                 found++;
-            if (line.contains("RangeByIsCountStrategy") && line.contains("RangeGlobalStep(0,3)"))
+            if (line.contains("CountStrategy") && line.contains("RangeGlobalStep(0,3)"))
                 found++;
         }
         assertEquals(4, found);
@@ -130,7 +130,7 @@ public class TraversalExplanationTest {
                 found++;
             if (line.contains("AdjacentToIncidentStrategy") && line.contains("[VertexStep(BOTH,edge)"))
                 found++;
-            if (line.contains("RangeByIsCountStrategy") && line.contains("RangeGlobalStep(0,3)"))
+            if (line.contains("CountStrategy") && line.contains("RangeGlobalStep(0,3)"))
                 found++;
         }
         assertEquals(4, found);

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
index 8eb7fbd..f5ba9fb 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/strategies.py
@@ -154,7 +154,7 @@ class PathRetractionStrategy(TraversalStrategy):
         TraversalStrategy.__init__(self)
 
 
-class RangeByIsCountStrategy(TraversalStrategy):
+class CountStrategy(TraversalStrategy):
     def __init__(self):
         TraversalStrategy.__init__(self)
 

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
----------------------------------------------------------------------
diff --git a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
index 1af6ba3..06afc1f 100644
--- a/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
+++ b/gremlin-test/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/ProfileTest.java
@@ -32,7 +32,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.Traverser;
 import org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__;
 import org.apache.tinkerpop.gremlin.process.traversal.step.Profiling;
 import org.apache.tinkerpop.gremlin.process.traversal.step.util.ProfileStep;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RepeatUnrollStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.VerificationException;
@@ -299,7 +299,7 @@ public abstract class ProfileTest extends AbstractGremlinProcessTest {
         assertEquals(1, metrics.getCount(TraversalMetrics.TRAVERSER_COUNT_ID).longValue());
         assertEquals(1, metrics.getCount(TraversalMetrics.ELEMENT_COUNT_ID).longValue());
 
-        if (traversal.asAdmin().getStrategies().toList().stream().anyMatch(s -> s instanceof RangeByIsCountStrategy)) {
+        if (traversal.asAdmin().getStrategies().toList().stream().anyMatch(s -> s instanceof CountStrategy)) {
             assertEquals("Metrics 1 should have 4 nested metrics.", 4, metrics.getNested().size());
         } else {
             assertEquals("Metrics 1 should have 3 nested metrics.", 3, metrics.getNested().size());

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/f08d44fc/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
index 50ba5d4..ded754d 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/process/TinkerGraphNoStrategyComputerProvider.java
@@ -25,7 +25,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.Connec
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.decoration.SideEffectStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.finalization.ProfileStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.FilterRankingStrategy;
-import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.RangeByIsCountStrategy;
+import org.apache.tinkerpop.gremlin.process.traversal.strategy.optimization.CountStrategy;
 import org.apache.tinkerpop.gremlin.process.traversal.strategy.verification.ComputerVerificationStrategy;
 import org.apache.tinkerpop.gremlin.structure.Graph;
 import org.apache.tinkerpop.gremlin.tinkergraph.structure.TinkerGraph;
@@ -41,7 +41,7 @@ import java.util.stream.Collectors;
 public class TinkerGraphNoStrategyComputerProvider extends TinkerGraphComputerProvider {
 
     private static final HashSet<Class<? extends TraversalStrategy>> REQUIRED_STRATEGIES = new HashSet<>(Arrays.asList(
-            RangeByIsCountStrategy.class,
+            CountStrategy.class,
             ComputerVerificationStrategy.class,
             ProfileStrategy.class,
             FilterRankingStrategy.class,