You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@tinkerpop.apache.org by ok...@apache.org on 2017/10/03 23:37:26 UTC

tinkerpop git commit: first non-tested implementation of math()-step. It uses the @twilmes model which parses a String representation of the expression.

Repository: tinkerpop
Updated Branches:
  refs/heads/TINKERPOP-1632 [created] 6f1a1f702


first non-tested implementation of math()-step. It uses the @twilmes model which parses a String representation of the expression.


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

Branch: refs/heads/TINKERPOP-1632
Commit: 6f1a1f7028f285c6e45b7e7596320710b91114c5
Parents: 4728916
Author: Marko A. Rodriguez <ok...@gmail.com>
Authored: Tue Oct 3 17:37:10 2017 -0600
Committer: Marko A. Rodriguez <ok...@gmail.com>
Committed: Tue Oct 3 17:37:10 2017 -0600

----------------------------------------------------------------------
 gremlin-core/pom.xml                            |   5 +
 .../traversal/dsl/graph/GraphTraversal.java     |  14 ++
 .../gremlin/process/traversal/dsl/graph/__.java |   7 +
 .../process/traversal/step/map/MathStep.java    | 128 +++++++++++++++++++
 .../process/traversal/util/TraversalHelper.java |   2 +-
 .../traversal/dsl/graph/GraphTraversalTest.java |   2 +
 .../Process/Traversal/GraphTraversal.cs         |   9 ++
 .../src/Gremlin.Net/Process/Traversal/__.cs     |   8 ++
 .../gremlin_python/process/graph_traversal.py   |  12 ++
 .../structure/TinkerGraphPlayTest.java          |  42 +-----
 10 files changed, 188 insertions(+), 41 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-core/pom.xml
----------------------------------------------------------------------
diff --git a/gremlin-core/pom.xml b/gremlin-core/pom.xml
index 3d9e701..30c1b9f 100644
--- a/gremlin-core/pom.xml
+++ b/gremlin-core/pom.xml
@@ -68,6 +68,11 @@ limitations under the License.
             <artifactId>javapoet</artifactId>
             <version>1.8.0</version>
         </dependency>
+        <dependency>
+            <groupId>net.objecthunter</groupId>
+            <artifactId>exp4j</artifactId>
+            <version>0.4.8</version>
+        </dependency>
         <!-- LOGGING -->
         <dependency>
             <groupId>org.slf4j</groupId>

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
index 44a7a3a..8cedbfb 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversal.java
@@ -86,6 +86,7 @@ import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaFlatMapStep
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LambdaMapStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.LoopsStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MatchStep;
+import org.apache.tinkerpop.gremlin.process.traversal.step.map.MathStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxGlobalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MaxLocalStep;
 import org.apache.tinkerpop.gremlin.process.traversal.step.map.MeanGlobalStep;
@@ -1097,6 +1098,18 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         return this;
     }
 
+    /**
+     * Map the {@link Traverser} to a {@link Double} according to the mathematical expression provided in the argument.
+     *
+     * @param expression the mathematical expression with variables refering to scope variables.
+     * @return the traversal with the {@link MathStep} added.
+     * @since 3.3.1
+     */
+    public default GraphTraversal<S, Double> math(final String expression) {
+        this.asAdmin().getBytecode().addStep(Symbols.math, expression);
+        return this.asAdmin().addStep(new MathStep<>(this.asAdmin(), expression));
+    }
+
     ///////////////////// FILTER STEPS /////////////////////
 
     /**
@@ -2691,6 +2704,7 @@ public interface GraphTraversal<S, E> extends Traversal<S, E> {
         public static final String value = "value";
         public static final String path = "path";
         public static final String match = "match";
+        public static final String math = "math";
         public static final String sack = "sack";
         public static final String loops = "loops";
         public static final String project = "project";

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
index 9dc3a93..39e5258 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/__.java
@@ -498,6 +498,13 @@ public class __ {
         return __.<A>start().addE(edgeLabelTraversal);
     }
 
+    /**
+     * @see GraphTraversal#math(String)
+     */
+    public static <A> GraphTraversal<A, Double> math(final String expression) {
+        return __.<A>start().math(expression);
+    }
+
     ///////////////////// FILTER STEPS /////////////////////
 
     /**

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
----------------------------------------------------------------------
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
new file mode 100644
index 0000000..645ea06
--- /dev/null
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/step/map/MathStep.java
@@ -0,0 +1,128 @@
+/*
+ *  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.step.map;
+
+import net.objecthunter.exp4j.Expression;
+import net.objecthunter.exp4j.ExpressionBuilder;
+import org.apache.tinkerpop.gremlin.process.traversal.Pop;
+import org.apache.tinkerpop.gremlin.process.traversal.Traversal;
+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.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.TraversalHelper;
+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;
+
+import java.util.LinkedHashSet;
+import java.util.List;
+import java.util.Set;
+
+/**
+ * @author Marko A. Rodriguez (http://markorodriguez.com)
+ */
+public final class MathStep<S> extends MapStep<S, Double> implements ByModulating, TraversalParent, Scoping {
+
+    private static final String CURRENT = "_";
+    private final String equation;
+    private final Set<String> variables;
+    private final Expression expression;
+    private TraversalRing<Object, Number> traversalRing = new TraversalRing<>();
+
+    public MathStep(final Traversal.Admin traversal, final String equation) {
+        super(traversal);
+        this.equation = equation;
+        final Set<String> labels = TraversalHelper.getLabels(TraversalHelper.getRootTraversal(this.getTraversal()));
+        this.variables = new LinkedHashSet<>();
+        for (final String label : labels) {
+            if (this.equation.contains(label))
+                this.variables.add(label);
+        }
+        if (this.equation.contains(CURRENT))
+            this.variables.add(CURRENT);
+        this.expression = new ExpressionBuilder(this.equation)
+                .variables(this.variables)
+                .build();
+    }
+
+    @Override
+    protected Double map(final Traverser.Admin<S> traverser) {
+        for (final String var : this.variables) {
+            this.expression.setVariable(var, TraversalUtil.applyNullable(
+                    var.equals(CURRENT) ?
+                            traverser.get() :
+                            this.getNullableScopeValue(Pop.last, var, traverser),
+                    this.traversalRing.next()).doubleValue());
+        }
+        this.traversalRing.reset();
+        return this.expression.evaluate();
+    }
+
+    @Override
+    public void modulateBy(final Traversal.Admin<?, ?> selectTraversal) {
+        this.traversalRing.addTraversal(this.integrateChild(selectTraversal));
+    }
+
+    @Override
+    public String toString() {
+        return StringFactory.stepString(this, this.equation, this.traversalRing);
+    }
+
+    @Override
+    public int hashCode() {
+        return super.hashCode() ^ this.equation.hashCode() ^ this.traversalRing.hashCode();
+    }
+
+    @Override
+    public List<Traversal.Admin<Object, Number>> getLocalChildren() {
+        return this.traversalRing.getTraversals();
+    }
+
+    @Override
+    public void reset() {
+        super.reset();
+        this.traversalRing.reset();
+    }
+
+    @Override
+    public MathStep<S> clone() {
+        final MathStep<S> clone = (MathStep<S>) super.clone();
+        clone.traversalRing = this.traversalRing.clone();
+        return clone;
+    }
+
+    @Override
+    public void setTraversal(final Traversal.Admin<?, ?> parentTraversal) {
+        super.setTraversal(parentTraversal);
+        this.traversalRing.getTraversals().forEach(this::integrateChild);
+    }
+
+    @Override
+    public Set<TraverserRequirement> getRequirements() {
+        return this.getSelfAndChildRequirements(TraverserRequirement.OBJECT, TraverserRequirement.SIDE_EFFECTS);
+    }
+
+    @Override
+    public Set<String> getScopeKeys() {
+        return this.variables;
+    }
+}

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
index 56f2eca..9db3ea8 100644
--- a/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
+++ b/gremlin-core/src/main/java/org/apache/tinkerpop/gremlin/process/traversal/util/TraversalHelper.java
@@ -560,7 +560,7 @@ public final class TraversalHelper {
     }
 
     public static Set<String> getLabels(final Traversal.Admin<?, ?> traversal) {
-        return TraversalHelper.getLabels(new HashSet<>(), traversal);
+        return TraversalHelper.getLabels(new LinkedHashSet<>(), traversal);
     }
 
     private static Set<String> getLabels(final Set<String> labels, final Traversal.Admin<?, ?> traversal) {

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java
----------------------------------------------------------------------
diff --git a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java
index cfa63fa..d3fe1c4 100644
--- a/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java
+++ b/gremlin-core/src/test/java/org/apache/tinkerpop/gremlin/process/traversal/dsl/graph/GraphTraversalTest.java
@@ -112,6 +112,8 @@ public class GraphTraversalTest {
                         list.add(arguments[0] = (long) (Math.abs(random.nextInt(10))));
                         list.add(arguments[1] = (long) (Math.abs(random.nextInt(10) + 100)));
                     }
+                } else if (stepMethod.getName().equals("math")) {
+                    list.add(arguments[0] = random.nextInt(100) + " + " + random.nextInt(100));
                 } else {
                     for (int i = 0; i < stepMethod.getParameterTypes().length; i++) {
                         final Class<?> type = stepMethod.getParameterTypes()[i];

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
index 00bfd4b..6c6d174 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/GraphTraversal.cs
@@ -495,6 +495,15 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <summary>
+        ///     Adds the math step to this <see cref="GraphTraversal{SType, EType}" />.
+        /// </summary>
+        public GraphTraversal< S , Double > Math (params object[] args)
+        {
+            Bytecode.AddStep("math", args);
+            return Wrap< S , Double >(this);
+        }
+
+        /// <summary>
         ///     Adds the max step to this <see cref="GraphTraversal{SType, EType}" />.
         /// </summary>
         public GraphTraversal< S , E2 > Max<E2> (params object[] args)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
----------------------------------------------------------------------
diff --git a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
index dfe114d..0e0c527 100644
--- a/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
+++ b/gremlin-dotnet/src/Gremlin.Net/Process/Traversal/__.cs
@@ -409,6 +409,14 @@ namespace Gremlin.Net.Process.Traversal
         }
 
         /// <summary>
+        ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the math step to that traversal.
+        /// </summary>
+        public static GraphTraversal<object, Double> Math(params object[] args)
+        {
+            return new GraphTraversal<object, object>().Math(args);
+        }
+
+        /// <summary>
         ///     Spawns a <see cref="GraphTraversal{SType, EType}" /> and adds the max step to that traversal.
         /// </summary>
         public static GraphTraversal<object, E2> Max<E2>(params object[] args)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
----------------------------------------------------------------------
diff --git a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
index f7bb201..d5630c0 100644
--- a/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
+++ b/gremlin-python/src/main/jython/gremlin_python/process/graph_traversal.py
@@ -317,6 +317,10 @@ class GraphTraversal(Traversal):
         self.bytecode.add_step("match", *args)
         return self
 
+    def math(self, *args):
+        self.bytecode.add_step("math", *args)
+        return self
+
     def max(self, *args):
         self.bytecode.add_step("max", *args)
         return self
@@ -697,6 +701,10 @@ class __(object):
         return cls.graph_traversal(None, None, Bytecode()).match(*args)
 
     @classmethod
+    def math(cls, *args):
+        return cls.graph_traversal(None, None, Bytecode()).math(*args)
+
+    @classmethod
     def max(cls, *args):
         return cls.graph_traversal(None, None, Bytecode()).max(*args)
 
@@ -1046,6 +1054,10 @@ def match(*args):
     return __.match(*args)
 statics.add_static('match', match)
 
+def math(*args):
+    return __.math(*args)
+statics.add_static('math', math)
+
 def max(*args):
     return __.max(*args)
 statics.add_static('max', max)

http://git-wip-us.apache.org/repos/asf/tinkerpop/blob/6f1a1f70/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
----------------------------------------------------------------------
diff --git a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
index eeb4f38..0af81bd 100644
--- a/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
+++ b/tinkergraph-gremlin/src/test/java/org/apache/tinkerpop/gremlin/tinkergraph/structure/TinkerGraphPlayTest.java
@@ -50,6 +50,7 @@ import static org.apache.tinkerpop.gremlin.process.traversal.P.lt;
 import static org.apache.tinkerpop.gremlin.process.traversal.P.neq;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.as;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.both;
+import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.bothE;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.choose;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.has;
 import static org.apache.tinkerpop.gremlin.process.traversal.dsl.graph.__.in;
@@ -70,48 +71,9 @@ public class TinkerGraphPlayTest {
     public void testPlay8() throws Exception {
         Graph graph = TinkerFactory.createModern();
         GraphTraversalSource g = graph.traversal();
-
-        final Traversal<?, ?> traversal = g.V().repeat(out()).times(2).groupCount().by("name").select(Column.keys).order().by(Order.decr);
-        final Bytecode bytecode = traversal.asAdmin().getBytecode();
-        //final JavaTranslator translator = JavaTranslator.of(g);
-        final Map<Bytecode, Traversal.Admin<?, ?>> cache = new HashMap<>();
-        cache.put(bytecode, traversal.asAdmin());
-        final HashSet<?> result = new LinkedHashSet<>(Arrays.asList("ripple", "lop"));
-
-        System.out.println("BYTECODE: " + bytecode + "\n");
-        System.out.println("Bytecode->Traversal.clone() cache: " + TimeUtil.clock(1000, () -> {
-            final Traversal.Admin<?, ?> t = cache.get(bytecode).clone();
-            //assertEquals(result, t.next());
-        }));
-
-        System.out.println("Bytecode->JavaTranslator call    : " + TimeUtil.clock(1000, () -> {
-            final Traversal t = JavaTranslator.of(g).translate(bytecode);
-            //assertEquals(result, t.next());
-        }));
-
-        System.out.println("\n==Second test with reversed execution==\n");
-
-        System.out.println("BYTECODE: " + bytecode + "\n");
-        System.out.println("Bytecode->JavaTranslator call    : " + TimeUtil.clock(1000, () -> {
-            final Traversal t = JavaTranslator.of(g).translate(bytecode);
-            //assertEquals(result, t.next());
-        }));
-
-        System.out.println("Bytecode->Traversal.clone() cache: " + TimeUtil.clock(1000, () -> {
-            final Traversal.Admin<?, ?> t = cache.get(bytecode).clone();
-            //assertEquals(result, t.next());
-        }));
+        System.out.println(g.V().as("a").out("knows").math("((a ^ _) / a)").by("age").by(bothE().count()).toList());
     }
 
-   /* @Test
-    public void testTraversalDSL() throws Exception {
-        Graph g = TinkerFactory.createClassic();
-        assertEquals(2, g.of(TinkerFactory.SocialTraversal.class).people("marko").knows().name().toList().size());
-        g.of(TinkerFactory.SocialTraversal.class).people("marko").knows().name().forEachRemaining(name -> assertTrue(name.equals("josh") || name.equals("vadas")));
-        assertEquals(1, g.of(TinkerFactory.SocialTraversal.class).people("marko").created().name().toList().size());
-        g.of(TinkerFactory.SocialTraversal.class).people("marko").created().name().forEachRemaining(name -> assertEquals("lop", name));
-    }*/
-
     @Test
     @Ignore
     public void benchmarkStandardTraversals() throws Exception {