/[cvs]/nfo/python/scripts/sixdegrees/boostgraph.py
ViewVC logotype

Diff of /nfo/python/scripts/sixdegrees/boostgraph.py

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

revision 1.1 by joko, Fri Feb 8 09:05:02 2008 UTC revision 1.6 by joko, Tue Feb 26 10:11:13 2008 UTC
# Line 3  Line 3 
3  # $Id$  # $Id$
4    
5  # (c) 2008 Andreas Motl <andreas.motl@ilo.de>  # (c) 2008 Andreas Motl <andreas.motl@ilo.de>
6    # (c) 2008 Sebastian Utz <su@rotamente.com>
7    
8  # This program is free software: you can redistribute it and/or modify  # This program is free software: you can redistribute it and/or modify
9  # it under the terms of the GNU Affero General Public License as published by  # it under the terms of the GNU Affero General Public License as published by
# Line 23  Line 24 
24  #  #
25  # BGL-Python Homepage: http://osl.iu.edu/~dgregor/bgl-python/  # BGL-Python Homepage: http://osl.iu.edu/~dgregor/bgl-python/
26  #  #
27  # Documentation:  # Documentation (Boost):
28  #  - http://osl.iu.edu/~dgregor/bgl-python/reference/boost.graph.html  #  - http://www.boost.org/libs/graph/doc/graph_theory_review.html
29  #  - http://www.boost.org/libs/graph/doc/depth_first_search.html  #  - http://www.boost.org/libs/graph/doc/depth_first_search.html
30    #  - http://www.boost.org/boost/graph/depth_first_search.hpp
31    #  - http://www.boost.org/libs/graph/doc/DFSVisitor.html
32    #  - http://www.boost.org/libs/graph/example/dfs-example.cpp
33    #
34    # Documentation (BGL-Python):
35    #  - http://osl.iu.edu/~dgregor/bgl-python/reference/boost.graph.html
36  #  #
37  # Subversion-Repository: https://svn.osl.iu.edu/svn/projects_viz/bgl-python/  # Subversion-Repository: https://svn.osl.iu.edu/svn/projects_viz/bgl-python/
38    
39    
40    RANDOM_MAX_NODES = 10
41    RANDOM_MAX_CHILDREN_PER_NODE = 10
42    MAX_SEARCH_DEPTH = 50
43    
44    
45    DEBUG = True
46    DEBUG = False
47    
48    ENABLE_PROFILING = False
49    
50    if ENABLE_PROFILING:
51      import profile
52      from profile import Profile
53    
54    
55  import sys, os  import sys, os
56    import random
57    
58  sys.path.append('bgl_python')  sys.path.append('bgl_python')
59  os.environ['PATH'] += ';' + './bgl_python'  os.environ['PATH'] += ';' + './bgl_python'
# Line 40  import boost.graph as bgl Line 63  import boost.graph as bgl
63    
64    
65  # from http://www.boost.org/libs/graph/doc/DFSVisitor.html  # from http://www.boost.org/libs/graph/doc/DFSVisitor.html
66  class tree_edges_dfs_visitor(bgl.dfs_visitor):  #class tree_edges_dfs_visitor(bgl.dfs_visitor):
67    class dfs_visitor_debug(bgl.dfs_visitor):
68    #class tree_edges_bfs_visitor(bgl.bfs_visitor):
69        
70    def __init__(self, name_map):    def __init__(self, startVertex, endVertex, maxdepth, color_map):
71        
72        print dir(self)
73        
74      #bgl.dfs_visitor.__init__(self)      #bgl.dfs_visitor.__init__(self)
75      self.name_map = name_map      #self.name_map = name_map
76        
77        self.startVertex = startVertex
78        self.endVertex = endVertex
79        
80        # for recognizing path switches
81      self.state = True      self.state = True
82        
83        # for tracking paths
84        self.paths = []
85        self.current_path = []
86        
87        # for limiting search depth
88        """
89        self.color_map = color_map
90        self.maxdepth = maxdepth
91        self.depth = 0
92        """
93        
94        self.level = 0
95        
96    
97      def back_edge(self, e, g):
98        self._touch_edge(e, g, 'back_edge')
99    
100      def forward_or_cross_edge(self, e, g):
101        self._touch_edge(e, g, 'forward_or_cross_edge')
102    
103    def tree_edge(self, e, g):    def tree_edge(self, e, g):
104        self._touch_edge(e, g, 'tree_edge')
105    
106      def examine_edge(self, e, g):
107        self._touch_edge(e, g, 'examine_edge')
108    
109      def _touch_edge(self, e, g, label=''):
110        
111      (u, v) = (g.source(e), g.target(e))      (u, v) = (g.source(e), g.target(e))
112      print "Tree edge ",      
113      print self.name_map[u],      # increase current search depth (level)
114        """
115        self.depth += 1
116        
117        # check if maximum depth reached
118        if self.depth == self.maxdepth:
119          # color all succeeding vertices to black (mark as "already visited")
120          # BUG!!! marks too many nodes
121          for child_edge in g.out_edges(v):
122            end_vertex = g.target(child_edge)
123            #self.color_map[end_vertex] = bgl.Color(bgl.Color.gray)
124        """
125        
126        name_map = g.vertex_properties['node_id']
127        
128        if label:
129          print "%s:\t" % label,
130        #print "edge ",
131        print name_map[u],
132      print " -> ",      print " -> ",
133      print self.name_map[v]      print name_map[v]
134      self.state = True      
135        #self.state = True
136        
137        if u == self.startVertex:
138          print "starting"
139          self.current_path = []
140    
141        # skip circular references
142        if v != self.startVertex:
143          self.current_path.append(e)
144    
145        if v == self.endVertex and self.current_path:
146          print "found:"
147          print self.current_path
148          self.paths.append(self.current_path)
149          self.current_path = []
150    
151    
152      def _touch_vertex(self, v, g, label=''):
153        name_map = g.vertex_properties['node_id']
154        id = name_map[v]
155        print '%s:\t%s' % (label, id)
156    
157    
158    def start_vertex(self, v, g):    def start_vertex(self, v, g):
159        self._touch_vertex(v, g, 'start_vertex')
160    
161      def discover_vertex(self, v, g):
162        self._touch_vertex(v, g, 'discover_vertex')
163    
164      def initialize_vertex(self, v, g):
165        self._touch_vertex(v, g, 'initialize_vertex')
166    
167      def examine_vertex(self, v, g):
168        self._touch_vertex(v, g, 'examine_vertex')
169    
170      def finish_vertex(self, v, g):
171        self._touch_vertex(v, g, 'finish_vertex')
172    
173    
174      """
175      def start_vertex(self, v, g):
176        self._seperator('start_vertex')
177        #pass
178      #print 'sssss'      #print 'sssss'
179      self._seperator()  
180      def discover_vertex(self, v, g):
181        #print '>>>'
182        self._seperator('discover_vertex')
183        #pass
184    
185    def initialize_vertex(self, v, g):    def initialize_vertex(self, v, g):
186      #print '>>>'      #print '>>>'
187      self._seperator()      self._seperator('initialize_vertex')
188    
189      def examine_vertex(self, v, g):
190        self._seperator('examine_vertex')
191    
192    def finish_vertex(self, v, g):    def finish_vertex(self, v, g):
193      #print '<<<'      #print '<<<'
194      self._seperator()      if self.current_path:
195          self.paths.append(self.current_path)
196        self.current_path = []
197        self.depth = 0
198        self._seperator('finish_vertex')
199      """
200    
201    def _seperator(self):    def _seperator(self, label = 'unknown'):
202      if self.state:      if 1 or self.state:
203        print '-' * 21        print '-' * 21, label
204        self.state = False        self.state = False
205    
206    
207    class tree_edges_dfs_visitor(bgl.dfs_visitor):
208    
209      def __init__(self, startVertex, endVertex, maxdepth, color_map):
210        
211        #print dir(self)
212        
213        #bgl.dfs_visitor.__init__(self)
214        #self.name_map = name_map
215        
216        self.startVertex = startVertex
217        self.endVertex = endVertex
218        
219        # for recognizing path switches
220        self.state = True
221        
222        # for tracking paths
223        self.paths = []
224        self.current_path = []
225        
226        # for limiting search depth
227        """
228        self.color_map = color_map
229        self.maxdepth = maxdepth
230        self.depth = 0
231        """
232        
233        self.level = 0
234    
235      def tree_edge(self, e, g):
236        self._touch_edge(e, g, 'tree_edge')
237    
238      def forward_or_cross_edge(self, e, g):
239        #self._touch_edge(e, g, 'forward_or_cross_edge')
240        self.find_new_variations_from_source(e, g)
241        self.find_new_variations_to_target(e, g)
242    
243      
244      def find_new_variations_from_source(self, e, g):
245        # find additional solutions as parts of already established ones (e.g. shortcuts)
246        localEndVertex = g.target(e)
247        path_additional = []
248        for path in self.paths:
249          found = False
250          for edge in path:
251            if found:
252              path_additional.append(edge)
253            else:
254              if g.source(edge) == localEndVertex:
255                #print "found2"
256                found = True
257                path_additional.append(e)
258                path_additional.append(edge)
259        
260        #print "find_new_variations_from_source:", path_additional
261        if path_additional:
262          self.paths.append(path_additional)
263    
264      def find_new_variations_to_target(self, e, g):
265        # find additional solutions as parts of already established ones (e.g. shortcuts)
266        localStartVertex = g.source(e)
267        localEndVertex = g.target(e)
268        
269        #return
270        
271        #if not (self.endVertex == localEndVertex and self.startVertex != localStartVertex):
272        if not (self.endVertex == localEndVertex):
273          return
274        
275        # find "direct" solution (start- and end-vertices are directly connected)
276        if self.startVertex == localStartVertex:
277          self.paths.append([e])
278          return
279        
280        #print "check"
281        path_additional = []
282        for path_iter in self.paths:
283          found = False
284          path = list(path_iter)
285          path.reverse()
286          for edge in path:
287            if found:
288              path_additional.insert(0, edge)
289            else:
290              if g.target(edge) == localStartVertex:
291                #print "found2"
292                found = True
293                path_additional.append(e)
294                path_additional.insert(0, edge)
295        
296        #print "find_new_variations_to_target:", path_additional
297        if path_additional:
298          self.paths.append(path_additional)
299    
300      def _touch_edge(self, e, g, label=''):
301        
302        (u, v) = (g.source(e), g.target(e))
303        
304        # increase current search depth (level)
305        """
306        self.depth += 1
307        
308        # check if maximum depth reached
309        if self.depth == self.maxdepth:
310          # color all succeeding vertices to black (mark as "already visited")
311          # BUG!!! marks too many nodes
312          for child_edge in g.out_edges(v):
313            end_vertex = g.target(child_edge)
314            #self.color_map[end_vertex] = bgl.Color(bgl.Color.gray)
315        """
316        
317        name_map = g.vertex_properties['node_id']
318        
319        if DEBUG:
320          if label:
321            print "%s:\t" % label,
322          #print "edge ",
323          print name_map[u],
324          print " -> ",
325          print name_map[v]
326        
327        #self.state = True
328        
329        if u == self.startVertex:
330          #print "starting"
331          self.current_path = []
332    
333        # skip circular references
334        if v != self.startVertex:
335          self.current_path.append(e)
336    
337        # finish current path if target found
338        if v == self.endVertex and self.current_path:
339          #print "found:"
340          #print self.current_path
341          self.paths.append(self.current_path)
342          self.current_path = []
343    
344    
345  def build_fixed_graph():  def build_fixed_graph():
346      
347    graph = bgl.Graph()    graph = bgl.Graph()
348      index = {}
349    
350      # doesn't this work? see http://www.nabble.com/-Graph--Getting-PageRank-to-work-in-BGL-Python-td14207115.html
351    #graph.add_vertex_property_map(name='my_name', type='float')    #graph.add_vertex_property_map(name='my_name', type='float')
352    
353    # 'write_graphviz' requires property 'node_id' on vertices    # 'write_graphviz' requires property 'node_id' on vertices
# Line 85  def build_fixed_graph(): Line 358  def build_fixed_graph():
358    
359    v1 = graph.add_vertex()    v1 = graph.add_vertex()
360    vmap[v1] = '1'    vmap[v1] = '1'
361      index['1'] = v1
362    
363    v2 = graph.add_vertex()    v2 = graph.add_vertex()
364    vmap[v2] = '2'    vmap[v2] = '2'
365      index['2'] = v2
366    
367    v3 = graph.add_vertex()    v3 = graph.add_vertex()
368    vmap[v3] = '3'    vmap[v3] = '3'
369      index['3'] = v3
370    
371    v4 = graph.add_vertex()    v4 = graph.add_vertex()
372    vmap[v4] = '4'    vmap[v4] = '4'
373      index['4'] = v4
374    
375    e1 = graph.add_edge(v1, v2)    e1 = graph.add_edge(v1, v2)
376    e2 = graph.add_edge(v1, v3)    e2 = graph.add_edge(v1, v3)
377    e3 = graph.add_edge(v3, v4)    e3 = graph.add_edge(v3, v4)
378      
379      e4 = graph.add_edge(v1, v4)
380      e5 = graph.add_edge(v2, v3)
381      e6 = graph.add_edge(v2, v4)
382    
383    """    """
384    for vertex in graph.vertices:    for vertex in graph.vertices:
# Line 111  def build_fixed_graph(): Line 392  def build_fixed_graph():
392    
393    graph.write_graphviz('friends.dot')    graph.write_graphviz('friends.dot')
394        
395    return graph    return (graph, index)
396    
397    
398    def build_random_graph():
399    
400      graph = bgl.Graph()
401      index = {}
402    
403      vmap = graph.vertex_property_map('string')
404      graph.vertex_properties['node_id'] = vmap
405    
406      count = 0
407      for parent_id in range(1, RANDOM_MAX_NODES + 1):
408        count += 1
409        if count % 100 == 0:
410          sys.stderr.write('.')
411          
412        parent_id_str = str(parent_id)
413        v1New = False
414        if not index.has_key(parent_id_str):
415          #print "adding v1:", parent_id_str
416          myVertex1 = graph.add_vertex()
417          vmap[myVertex1] = parent_id_str
418          index[parent_id_str] = myVertex1
419          v1New = True
420    
421      
422      count = 0
423      #for j in range(1, random.randint(1, RANDOM_MAX_CHILDREN_PER_NODE)):
424      for j in range(1, RANDOM_MAX_CHILDREN_PER_NODE):
425    
426        count += 1
427        if count % 100 == 0:
428          sys.stderr.write('.')
429    
430        parent_id_str = random.choice(index.keys())
431        
432        child_id_str = parent_id_str
433        while child_id_str == parent_id_str:
434          child_id_str = random.choice(index.keys())
435          #print child_id_str
436          
437          myVertex1 = index[parent_id_str]
438          myVertex2 = index[child_id_str]
439          
440          graph.add_edge(myVertex1, myVertex2)
441            
442      sys.stderr.write("\n")
443    
444      return (graph, index)
445    
446    
447    def dump_track(graph, track):
448      track_ids = []
449      for node in track:
450        node_id = graph.vertex_properties['node_id'][node]
451        track_ids.append(node_id)
452      
453      print ' -> '.join(track_ids)
454    
455    def dump_edges(g, edges):
456      name_map = g.vertex_properties['node_id']
457      for e in edges:
458        (u, v) = (g.source(e), g.target(e))
459        print "edge ",
460        print name_map[u],
461        print " -> ",
462        print name_map[v]
463    
464    def find_path_solutions(source, target, graph, paths):
465      
466      print
467      print "=" * 42
468      print "find_path_solutions"
469      print "=" * 42
470    
471      #print visitor.paths
472      #(u, v) = (g.source(e), g.target(e))
473      for path in paths:
474        startVertex = graph.source(path[0])
475        
476        track = []
477        track.append(startVertex)
478        
479        for edge in path:
480          endVertex = graph.target(edge)
481          track.append(endVertex)
482          if source == startVertex and target == endVertex:
483            #print "found:", track
484            dump_track(graph, track)
485    
486    def dump_graph(graph):
487      for edge in graph.edges:
488        (u, v) = (graph.source(edge), graph.target(edge))
489        startIndex = graph.vertex_properties['node_id'][u]
490        endIndex = graph.vertex_properties['node_id'][v]
491        print "%s -> %s" % (startIndex, endIndex)
492    
493    def dump_edges_vertices(graph, edge_list):
494      startVertex = graph.source(edge_list[0])
495      
496      track = []
497      track.append(startVertex)
498    
499      for edge in edge_list:
500        endVertex = graph.target(edge)
501        track.append(endVertex)
502      dump_track(graph, track)
503    
504    def print_path_solutions(graph, paths):
505      for path in paths:
506        if DEBUG:
507          print '-' * 21
508          dump_edges(graph, path)
509        dump_edges_vertices(graph, path)
510    
511    
512    
# Line 119  def main(): Line 514  def main():
514        
515    # Load a graph from the GraphViz file 'mst.dot'    # Load a graph from the GraphViz file 'mst.dot'
516    #graph = bgl.Graph.read_graphviz('mst.dot')    #graph = bgl.Graph.read_graphviz('mst.dot')
517    graph = build_fixed_graph()    
518      # 1. fixed graph with fixed required solution
519      (graph, index) = build_fixed_graph()
520      startIndex = '1'
521      endIndex = '4'
522      
523      # 2. random graph with according solution
524      #(graph, index) = build_random_graph()
525      #startIndex = random.choice(index.keys())
526      #endIndex = random.choice(index.keys())
527    
528      print '-' * 42
529      print "complete graph:"
530      dump_graph(graph)
531      print '-' * 42
532    
533    # Compute all paths rooted from each vertex    # Compute all paths rooted from each vertex
534    #mst_edges = bgl.kruskal_minimum_spanning_tree(graph, weight)    #mst_edges = bgl.kruskal_minimum_spanning_tree(graph, weight)
535    #bgl.depth_first_search(graph, root_vertex = None, visitor = None, color_map = None)    #bgl.depth_first_search(graph, root_vertex = None, visitor = None, color_map = None)
536      
537      """
538    for root in graph.vertices:    for root in graph.vertices:
539      print      print
540      print '=' * 42      print '=' * 42
541      print 'Paths originating from node %s' % graph.vertex_properties['node_id'][root]      print 'Paths originating from node %s' % graph.vertex_properties['node_id'][root]
542      visitor = tree_edges_dfs_visitor(graph.vertex_properties['node_id'])      #cmap = graph.vertex_property_map('color')
543        cmap = None
544        visitor = tree_edges_dfs_visitor(3, graph.vertex_properties['node_id'], cmap)
545        #visitor = tree_edges_bfs_visitor(3, graph.vertex_properties['node_id'], cmap)
546      bgl.depth_first_search(graph, root_vertex = root, visitor = visitor, color_map = None)      bgl.depth_first_search(graph, root_vertex = root, visitor = visitor, color_map = None)
547          #bgl.breadth_first_search(graph, root_vertex = root, visitor = visitor, color_map = None)
548        #find_path_solutions(index['1'], index['4'], graph, visitor.paths)
549      #sys.exit(0)
550      """
551    
552      print "Trying to find solution for: %s -> %s" % (startIndex, endIndex)
553    
554      startVertex = index[startIndex]
555      endVertex = index[endIndex]
556    
557      def doCompute():
558        cmap = graph.vertex_property_map('color')
559        visitor = tree_edges_dfs_visitor(startVertex, endVertex, MAX_SEARCH_DEPTH, cmap)
560        bgl.depth_first_search(graph, root_vertex = startVertex, visitor = visitor, color_map = None)
561        #bgl.depth_first_visit(graph, root_vertex = startVertex, visitor = visitor, color_map = cmap)
562        #find_path_solutions(startVertex, endVertex, graph, visitor.paths)
563        print '-' * 42
564        print "solution(s):"
565        print_path_solutions(graph, visitor.paths)
566    
567      if ENABLE_PROFILING:
568        global paths
569        paths = []
570        p = Profile()
571        p.runcall(doCompute)
572        p.print_stats()
573      else:
574        paths = doCompute()
575    
576        
577    # STOP HERE    # STOP HERE
578    sys.exit(0)    sys.exit(0)

Legend:
Removed from v.1.1  
changed lines
  Added in v.1.6

MailToCvsAdmin">MailToCvsAdmin
ViewVC Help
Powered by ViewVC 1.1.26 RSS 2.0 feed