def find_cuds_object(criterion, root, rel, find_all, max_depth=float("inf"),
                     current_depth=0, visited=None):
    """
    Recursively finds an element inside a container
    by considering the given relationship.

    :param criterion: function that returns True on the Cuds object
        that is searched.
    :type criterion: Callable
    :param root: Starting point of search
    :type root: Cuds
    :param rel: The relationship (incl. subrelationships) to consider
    :type rel: Type[Relationship]
    :param find_all: Whether to find all cuds_objects with satisfying
        the criterion.
    :type find_all: bool
    :param max_depth: The maximum depth for the search.
    :type max_depth: Union(float, int)
    :return: the element if found
    :rtype: Union[Cuds, List[Cuds]]
    """
    visited = visited or set()
    visited.add(root.uid)
    output = [root] if criterion(root) else []

    if output and not find_all:
        return output[0]

    if current_depth < max_depth:
        for sub in root.iter(rel=rel):
            if sub.uid not in visited:
                result = find_cuds_object(criterion=criterion,
                                          root=sub,
                                          rel=rel,
                                          find_all=find_all,
                                          max_depth=max_depth,
                                          current_depth=current_depth + 1,
                                          visited=visited)
                if not find_all and result is not None:
                    return result
                if result is not None:
                    output += result
    return output if find_all else None