Planet
navi homePPSaboutscreenshotsdownloaddevelopmentforum

source: downloads/boost_1_33_1/libs/graph/example/file_dependencies.cpp @ 12

Last change on this file since 12 was 12, checked in by landauf, 17 years ago

added boost

File size: 6.5 KB
Line 
1//=======================================================================
2// Copyright 1997, 1998, 1999, 2000 University of Notre Dame.
3// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek
4//
5// Distributed under the Boost Software License, Version 1.0. (See
6// accompanying file LICENSE_1_0.txt or copy at
7// http://www.boost.org/LICENSE_1_0.txt)
8//=======================================================================
9/*
10
11  Paul Moore's request:
12
13  As an example of a practical problem which is not restricted to graph
14  "experts", consider file dependencies. It's basically graph construction,
15  plus topological sort, but it might make a nice "tutorial" example. Build a
16  dependency graph of files, then use the algorithms to do things like
17 
18  1. Produce a full recompilation order (topological sort, by modified date)
19  2. Produce a "parallel" recompilation order (same as above, but group files
20  which can be built in parallel)
21  3. Change analysis (if I change file x, which others need recompiling)
22  4. Dependency changes (if I add a dependency between file x and file y, what
23  are the effects)
24 
25*/
26
27#include <boost/config.hpp> // put this first to suppress some VC++ warnings
28
29#include <iostream>
30#include <iterator>
31#include <algorithm>
32#include <time.h>
33
34#include <boost/utility.hpp>
35#include <boost/graph/adjacency_list.hpp>
36#include <boost/graph/topological_sort.hpp>
37#include <boost/graph/depth_first_search.hpp>
38#include <boost/graph/dijkstra_shortest_paths.hpp>
39#include <boost/graph/visitors.hpp>
40
41using namespace std;
42using namespace boost;
43
44enum files_e { dax_h, yow_h, boz_h, zow_h, foo_cpp, 
45               foo_o, bar_cpp, bar_o, libfoobar_a,
46               zig_cpp, zig_o, zag_cpp, zag_o, 
47                 libzigzag_a, killerapp, N };
48const char* name[] = { "dax.h", "yow.h", "boz.h", "zow.h", "foo.cpp",
49                       "foo.o", "bar.cpp", "bar.o", "libfoobar.a",
50                       "zig.cpp", "zig.o", "zag.cpp", "zag.o",
51                       "libzigzag.a", "killerapp" };
52
53
54struct print_visitor : public bfs_visitor<> {
55  template <class Vertex, class Graph>
56  void discover_vertex(Vertex v, Graph&) {
57    cout << name[v] << " ";
58  }
59};
60
61
62struct cycle_detector : public dfs_visitor<>
63{
64  cycle_detector(bool& has_cycle) 
65    : m_has_cycle(has_cycle) { }
66
67  template <class Edge, class Graph>
68  void back_edge(Edge, Graph&) { m_has_cycle = true; }
69protected:
70  bool& m_has_cycle;
71};
72
73
74
75
76int main(int,char*[])
77{
78   
79  typedef pair<int,int> Edge;
80  Edge used_by[] = {
81    Edge(dax_h, foo_cpp), Edge(dax_h, bar_cpp), Edge(dax_h, yow_h),
82    Edge(yow_h, bar_cpp), Edge(yow_h, zag_cpp),
83    Edge(boz_h, bar_cpp), Edge(boz_h, zig_cpp), Edge(boz_h, zag_cpp),
84    Edge(zow_h, foo_cpp), 
85    Edge(foo_cpp, foo_o),
86    Edge(foo_o, libfoobar_a),
87    Edge(bar_cpp, bar_o),
88    Edge(bar_o, libfoobar_a),
89    Edge(libfoobar_a, libzigzag_a),
90    Edge(zig_cpp, zig_o),
91    Edge(zig_o, libzigzag_a),
92    Edge(zag_cpp, zag_o),
93    Edge(zag_o, libzigzag_a),
94    Edge(libzigzag_a, killerapp)
95  };
96  const std::size_t nedges = sizeof(used_by)/sizeof(Edge);
97  int weights[nedges];
98  std::fill(weights, weights + nedges, 1);
99
100  typedef adjacency_list<vecS, vecS, directedS, 
101      property<vertex_color_t, default_color_type>,
102      property<edge_weight_t, int>
103    > Graph;
104#if defined(BOOST_MSVC) && BOOST_MSVC <= 1300
105  // VC++ can't handle the iterator constructor
106  Graph g(N);
107  property_map<Graph, edge_weight_t>::type weightmap = get(edge_weight, g);
108  for (std::size_t j = 0; j < nedges; ++j) {
109    graph_traits<Graph>::edge_descriptor e; bool inserted;
110    tie(e, inserted) = add_edge(used_by[j].first, used_by[j].second, g);
111    weightmap[e] = weights[j];
112  }
113#else
114  Graph g(used_by, used_by + nedges, weights, N);
115#endif
116  typedef graph_traits<Graph>::vertex_descriptor Vertex;
117
118  // Determine ordering for a full recompilation
119  {
120    typedef list<Vertex> MakeOrder;
121    MakeOrder make_order;
122    topological_sort(g, std::front_inserter(make_order));
123   
124    cout << "make ordering: ";
125    for (MakeOrder::iterator i = make_order.begin();
126         i != make_order.end(); ++i)
127      cout << name[*i] << " ";
128    cout << endl;
129  }
130  cout << endl;
131
132  // Recompilation order with files that can be compiled in parallel
133  // grouped together
134  {
135    // Set up the necessary graph properties.
136    vector<int> time(N);
137    typedef vector<int>::iterator Time;
138    property_map<Graph, edge_weight_t>::type weight = get(edge_weight, g);
139
140    // Calculate the in_degree for each vertex.
141    vector<int> in_degree(N, 0);
142    graph_traits<Graph>::vertex_iterator i, iend;
143    graph_traits<Graph>::out_edge_iterator j, jend;
144    for (tie(i, iend) = vertices(g); i != iend; ++i)
145      for (tie(j, jend) = out_edges(*i,g); j != jend; ++j)
146        in_degree[target(*j,g)] += 1;
147
148    std::greater<int> compare;
149    closed_plus<int> combine;
150
151    // Run best-first-search from each vertex with zero in-degree.
152    for (tie(i, iend) = vertices(g); i != iend; ++i) {
153      if (in_degree[*i] == 0) {
154        std::vector<graph_traits<Graph>::vertex_descriptor> 
155          pred(num_vertices(g));
156        property_map<Graph, vertex_index_t>::type
157          indexmap = get(vertex_index, g);
158        dijkstra_shortest_paths_no_init
159          (g, *i, &pred[0], &time[0], weight, indexmap, 
160           compare, combine, 0,  // Since we are using > instead of >, we
161           (std::numeric_limits<int>::max)(), // flip 0 and inf.
162           default_dijkstra_visitor());
163      }
164    }
165
166    cout << "parallel make ordering, " << endl
167         << "vertices with same group number can be made in parallel" << endl;
168    for (tie(i,iend) = vertices(g); i != iend; ++i)
169      cout << "time_slot[" << name[*i] << "] = " << time[*i] << endl;
170  }
171  cout << endl;
172
173  // if I change yow.h what files need to be re-made?
174  {
175    cout << "A change to yow.h will cause what to be re-made?" << endl;
176    print_visitor vis;
177    breadth_first_search(g, vertex(yow_h, g), visitor(vis));
178    cout << endl;
179  }
180  cout << endl;
181
182  // are there any cycles in the graph?
183  {
184    bool has_cycle = false;
185    cycle_detector vis(has_cycle);
186    depth_first_search(g, visitor(vis));
187    cout << "The graph has a cycle? " << has_cycle << endl;
188  }
189  cout << endl;
190
191  // add a dependency going from bar.cpp to dax.h
192  {
193    cout << "adding edge bar_cpp -> dax_h" << endl;
194    add_edge(bar_cpp, dax_h, g);
195  }
196  cout << endl;
197
198  // are there any cycles in the graph?
199  {
200    bool has_cycle = false;
201    cycle_detector vis(has_cycle);
202    depth_first_search(g, visitor(vis));
203    cout << "The graph has a cycle now? " << has_cycle << endl;
204  }
205
206  return 0;
207}
Note: See TracBrowser for help on using the repository browser.