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.

    Use the given relationship for traversal.

    Args:
        criterion (Callable): Function that returns True on the Cuds object
            that is searched.
        root (Cuds): Starting point of search
        rel (OntologyRelationship): The relationship (incl. subrelationships)
            to consider for traversal.
        find_all (bool): Whether to find all cuds_objects satisfying
            the criterion.
        max_depth (int, optional): The maximum depth for the search.
            Defaults to float("inf").
        current_depth (int, optional): The current search depth. Defaults to 0.
        visited (Set[Union[UUID, URIRef]], optional): The set of uids
            already visited. Defaults to None.

    Returns:
        Union[Cuds, List[Cuds]]: The element(s) found.
    """
    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