def calculate_objective(sol, D):
    """ The objective is the total cost of all routes in VRP solution. D is 
    the full distance matrix of the points in the problem (also includes the
    depot with index of 0), and solution is a list containing giant tour
    encoded VRP solution, where 0 indicates a visit to the depot OR a list of 
    routes leaving and returning to the depot.
    """
    f = 0.0
    if hasattr(sol[0], '__iter__'):
        # routes are separately
        for route in sol:
            f+= sum( D[route[i-1],route[i]] for i in range(1,len(route)))
            # sometimes a end or start (or both) visit to depot may be missing
            if route[0]!=0:
                f+=D[0,route[0]]
            if route[-1]!=0:
                f+=D[route[-1],0]
    else:
        # giant tour encoding
        f = sum( D[sol[i-1],sol[i]] for i in range(1,len(sol)))
        f+=D[sol[-1], sol[0]]
    return f