Guest User

Untitled

a guest
Feb 20th, 2018
73
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 6.65 KB | None | 0 0
  1. #!/usr/bin/env python2.6
  2. #coding=utf8
  3.  
  4. import re
  5.  
  6. COLOR_MAPPING = {
  7. 1: 'gold',
  8. 2: 'blue',
  9. 3: 'gold4',
  10. 30: 'deepskyblue', # Ligne 3b
  11. 4: 'hotpink3',
  12. 5: 'orange',
  13. 6: 'springgreen2',
  14. 7: 'pink1',
  15. 8: 'darkorchid2',
  16. 9: 'yellow3',
  17. 11: 'tan4',
  18. 12: 'springgreen4',
  19. 13: 'skyblue',
  20. 14: 'indigo',
  21. }
  22.  
  23. def slugify(name):
  24. chars = u'abcdefghijklmnopqrstuvwxyz'
  25. special_chars = {
  26. u'é': u'e', u'è': u'e', u'â': u'a',
  27. u'ê': u'e', u'î': u'i', u'ô': u'o',
  28. u'ç': u'c', u'ü': u'u', u'—': u' '
  29. }
  30. sluged_string = ''
  31. for char in name.lower():
  32. if char in chars:
  33. sluged_string += char
  34. elif char in special_chars:
  35. sluged_string += special_chars[char]
  36. return sluged_string
  37.  
  38.  
  39. class Node(object):
  40. def __init__(self, name):
  41. self.name = name
  42. self.reset()
  43.  
  44. def reset(self):
  45. self.previous = None
  46. self.traveled = float('inf')
  47. self.line_nb = None
  48.  
  49. def __repr__(self):
  50. return '<Node: %s (%s)>' % (self.name.encode('utf8'), self.traveled)
  51.  
  52. class Edge(object):
  53. def __init__(self, node1, node2, weight, line_nb):
  54. self.node1 = node1
  55. self.node2 = node2
  56. self.weight = weight
  57. self.line_nb = line_nb
  58.  
  59. def give_other_node(self, node):
  60. '''Return the other node'''
  61. if node is self.node1:
  62. return self.node2
  63. elif node is self.node2:
  64. return self.node1
  65.  
  66. def __repr__(self):
  67. return '<Edge: %s -%s- %s>' % (self.node1.name, self.weight, self.node2.name)
  68.  
  69. class Graph(object):
  70.  
  71. regex_import = re.compile(r'(?P<line_nb>\d+): "(?P<station1>.+?)" -(?P<weight>\d+)- "(?P<station2>.+?)"')
  72.  
  73. def __init__(self):
  74. self.nodes = []
  75. self.edges = []
  76. self.edge_start = None
  77.  
  78. def add_node(self, node):
  79. if not node in self.nodes:
  80. self.nodes.append(node)
  81.  
  82. def add_edge(self, edge):
  83. if not edge in self.edges:
  84. self.edges.append(edge)
  85.  
  86. def search_station(self, name):
  87. selection = [n for n in self.nodes if slugify(name.decode('utf8')) in slugify(n.name)]
  88. if len(selection) == 1:
  89. return [selection[0]]
  90. elif not selection:
  91. return []
  92. for node in selection:
  93. if slugify(name.decode('utf8')) == slugify(node.name):
  94. return [node]
  95. else:
  96. return selection
  97.  
  98. def import_from_file(self, filename):
  99.  
  100. stations = {}
  101. edges = []
  102.  
  103. for line in open(filename, 'r'):
  104. m = self.regex_import.match(line)
  105. if m:
  106. line_nb = int(m.group('line_nb'))
  107. station1 = m.group('station1').decode('utf8')
  108. weight = int(m.group('weight'))
  109. station2 = m.group('station2').decode('utf8')
  110.  
  111. if not station1 in stations:
  112. stations[station1] = Node(station1)
  113. if not station2 in stations:
  114. stations[station2] = Node(station2)
  115.  
  116. edges.append(Edge(stations[station1], stations[station2], weight, line_nb))
  117.  
  118. self.edges = edges
  119. self.nodes = stations.values()
  120.  
  121. def give_connected_edges(self, node):
  122. edges = []
  123. for edge in self.edges:
  124. if node is edge.node1 or node is edge.node2:
  125. edges.append(edge)
  126.  
  127. return edges
  128.  
  129. def init_dijkstra(self, node_start):
  130. for node in self.nodes:
  131. node.reset()
  132.  
  133. self.node_start = node_start
  134.  
  135. self.node_start.traveled = 0
  136. nodes_not_traveled = list(self.nodes)
  137.  
  138. while nodes_not_traveled:
  139. n1 = min(nodes_not_traveled, key=lambda x: x.traveled)
  140. nodes_not_traveled.remove(n1)
  141.  
  142. for edge in self.give_connected_edges(n1):
  143. if n1.line_nb and n1.line_nb != edge.line_nb:
  144. changing_malus = 300
  145. else:
  146. changing_malus = 0
  147. n2 = edge.give_other_node(n1)
  148. if n2.traveled > n1.traveled + edge.weight + changing_malus:
  149. n2.traveled = n1.traveled + edge.weight + changing_malus
  150. n2.previous = n1
  151. n2.line_nb = edge.line_nb
  152.  
  153. def best_path_dijkstra(self, node_end):
  154. if self.node_start not in self.nodes:
  155. raise ValueError('Dijkstra not initialized')
  156. path = []
  157. current_node = node_end
  158. while current_node is not self.edge_start:
  159. path.insert(0, current_node)
  160. current_node = current_node.previous
  161.  
  162. return path
  163.  
  164. def export_graphviz(self):
  165. lines = ['graph {']
  166. for node in self.nodes:
  167. lines.append(' "%s";' % node.name)
  168. for edge in self.edges:
  169. lines.append(' "%s" -- "%s" [label="%s", color="%s"];' % (edge.node1.name, edge.node2.name, edge.weight, COLOR_MAPPING[edge.line_nb]))
  170. lines.append('}')
  171.  
  172. return '\n'.join(lines)
  173.  
  174.  
  175. if __name__ == '__main__':
  176.  
  177. g = Graph()
  178. g.import_from_file('paris.gph')
  179.  
  180. print 'Bienvenue dans le programme de calcul d\'itinéraires'
  181. print
  182. print 'Entrez une station de départ'
  183. while True:
  184. station_start = raw_input('>')
  185. stations_found = g.search_station(station_start)
  186. if not len(stations_found):
  187. print 'Aucune station trouvée, recommencez.'
  188. continue
  189. elif len(stations_found) == 1:
  190. station_start = stations_found[0]
  191. break
  192. else:
  193. print 'Plusieurs stations trouvées :'
  194. for i, st in enumerate(stations_found):
  195. print ' - %s : %s' % (i+1, st.name.encode('utf8'))
  196. print
  197. print 'Entrez le numéro de la station voulue :'
  198. while True:
  199. nb_station = input('>')-1
  200. if 0 < nb_station <= len(stations_found):
  201. break
  202. else:
  203. print 'Mauvais numéro, recommencez.'
  204. station_start = stations_found[nb_station]
  205. break
  206.  
  207. print 'Station %s selectionnée pour le départ.' % station_start.name.encode('utf8')
  208. print
  209. print 'Entrez une station d\'arrivée'
  210. while True:
  211. station_end = raw_input('>')
  212. stations_found = g.search_station(station_end)
  213. if not len(stations_found):
  214. print 'Aucune station trouvée, recommencez.'
  215. continue
  216. elif len(stations_found) == 1:
  217. station_end = stations_found[0]
  218. break
  219. else:
  220. print 'Plusieurs stations trouvées :'
  221. for i, st in enumerate(stations_found):
  222. print ' - %s : %s' % (i+1, st.name.encode('utf8'))
  223. print
  224. print 'Entrez le numéro de la station voulue :'
  225. while True:
  226. nb_station = input('>')-1
  227. if 0 <= nb_station <= len(stations_found):
  228. break
  229. else:
  230. print 'Mauvais numéro, recommencez.'
  231. station_end = stations_found[nb_station]
  232. break
  233.  
  234. print 'Station %s selectionnée pour l\'arrivée.' % station_end.name.encode('utf8')
  235.  
  236. print
  237. print 'Itinéraire :'
  238. print '============'
  239. print
  240. g.init_dijkstra(station_start)
  241.  
  242. path = g.best_path_dijkstra(station_end)
  243.  
  244. last_line = 0
  245. last_sta = None
  246.  
  247. for n in path:
  248. if not n.line_nb:
  249. print ' - Entrez dans la station %s et prenez le métro (sans blague)' % n.name.encode('utf8')
  250. elif last_line and n.line_nb != last_line:
  251. print ' - Changez à %s et prendre la ligne %s' % (last_sta.name.encode('utf8'), n.line_nb)
  252. last_line = n.line_nb
  253. last_sta = n
  254. print ' - Arrivée à %s (trop bien \o)' % n.name.encode('utf8')
Add Comment
Please, Sign In to add comment