Pairwise Comparison of Attributes of the Target Vertices

Hi TG Team,

Suppose I have a graph of two vertex types - Car and Accident. The relationship is Car - (INVOLVED_IN) -> Accident. Accident vertex has a datetime attribute called “time”. Now for the accidents originated from each car, I want to compare the accident time between any two accidents. If the time difference is bigger smaller than a threshold, I want to store the car vertex and the corresponding accident pairs into a mapaccum.

What is the most efficient way to do this? My attempt is to first create a mapaccum storing Car vertex as key and a setaccum of corresponding accidents as value. Then I write a nested for loop to loop through each claim set twice, and determine whether the time difference is greater than the threshold. But the problem is that when using IF or CASE WHEN, there must be only one operation after the the THEN statement, which means that I need to add both accidents from a pair to a set or something in just one line, and I can’t figure out how.

I was also considering creating undirected edges between accidents to do the comparison, but since I have too many accidents in my graph, it will lead to way too many undirected edges. I’ m not sure if this is a good way.

Any help? Thanks !

Think I found a way to do it. Here is the code:

SetAccum<Vertex> @accident_set;
out = SELECT a1 FROM Accident:a1 - (<INVOLVED_IN) - Car:c - (INVOLVED_IN>) -> Accident:a2
WHERE a1 != a2
ACCUM CASE WHEN abs(datetime_diff(a1.accident_time, a2.accident_time)) < threshold THEN
car.@accident_set += (a1, a2) END;

However, the code gave the following error:

type of a2 in the list is not consistent with other elements

My workaround is to use listaccum instead of setaccum and replace (a1, a2) with [a1, a2]. The code now works but the listaccum will contain duplicates which is not optimal. So why would that error happen? It seems my code was correct.

Thx

Hey,

This is probably happening because your accumulation step is syntactically incorrect. When accumulating a SetAccum, you can either add individual elements to it or entire other SetAccums. You are effectively trying to add another set to car.@accident_set, but (a1,a2) is not valid syntax for a SetAccum. Try doing this instead:

SetAccum<Vertex> @accident_set;

out = SELECT a1 FROM Accident:a1 - (<INVOLVED_IN) - Car:c - (INVOLVED_IN>) -> Accident:a2
WHERE a1 != a2
ACCUM CASE WHEN abs(datetime_diff(a1.accident_time, a2.accident_time)) < threshold THEN
car.@accident_set += a1, car.@accident_set += a2 END;

However, this would still lead to no association between any two accidents in a pairing. It would just be one massive unassociated list. To add pairs to a SetAccum, you will need to TYPEDEF a TUPLE as such:

TYPEDEF TUPLE <Vertex<Accident> a1, Vertex<Accident> a2> pair;
SetAccum<pair> @accident_set;

out = SELECT a1 FROM Accident:a1 - (<INVOLVED_IN) - Car:c - (INVOLVED_IN>) -> Accident:a2
WHERE a1 != a2 and abs(datetime_diff(a1.accident_time, a2.accident_time)) < threshold
ACCUM car.@accident_set += (pair(a1,a2));

However, some weird tuple VERTEX typing behavior prevents you from having a CASE/IF statement check before the accumulation. You could have the CASE structure only if you broadened the TUPLE definition to accept all VERTEX types for the first argument. You may not want to do this in the interest of having access to VERTEX attributes, but if you did, it would be easier to implement an additional check to prevent reversed duplicate pairs from being added:

TYPEDEF TUPLE <Vertex a1, Vertex a2> pair;
SetAccum<pair> @accident_set;

out = SELECT a1 FROM Accident:a1 - (<INVOLVED_IN) - Car:c - (INVOLVED_IN>) -> Accident:a2
WHERE a1 != a2 and abs(datetime_diff(a1.accident_time, a2.accident_time)) < threshold
ACCUM IF (NOT g.@accident_set.contains(pair(a2,a1))) THEN car.@accident_set += (pair(a1,a2)) END;

This broadened VERTEX type may be a deal-breaker, in which case I recommend removing duplicates from the SetAccum in a different statement following this one.

2 Likes

How about this tweak - which simplifies things a bit

TYPEDEF TUPLE <Vertex a1, Vertex a2> pair;
SetAccum @accident_set;

out = SELECT a1 FROM Accident:a1 - (<INVOLVED_IN) - Car:c - (INVOLVED_IN>) -> Accident:a2
WHERE a1 != a2 and a1.accident_time > a2.accident_time and abs(datetime_diff(a1.accident_time, a2.accident_time)) < threshold
ACCUM c.@accident_set += pair(a1,a2) ;

5 Likes

Great idea, now everything can be in a single statement and duplicates are accounted for.

4 Likes

@lshestakov @markmegerian
Thanks for the timely reply :slight_smile: That solves the problem perfectly.

By the way, I was using (a1, a2) for the set accumulation because in the document, there is an example:

@@intSetAccum += (1,2,3,4); # Can create simple sets this way

Maybe it only works with integers not vertices idk :slight_smile:

1 Like