Return a list of all rooted subtrees (each as a list of Location objects).

def get_all_rooted_subtrees_as_lists(self, start_location=None):
        """Return a list of all rooted subtrees (each as a list of Location objects)."""
        if start_location is not None and start_location not in self._location_to_children:
            raise AssertionError(u'Received invalid start_location {} that was not present '
                                 u'in the tree. Present root locations of complex @optional '
                                 u'queries (ones that expand vertex fields within) are: {}'
                                 .format(start_location, self._location_to_children.keys()))

        if start_location is None:
            start_location = self._root_location

        if len(self._location_to_children[start_location]) == 0:
            # Node with no children only returns a singleton list containing the null set.
            return [[]]

        current_children = sorted(self._location_to_children[start_location])

        # Recursively find all rooted subtrees of each of the children of the current node.
        location_to_list_of_subtrees = {
            location: list(self.get_all_rooted_subtrees_as_lists(location))
            for location in current_children
        }

        # All subsets of direct child Location objects
        all_location_subsets = [
            list(subset)
            for subset in itertools.chain(*[
                itertools.combinations(current_children, x)
                for x in range(0, len(current_children) + 1)
            ])
        ]

        # For every possible subset of the children, and every combination of the chosen
        # subtrees within, create a list of subtree Location lists.
        new_subtrees_as_lists = []
        for location_subset in all_location_subsets:
            all_child_subtree_possibilities = [
                location_to_list_of_subtrees[location]
                for location in location_subset
            ]
            all_child_subtree_combinations = itertools.product(*all_child_subtree_possibilities)

            for child_subtree_combination in all_child_subtree_combinations:
                merged_child_subtree_combination = list(itertools.chain(*child_subtree_combination))
                new_subtree_as_list = location_subset + merged_child_subtree_combination
                new_subtrees_as_lists.append(new_subtree_as_list)

        return new_subtrees_as_lists