docs: def __get_scope(cls,
              expr: Union['Expression', Tuple]) -> Set[str]:
          '''Returns the set of fluents in the expression's scope.
  
          Args:
              expr: Expression object or nested tuple of Expressions.
  
          Returns:
              The set of fluents in the expression's scope.
          '''
          scope = set()
          for i, atom in enumerate(expr):
              if isinstance(atom, Expression):
                  scope.update(cls.__get_scope(atom._expr))
              elif type(atom) in [tuple, list]:
                  scope.update(cls.__get_scope(atom))
              elif atom == 'pvar_expr':
                  functor, params = expr[i+1]
                  arity = len(params) if params is not None else 0
                  name = '{}/{}'.format(functor, arity)
                  scope.add(name)
                  break
          return scope