def _follow_relation_set(self, rel_expr,
                           inverted):
    """Follow a relation group.

    Args:
      rel_expr: A NeuralQueryExpression for what to follow.
      inverted: +1 to follow the relations normally, -1 to use inverses  This is
        a macro, which expands to an expression that computes a weighted set of
        objects obtained by following the relations associated with rel_expr, or
        their inverses if inverted == -1.

    Returns:
      A NeuralQueryExpression

    Raises:
      RelationNameError: If the type of the expression is not a relation group.
    """
    if not self.context.is_group(rel_expr.type_name):
      raise RelationNameError(rel_expr.type_name,
                              'Expression type is not a relation group.')
    g = self.context.get_group(rel_expr.type_name)
    if inverted == +1:
      with tf.name_scope('follow_group_%s' % rel_expr.type_name):
        return (self.follow(g.subject_rel, -1) *
                rel_expr.follow(g.relation_rel, -1)).follow(g.object_rel)
    else:
      with tf.name_scope('follow_group_%s_inverse' % rel_expr.type_name):
        return (self.follow(g.object_rel, -1) *
                rel_expr.follow(g.relation_rel, -1)).follow(g.subject_rel)
Follow a relation group.

    Args:
      rel_expr: A NeuralQueryExpression for what to follow.
      inverted: +1 to follow the relations normally, -1 to use inverses  This is
        a macro, which expands to an expression that computes a weighted set of
        objects obtained by following the relations associated with rel_expr, or
        their inverses if inverted == -1.

    Returns:
      A NeuralQueryExpression

    Raises:
      RelationNameError: If the type of the expression is not a relation group.
    
language/nql/nql/__init__.py