import math


def iterate_pagerank(corpus, damping_factor):

    """
    
    Return PageRank values for each page by iteratively updating
    PageRank values until convergence.
    Return a dictionary where keys are page names, and values are
    their estimated PageRank value (a value between 0 and 1). All
    PageRank values should sum to 1.
    
    """
    
    pagerank = dict()
    newrank = dict()

    # Assign initial values for pagerank

    for page in corpus:
        pagerank[page] = 1 / len(corpus)

    repeat = True

    while repeat:

        
        # Calculate new rank values based on all of the current rank values
        
        for page in pagerank:
            total = float(0)

            for possible_page in corpus: 
                
                # We consider each possible page that links to current page
                
                if page in corpus[possible_page]:
                    total += pagerank[possible_page] / len(corpus[possible_page])
                
                # A page that has no links is interpreted as having one link for every page (including itself)
                
                if not corpus[possible_page]:
                    total += pagerank[possible_page] / len(corpus)

            
            newrank[page] = (1 - damping_factor) / len(corpus) + damping_factor * total

        
        repeat = False

        
        # If any of the values changes by more than the threshold, repeat process
        
        for page in pagerank:
            if not math.isclose(newrank[page], pagerank[page], abs_tol=0.001):
                repeat = True
            
            # Assign new values to current values
            
            pagerank[page] = newrank[page]

    return pagerank