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