Using parameter to determine the length of an n-Hop Pattern

Hello! I’m trying to create a query that returns the n-hop ego net for a node, where the input parameters are the starting node and the number of hops. However, I get an error when I try to use the input parameter to set the number of hops in the pattern. For example, if the pattern is:
X:x -(F>*..3)- Y:y
, I would like to set the length with a parameter:

INT num_hops = 3;
X:x -(F>*..num_hops)- Y:y

However, this produces an error.

To be specific, here is my query:

USE GRAPH RoadMap
SET syntax_version="v2"

CREATE QUERY n_hop_neighborhood(VERTEX<Coordinate> start_node, INT num_hops) 
{

start = {start_node};

SetAccum<VERTEX> @@vertex_set;
SetAccum<EDGE> @@edge_set;

dummy = SELECT c2
    FROM start:c1 -(Road>*..num_hops)- Coordinate:c2
    ACCUM
    @@vertex_set += c2, 
    @@vertex_set += c1;

my_nodes = SELECT c
    FROM Coordinate:c
    WHERE c in @@vertex_set;

dummy = SELECT c2
    FROM Coordinate:c1 -(Road>:r)- Coordinate:c2
    WHERE c1 in @@vertex_set and c2 in @@vertex_set
    ACCUM
    @@edge_set += r; 

print my_nodes, @@edge_set;

}

It produces the following error message:

line 15:28 no viable alternative at input 'from start:c1 -(Road>*..num_hops'
line 15:49 mismatched input ':' expecting {INTERSECT, MINUS, UNION, '%', '&', '+', '-', '*', '/', '.', ';', '>', '|', '<<'}
line 17:22 no viable alternative at input 'c2,'
Parsing encountered 3 syntax error(s)

If I change the line FROM start:c1 -(Road>*..num_hops)- Coordinate:c2 to e.g. FROM start:c1 -(Road>*..3)- Coordinate:c2, it all works.

Any help would be much appreciated!

One easy change, if the syntax doesn’t support a variable, is to use a loop for the number of hops, and only add the target vertex on the final iteration. Perhaps not as elegant, but it works.

1 Like

Thank you for your advice, @markmegerian ! I’m not sure I fully understand your suggestion, but I tried to follow it. I replaced the number of hops with a loop which iteratively grows the vertex set. This produces the correct results. Here is my code:

USE GRAPH RoadMap
SET syntax_version="v2"

CREATE QUERY n_hop_neighborhood(VERTEX<Coordinate> start_node, INT num_hops) 
{
Start = {start_node};
SetAccum<VERTEX> @@vertex_set;
SetAccum<EDGE> @@edge_set;

dummy = SELECT c1
    FROM Start:c1
    ACCUM
    @@vertex_set += c1;

FOREACH i in RANGE[1, num_hops] DO
    dummy = SELECT c2 
        FROM Coordinate:c1 -(Road>:r)- Coordinate:c2
        WHERE c1 in @@vertex_set //and c2 not in @@vertex_set
        ACCUM
        @@vertex_set += c2;
END; 

my_nodes = SELECT c
    FROM Coordinate:c
    WHERE c in @@vertex_set;

dummy = SELECT c2
    FROM Coordinate:c1 -(Road>:r)- Coordinate:c2
    WHERE c1 in @@vertex_set and c2 in @@vertex_set
    ACCUM
    @@edge_set += r; 

print my_nodes, @@edge_set;
}

The thing is that I found this approach to be 10x slower than the original one that uses the pattern matching with variable path-length.

Since I work from Python, my current solution will be to create a python-function that creates and runs an interpreted query where the parameter num_hops is set in the query-string before passing it to gsql.

1 Like

I feel like it would be much more efficient to use dummy as the seed set inside the loop and remove the where clause

dummy =  Start; 
my_nodes = Start;

FOREACH i in RANGE[1, num_hops] DO
    nextset = SELECT c2 
        FROM dummy:c1 -(Road>:r)- Coordinate:c2 ;
   my_nodes = my_nodes UNION nextset;
   dummy = nextset; 
END;

PRINT my_nodes;
2 Likes

Thanks a lot, @markmegerian! With your suggestions the query is now faster than the interpreted approach and also simpler.

USE GRAPH RoadMap
SET syntax_version="v2"

CREATE QUERY n_hop_neighborhood(VERTEX<Coordinate> start_node, INT num_hops) 
{

SetAccum<EDGE> @@edge_set;
node_set = {start_node};

expand_set = {start_node};

FOREACH i in RANGE[1, num_hops] DO
    next_set = SELECT c2 
        FROM expand_set:c1 -(Road>:r)- Coordinate:c2
        ACCUM
        @@edge_set += r; 
    node_set = node_set UNION next_set; 
    expand_set = next_set; 
END; 

print node_set, @@edge_set AS edge_set;

}
2 Likes