comparison src/graph_helpers.hpp @ 0:add35537fdbb tip

Initial import
author irh <ian.r.hobson@gmail.com>
date Thu, 25 Aug 2011 11:05:55 +0100
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:add35537fdbb
1 // Copyright 2011, Ian Hobson.
2 //
3 // This file is part of gpsynth.
4 //
5 // gpsynth is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // gpsynth is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with gpsynth in the file COPYING.
17 // If not, see http://www.gnu.org/licenses/.
18
19 // Some helper functions for boost.graph
20
21 #pragma once
22
23 #include "boost/graph/adjacency_list.hpp"
24 #include "boost/tuple/tuple.hpp"
25
26 // removes the tree starting at the specified edge from the graph
27 template<typename GRAPH>
28 void RemoveSubTree(typename boost::graph_traits<GRAPH>::edge_descriptor edge,
29 GRAPH& graph) {
30 typename boost::graph_traits<GRAPH>::vertex_descriptor source;
31 typename boost::graph_traits<GRAPH>::vertex_descriptor target;
32 source = boost::source(edge, graph);
33 target = boost::target(edge, graph);
34 // avoid iteration as removing edges invalidates iterators
35 while (boost::in_degree(source, graph) > 0) {
36 RemoveSubTree(*(boost::in_edges(source, graph).first), graph);
37 }
38 boost::remove_edge(source, target, graph);
39 boost::remove_vertex(source, graph);
40 }
41
42 // removes the tree starting at the specified vertex from the graph
43 template<typename T>
44 void RemoveSubTree(typename boost::graph_traits<T>::vertex_descriptor vertex,
45 T& graph) {
46 // avoid iteration as removing edges invalidates iterators
47 while (boost::in_degree(vertex, graph) > 0) {
48 RemoveSubTree(*(boost::in_edges(vertex, graph).first), graph);
49 }
50 boost::remove_vertex(vertex, graph);
51 }
52
53 // inserts the subtree identified by source in to target_graph
54 // returns the root vertex of the inserted subtree
55 template<typename GRAPH>
56 typename boost::graph_traits<GRAPH>::vertex_descriptor
57 InsertSubTree(typename boost::graph_traits<GRAPH>::vertex_descriptor source,
58 const GRAPH& source_graph,
59 GRAPH& target_graph) {
60 typedef typename boost::graph_traits<GRAPH>::vertex_descriptor Vertex;
61 typedef typename boost::graph_traits<GRAPH>::in_edge_iterator InEdge;
62 Vertex new_vertex = boost::add_vertex(source_graph[source], target_graph);
63 InEdge in_edge;
64 InEdge in_edges_end;
65 boost::tie(in_edge, in_edges_end) = boost::in_edges(source, source_graph);
66 while (in_edge != in_edges_end) {
67 Vertex input = InsertSubTree(boost::source(*in_edge, source_graph),
68 source_graph,
69 target_graph);
70 boost::add_edge(input, new_vertex, source_graph[*in_edge], target_graph);
71 ++in_edge;
72 }
73 return new_vertex;
74 }
75
76 // SwapSubTrees - swaps the subtrees starting at node_1 and node_2
77 // writing to graphs passed in as targets
78 template<typename GRAPH>
79 void SwapSubTrees(typename boost::graph_traits<GRAPH>::vertex_descriptor node_1,
80 typename boost::graph_traits<GRAPH>::vertex_descriptor node_2,
81 const GRAPH& source_1, const GRAPH& source_2,
82 GRAPH& target_1, GRAPH& target_2) {
83
84 typedef typename boost::graph_traits<GRAPH>::vertex_descriptor Vertex;
85 typedef typename boost::graph_traits<GRAPH>::edge_descriptor Edge;
86 // copy sources to targets
87 target_1 = source_1;
88 target_2 = source_2;
89 // get connecting output edges
90 Edge edge_1 = *(boost::out_edges(node_1, source_1).first);
91 Edge edge_2 = *(boost::out_edges(node_2, source_2).first);
92 // get connecting nodes on other end of outputs
93 Vertex target_node_1 = boost::target(edge_1, source_1);
94 Vertex target_node_2 = boost::target(edge_2, source_2);
95 // delete subtrees
96 RemoveSubTree(edge_1, target_1);
97 RemoveSubTree(edge_2, target_2);
98 // insert copies of subtrees in opposing target graphs
99 Vertex new_node_1 = InsertSubTree(node_2, source_2, target_1);
100 Vertex new_node_2 = InsertSubTree(node_1, source_1, target_2);
101 // connect the new subtrees using the same edge properties as old connection
102 boost::add_edge(new_node_1, target_node_1, source_1[edge_1], target_1);
103 boost::add_edge(new_node_2, target_node_2, source_2[edge_2], target_2);
104 }