# Path: priodict.py
# class priorityDictionary(dict):
#     def __init__(self):
#         '''Initialize priorityDictionary by creating binary heap
# of pairs (value,key).  Note that changing or removing a dict entry will
# not remove the old pair from the heap until it is found by smallest() or
# until the heap is rebuilt.'''
#         self.__heap = []
#         dict.__init__(self)
# 
#     def smallest(self):
#         '''Find smallest item after removing deleted items from heap.'''
#         if len(self) == 0:
#             raise IndexError, "smallest of empty priorityDictionary"
#         heap = self.__heap
#         while heap[0][1] not in self or self[heap[0][1]] != heap[0][0]:
#             lastItem = heap.pop()
#             insertionPoint = 0
#             while 1:
#                 smallChild = 2*insertionPoint+1
#                 if smallChild+1 < len(heap) and \
#                         heap[smallChild] > heap[smallChild+1]:
#                     smallChild += 1
#                 if smallChild >= len(heap) or lastItem <= heap[smallChild]:
#                     heap[insertionPoint] = lastItem
#                     break
#                 heap[insertionPoint] = heap[smallChild]
#                 insertionPoint = smallChild
#         return heap[0][1]
# 	
#     def __iter__(self):
#         '''Create destructive sorted iterator of priorityDictionary.'''
#         def iterfn():
#             while len(self) > 0:
#                 x = self.smallest()
#                 yield x
#                 del self[x]
#         return iterfn()
# 	
#     def __setitem__(self,key,val):
#         '''Change value stored in dictionary and add corresponding
# pair to heap.  Rebuilds the heap if the number of deleted items grows
# too large, to avoid memory leakage.'''
#         dict.__setitem__(self,key,val)
#         heap = self.__heap
#         if len(heap) > 2 * len(self):
#             self.__heap = [(v,k) for k,v in self.iteritems()]
#             self.__heap.sort()  # builtin sort likely faster than O(n) heapify
#         else:
#             newPair = (val,key)
#             insertionPoint = len(heap)
#             heap.append(None)
#             while insertionPoint > 0 and \
#                     newPair < heap[(insertionPoint-1)//2]:
#                 heap[insertionPoint] = heap[(insertionPoint-1)//2]
#                 insertionPoint = (insertionPoint-1)//2
#             heap[insertionPoint] = newPair
# 	
#     def setdefault(self,key,val):
#         '''Reimplement setdefault to call our customized __setitem__.'''
#         if key not in self:
#             self[key] = val
#         return self[key]


import SOMTools
import numpy
import scipy.spatial.distance
import itertools
        import matplotlib.pyplot
from priodict import priorityDictionary
    from IPython.display import clear_output
        as dictionaries mapping vertices to lists of neighbors,
        however dictionaries of edges have many advantages
        over lists: they can store extra information (here,
        the lengths), they support fast existence tests,
        and they allow easy modification of the graph by edge
        insertion and removal.  Such modifications are not
        needed here but are important in other graph algorithms.
        Since dictionaries obey iterator protocol, a graph
        represented as described here could be handed without
        modification to an algorithm using Guido's representation.

        Of course, G and G[v] need not be Python dict objects;
        they can be any other object that obeys dict protocol,
        for instance a wrapper in which vertices are URLs
        and a call to G[v] loads the web page and finds its links.
        
        The output is a pair (D,P) where D[v] is the distance
        from start to v and P[v] is the predecessor of v along
        the shortest path from s to v.
        
        Dijkstra's algorithm is only guaranteed to work correctly
        when all edge lengths are positive. This code does not
        verify this property for all edges (only the edges seen
        before the end vertex is reached), but will correctly
        compute shortest paths even for some graphs with negative
        edges, and will raise an exception if it discovers that
        a negative edge has caused it to make a mistake.
        """
        D = {}  # dictionary of final distances
        P = {}  # dictionary of predecessors

# Path: priodict.py
# class priorityDictionary(dict):
#     def __init__(self):
#         '''Initialize priorityDictionary by creating binary heap
# of pairs (value,key).  Note that changing or removing a dict entry will
# not remove the old pair from the heap until it is found by smallest() or
# until the heap is rebuilt.'''
#         self.__heap = []
#         dict.__init__(self)
# 
#     def smallest(self):
#         '''Find smallest item after removing deleted items from heap.'''
#         if len(self) == 0:
#             raise IndexError, "smallest of empty priorityDictionary"
#         heap = self.__heap
#         while heap[0][1] not in self or self[heap[0][1]] != heap[0][0]:
#             lastItem = heap.pop()
#             insertionPoint = 0
#             while 1:
#                 smallChild = 2*insertionPoint+1
#                 if smallChild+1 < len(heap) and \
#                         heap[smallChild] > heap[smallChild+1]:
#                     smallChild += 1
#                 if smallChild >= len(heap) or lastItem <= heap[smallChild]:
#                     heap[insertionPoint] = lastItem
#                     break
#                 heap[insertionPoint] = heap[smallChild]
#                 insertionPoint = smallChild
#         return heap[0][1]
# 	
#     def __iter__(self):
#         '''Create destructive sorted iterator of priorityDictionary.'''
#         def iterfn():
#             while len(self) > 0:
#                 x = self.smallest()
#                 yield x
#                 del self[x]
#         return iterfn()
# 	
#     def __setitem__(self,key,val):
#         '''Change value stored in dictionary and add corresponding
# pair to heap.  Rebuilds the heap if the number of deleted items grows
# too large, to avoid memory leakage.'''
#         dict.__setitem__(self,key,val)
#         heap = self.__heap
#         if len(heap) > 2 * len(self):
#             self.__heap = [(v,k) for k,v in self.iteritems()]
#             self.__heap.sort()  # builtin sort likely faster than O(n) heapify
#         else:
#             newPair = (val,key)
#             insertionPoint = len(heap)
#             heap.append(None)
#             while insertionPoint > 0 and \
#                     newPair < heap[(insertionPoint-1)//2]:
#                 heap[insertionPoint] = heap[(insertionPoint-1)//2]
#                 insertionPoint = (insertionPoint-1)//2
#             heap[insertionPoint] = newPair
# 	
#     def setdefault(self,key,val):
#         '''Reimplement setdefault to call our customized __setitem__.'''
#         if key not in self:
#             self[key] = val
#         return self[key]


# Path: SOMgraph.py
import SOMTools
import numpy
import scipy.spatial.distance
import itertools
        import matplotlib.pyplot
from priodict import priorityDictionary
    from IPython.display import clear_output

        as dictionaries mapping vertices to lists of neighbors,
        however dictionaries of edges have many advantages
        over lists: they can store extra information (here,
        the lengths), they support fast existence tests,
        and they allow easy modification of the graph by edge
        insertion and removal.  Such modifications are not
        needed here but are important in other graph algorithms.
        Since dictionaries obey iterator protocol, a graph
        represented as described here could be handed without
        modification to an algorithm using Guido's representation.

        Of course, G and G[v] need not be Python dict objects;
        they can be any other object that obeys dict protocol,
        for instance a wrapper in which vertices are URLs
        and a call to G[v] loads the web page and finds its links.
        
        The output is a pair (D,P) where D[v] is the distance
        from start to v and P[v] is the predecessor of v along
        the shortest path from s to v.
        
        Dijkstra's algorithm is only guaranteed to work correctly
        when all edge lengths are positive. This code does not
        verify this property for all edges (only the edges seen
        before the end vertex is reached), but will correctly
        compute shortest paths even for some graphs with negative
        edges, and will raise an exception if it discovers that
        a negative edge has caused it to make a mistake.
        """
        D = {}  # dictionary of final distances
        P = {}  # dictionary of predecessors

        Q = priorityDictionary()   # est.dist. of non-final vert.