0
votes

I'm trying to traverse the graph with an interval. Each edge has a property("interval") storing the intervals. I'm using withSack to propagate the intersections of the intervals to the next step. If there's no intersection the traversal should stop.

For example:

V1          e1         V2         e2          V3         e3          V4

O----------------------O----------------------O----------------------O
^
    [[1,3],[5,7]]              [[4,6]]                [[7,9]]
     e1.interval             e2.interval            e3.interval

If I start traversal from V1 with interval [2,8], I want it to return

V1: [[2,3],[5,7]]
V2: [[5,6]]

Notice that V3 and V4 is not included since the intersected interval on e2 stops at 6.

I'm using Tinkerpop Java API and for this purpose, I defined a method that returns the intersections of the intervals and tried to use withSack(Lambda.biFunction(...)). The function has while loop with curly braces({}) and I think it causes a problem on the gremlin server's script engine. The exception I'm getting is this:

Script28.groovy: 1: expecting '}', found 'return' @ line 1, column 520.
   get(j).get(1)) i++; else j++;}return int

I'm passing the function as a string to (Lambda.biFunction(...)) like this:

"x, y -> " +
"List<List<Long>> intersections = new ArrayList();" +
"if (x.isEmpty() || y.isEmpty()) return new ArrayList<>();" +
"int i = 0, j = 0;" +
"while (i < x.size() && j < y.size()) {" +
"long low = Math.max(x.get(i).get(0), y.get(j).get(0));" +
"long high = Math.min(x.get(i).get(1), y.get(j).get(1));" +
"if (low <= high) intersections.add(Arrays.asList(low, high));" +
"if (x.get(i).get(1) < y.get(j).get(1)) i++; else j++;" +
"}" +
"return intersections;";

For the readability I'm also putting the original function:

public List<List<Long>> intersections(List<List<Long>> x, List<List<Long>> y) {
    List<List<Long>> intersections = new ArrayList();

    if (x.isEmpty() || y.isEmpty()) {
        return new ArrayList<>();
    }
    int i = 0, j = 0;

    while (i < x.size() && j < y.size()) {
        long low = Math.max(x.get(i).get(0), y.get(j).get(0));
        long high = Math.min(x.get(i).get(1), y.get(j).get(1));

        if (low <= high) {
            intersections.add(Arrays.asList(low, high));
        }

        if (x.get(i).get(1) < y.get(j).get(1)) {
            i++;
        } else {
            j++;
        }
    }

    return intersections;
}

I have 2 questions:

  1. How to pass a complex lambda function like this to gremlin server?
  2. Is there a better way to accomplish this?
1

1 Answers

1
votes

The string of your lambda needs to match a Groovy closure form. For your multiline and multi-argument script you need to wrap some curly braces around it:

withSack(Lambda.biFunction(
"{ x, y -> " +
"  intersections = []\n" +
"  if (x.isEmpty() || y.isEmpty()) return []\n" +
"  i = 0\n" +
"  j = 0\n" +
"  while (i < x.size() && j < y.size()) {\n" +
"    def low = Math.max(x[i][0], y[j][0])\n" +
"    def high = Math.min(x[i][1], y[j][1])\n" +
"    if (low <= high) intersections.add(Arrays.asList(low, high))\n" +
"    if (x[i][1] < y[j][1]) i++; else j++\n" +
"  }\n" +
"  return intersections\n" +
"}"))

I also converted your Java to Groovy (hopefully correctly) which ends up being a little more succinct but that part should be unnecessary.