def clone(self):
        """Returns a deep copy of self

        Function clones:
        
        * routes
        * allocation
        * nodes

        Returns
        -------
        SavingsSolution
            A clone (deepcopy) of the instance itself
        """

        new_solution = self.__class__(self._problem)

        # Clone routes
        for index, r in enumerate(self._routes):
            new_route = new_solution._routes[index] = models.Route(self._problem)
            for node in r.nodes():
                # Insert new node on new route
                new_node = new_solution._nodes[node.name()]
                new_route.allocate([new_node])

        # remove empty routes from new solution
        new_solution._routes = [route for route in new_solution._routes if route._nodes]
        
        return new_solution