This function runs k-means on given data and initial set of centroids.
           maxiter: maximum number of iterations to run.
           record_heterogeneity: (optional) a list, to store the history of heterogeneity as function of iterations
                             if None, do not store the history.
           verbose: if True, print how many data points changed their cluster labels in each iteration

def kmeans(self, maxiter, record_heterogeneity=None, verbose=False):
        '''This function runs k-means on given data and initial set of centroids.
           maxiter: maximum number of iterations to run.
           record_heterogeneity: (optional) a list, to store the history of heterogeneity as function of iterations
                             if None, do not store the history.
           verbose: if True, print how many data points changed their cluster labels in each iteration'''
        centroids = self.centroids[:]
        prev_cluster_assignment = None
        for itr in range(int(maxiter)):        
            if verbose:
                print(itr)
            # 1. Make cluster assignments using nearest centroids
            # YOUR CODE HERE
            cluster_assignment = self.assign_clusters() 
            # 2. Compute a new centroid for each of the k clusters, averaging all data points assigned to that cluster.
            # YOUR CODE HERE
            centroids = self.revise_centroids()  
            # Check for convergence: if none of the assignments changed, stop
            if prev_cluster_assignment is not None and \
              (prev_cluster_assignment==self.cluster_assignment).all():
                break
            # Print number of new assignments 
            if prev_cluster_assignment is not None:
                num_changed = np.sum(prev_cluster_assignment!=self.cluster_assignment)
                if verbose:
                    print('    {0:5d} elements changed their cluster assignment.'.format(num_changed))   
            # Record heterogeneity convergence metric
            if record_heterogeneity is not None:
                # YOUR CODE HERE
                score = compute_heterogeneity(self.data, self.k, centroids, cluster_assignment)
                record_heterogeneity.append(score)
            prev_cluster_assignment = cluster_assignment[:]
        self.centroids=centroids
        self.cluster_assignment=cluster_assignment
        return centroids, cluster_assignment