Mercurial > hg > gpsynth
view 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 |
line wrap: on
line source
// Copyright 2011, Ian Hobson. // // This file is part of gpsynth. // // gpsynth is free software: you can redistribute it and/or modify // it under the terms of the GNU General Public License as published by // the Free Software Foundation, either version 3 of the License, or // (at your option) any later version. // // gpsynth is distributed in the hope that it will be useful, // but WITHOUT ANY WARRANTY; without even the implied warranty of // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the // GNU General Public License for more details. // // You should have received a copy of the GNU General Public License // along with gpsynth in the file COPYING. // If not, see http://www.gnu.org/licenses/. // Some helper functions for boost.graph #pragma once #include "boost/graph/adjacency_list.hpp" #include "boost/tuple/tuple.hpp" // removes the tree starting at the specified edge from the graph template<typename GRAPH> void RemoveSubTree(typename boost::graph_traits<GRAPH>::edge_descriptor edge, GRAPH& graph) { typename boost::graph_traits<GRAPH>::vertex_descriptor source; typename boost::graph_traits<GRAPH>::vertex_descriptor target; source = boost::source(edge, graph); target = boost::target(edge, graph); // avoid iteration as removing edges invalidates iterators while (boost::in_degree(source, graph) > 0) { RemoveSubTree(*(boost::in_edges(source, graph).first), graph); } boost::remove_edge(source, target, graph); boost::remove_vertex(source, graph); } // removes the tree starting at the specified vertex from the graph template<typename T> void RemoveSubTree(typename boost::graph_traits<T>::vertex_descriptor vertex, T& graph) { // avoid iteration as removing edges invalidates iterators while (boost::in_degree(vertex, graph) > 0) { RemoveSubTree(*(boost::in_edges(vertex, graph).first), graph); } boost::remove_vertex(vertex, graph); } // inserts the subtree identified by source in to target_graph // returns the root vertex of the inserted subtree template<typename GRAPH> typename boost::graph_traits<GRAPH>::vertex_descriptor InsertSubTree(typename boost::graph_traits<GRAPH>::vertex_descriptor source, const GRAPH& source_graph, GRAPH& target_graph) { typedef typename boost::graph_traits<GRAPH>::vertex_descriptor Vertex; typedef typename boost::graph_traits<GRAPH>::in_edge_iterator InEdge; Vertex new_vertex = boost::add_vertex(source_graph[source], target_graph); InEdge in_edge; InEdge in_edges_end; boost::tie(in_edge, in_edges_end) = boost::in_edges(source, source_graph); while (in_edge != in_edges_end) { Vertex input = InsertSubTree(boost::source(*in_edge, source_graph), source_graph, target_graph); boost::add_edge(input, new_vertex, source_graph[*in_edge], target_graph); ++in_edge; } return new_vertex; } // SwapSubTrees - swaps the subtrees starting at node_1 and node_2 // writing to graphs passed in as targets template<typename GRAPH> void SwapSubTrees(typename boost::graph_traits<GRAPH>::vertex_descriptor node_1, typename boost::graph_traits<GRAPH>::vertex_descriptor node_2, const GRAPH& source_1, const GRAPH& source_2, GRAPH& target_1, GRAPH& target_2) { typedef typename boost::graph_traits<GRAPH>::vertex_descriptor Vertex; typedef typename boost::graph_traits<GRAPH>::edge_descriptor Edge; // copy sources to targets target_1 = source_1; target_2 = source_2; // get connecting output edges Edge edge_1 = *(boost::out_edges(node_1, source_1).first); Edge edge_2 = *(boost::out_edges(node_2, source_2).first); // get connecting nodes on other end of outputs Vertex target_node_1 = boost::target(edge_1, source_1); Vertex target_node_2 = boost::target(edge_2, source_2); // delete subtrees RemoveSubTree(edge_1, target_1); RemoveSubTree(edge_2, target_2); // insert copies of subtrees in opposing target graphs Vertex new_node_1 = InsertSubTree(node_2, source_2, target_1); Vertex new_node_2 = InsertSubTree(node_1, source_1, target_2); // connect the new subtrees using the same edge properties as old connection boost::add_edge(new_node_1, target_node_1, source_1[edge_1], target_1); boost::add_edge(new_node_2, target_node_2, source_2[edge_2], target_2); }