diff options
author | maxim-yurchuk <maxim-yurchuk@yandex-team.com> | 2024-10-09 12:29:46 +0300 |
---|---|---|
committer | maxim-yurchuk <maxim-yurchuk@yandex-team.com> | 2024-10-09 13:14:22 +0300 |
commit | 9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80 (patch) | |
tree | a8fb3181d5947c0d78cf402aa56e686130179049 /contrib/restricted/boost/graph | |
parent | a44b779cd359f06c3ebbef4ec98c6b38609d9d85 (diff) | |
download | ydb-9731d8a4bb7ee2cc8554eaf133bb85498a4c7d80.tar.gz |
publishFullContrib: true for ydb
<HIDDEN_URL>
commit_hash:c82a80ac4594723cebf2c7387dec9c60217f603e
Diffstat (limited to 'contrib/restricted/boost/graph')
141 files changed, 47116 insertions, 0 deletions
diff --git a/contrib/restricted/boost/graph/.yandex_meta/devtools.copyrights.report b/contrib/restricted/boost/graph/.yandex_meta/devtools.copyrights.report new file mode 100644 index 0000000000..02724c3c19 --- /dev/null +++ b/contrib/restricted/boost/graph/.yandex_meta/devtools.copyrights.report @@ -0,0 +1,1144 @@ +# File format ($ symbol means the beginning of a line): +# +# $ # this message +# $ # ======================= +# $ # comments (all commentaries should starts with some number of spaces and # symbol) +# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits +# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files +# $ # user comments +# $ +# ${action} {license id} {license text hash} +# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make +# ${all_file_action} filename +# $ # user commentaries (many lines) +# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify) +# ${action} {license spdx} {license text hash} +# $BELONGS ./ya/make/file/relative/path/3/ya.make +# ${all_file_action} filename +# $ # user commentaries +# $ generated description +# $ ... +# +# You can modify action, all_file_action and add commentaries +# Available actions: +# keep - keep license in contrib and use in credits +# skip - skip license +# remove - remove all files with this license +# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file +# +# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory) +# We suppose that that files can contain some license info +# Available all file actions: +# FILE_IGNORE - ignore file (do nothing) +# FILE_INCLUDE - include all file data into licenses text file +# ======================= + +KEEP COPYRIGHT_SERVICE_LABEL 00d8c23eb547d50de392cb17b51e426e +BELONGS ya.make + License text: + // Copyright 2002 Indiana University. + // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/adjacency_iterator.hpp [2:3] + include/boost/graph/create_condensation_graph.hpp [2:3] + include/boost/graph/dag_shortest_paths.hpp [2:3] + include/boost/graph/detail/incremental_components.hpp [2:4] + include/boost/graph/detail/list_base.hpp [2:3] + include/boost/graph/exception.hpp [2:3] + include/boost/graph/graph_archetypes.hpp [2:3] + include/boost/graph/graph_selectors.hpp [2:3] + include/boost/graph/iteration_macros_undef.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL 01ee5bf19060374ef2efda82af9fc108 +BELONGS ya.make + License text: + // Copyright Michael Drexl 2005, 2006. + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/r_c_shortest_paths.hpp [3:5] + +KEEP COPYRIGHT_SERVICE_LABEL 0248c07689d63f8e0b5cff0f09a2737a +BELONGS ya.make + License text: + // Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) + // Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark + // (jlandersen@imada.sdu.dk) + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/vf2_sub_graph_iso.hpp [2:4] + +KEEP COPYRIGHT_SERVICE_LABEL 09990d303a67b1a0c87b3ccf09c2097c +BELONGS ya.make + License text: + // Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de> + // Copyright (C) 2004,2009 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + src/graphml.cpp [1:2] + +KEEP COPYRIGHT_SERVICE_LABEL 0a1ddf2f633492698f29966f2ba00d47 +BELONGS ya.make + License text: + // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. + // Copyright (C) Vladimir Prus 2003 + // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/random.hpp [2:4] + +KEEP COPYRIGHT_SERVICE_LABEL 0b29116922cfef70c51094e6d835a79b +BELONGS ya.make + License text: + // (C) Copyright Francois Faure, iMAGIS-GRAVIR / UJF, 2001. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/property_iter_range.hpp [2:2] + +KEEP COPYRIGHT_SERVICE_LABEL 1503802c606bb498fc119fbf3329ccce +BELONGS ya.make + License text: + // Copyright (c) Jeremy Siek 2001 + // Copyright (c) Douglas Gregor 2004 + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/biconnected_components.hpp [1:2] + +KEEP COPYRIGHT_SERVICE_LABEL 1638af8b9d8a13b7d2e95217a0492d14 +BELONGS ya.make + License text: + // (C) Copyright Andrew Sutton 2007 + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/geodesic_distance.hpp [1:1] + include/boost/graph/property_maps/null_property_map.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 1a243be6fc839e64391e9bd0d3aea29a +BELONGS ya.make + License text: + // (c) Copyright Juergen Hunold 2008 + // Use, modification and distribution is subject to the Boost Software + // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/edmunds_karp_max_flow.hpp [2:4] + +KEEP COPYRIGHT_SERVICE_LABEL 1b49b31378926fed6bad2e9e34790202 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/pending/container_traits.hpp [1:5] + include/boost/pending/detail/disjoint_sets.hpp [1:3] + include/boost/pending/detail/property.hpp [1:3] + include/boost/pending/fibonacci_heap.hpp [1:3] + include/boost/pending/property.hpp [1:3] + include/boost/pending/queue.hpp [1:3] + include/boost/pending/stringtok.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL 1bf87741a9385d7452ade49e1b079010 +BELONGS ya.make + License text: + // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. + // Copyright 2010 Thomas Claveirole + // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/adjacency_list.hpp [2:4] + include/boost/graph/bellman_ford_shortest_paths.hpp [3:4] + include/boost/graph/breadth_first_search.hpp [3:4] + include/boost/graph/cuthill_mckee_ordering.hpp [2:5] + include/boost/graph/depth_first_search.hpp [2:4] + include/boost/graph/detail/adj_list_edge_iterator.hpp [3:4] + include/boost/graph/detail/adjacency_list.hpp [3:5] + include/boost/graph/detail/array_binary_tree.hpp [3:4] + include/boost/graph/detail/connected_components.hpp [2:3] + include/boost/graph/detail/edge.hpp [3:4] + include/boost/graph/detail/incidence_iterator.hpp [3:4] + include/boost/graph/detail/self_avoiding_walk.hpp [2:3] + include/boost/graph/detail/sparse_ordering.hpp [2:5] + include/boost/graph/dijkstra_shortest_paths.hpp [2:3] + include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp [2:4] + include/boost/graph/edge_list.hpp [2:3] + include/boost/graph/filtered_graph.hpp [2:3] + include/boost/graph/graph_as_tree.hpp [3:4] + include/boost/graph/graph_concepts.hpp [3:4] + include/boost/graph/graph_traits.hpp [2:3] + include/boost/graph/graph_utility.hpp [3:4] + include/boost/graph/johnson_all_pairs_shortest.hpp [2:3] + include/boost/graph/king_ordering.hpp [2:5] + include/boost/graph/kruskal_min_spanning_tree.hpp [3:4] + include/boost/graph/leda_graph.hpp [2:6] + include/boost/graph/matrix_as_graph.hpp [3:4] + include/boost/graph/named_function_params.hpp [2:3] + include/boost/graph/neighbor_bfs.hpp [3:4] + include/boost/graph/prim_minimum_spanning_tree.hpp [2:3] + include/boost/graph/properties.hpp [2:3] + include/boost/graph/random.hpp [2:4] + include/boost/graph/read_dimacs.hpp [2:3] + include/boost/graph/relax.hpp [2:3] + include/boost/graph/sequential_vertex_coloring.hpp [2:4] + include/boost/graph/smallest_last_ordering.hpp [2:3] + include/boost/graph/strong_components.hpp [3:4] + include/boost/graph/topological_sort.hpp [3:4] + include/boost/graph/transpose_graph.hpp [3:4] + include/boost/graph/undirected_dfs.hpp [3:4] + include/boost/graph/vector_as_graph.hpp [2:5] + include/boost/graph/visitors.hpp [2:3] + include/boost/pending/bucket_sorter.hpp [3:4] + include/boost/pending/disjoint_sets.hpp [3:4] + include/boost/pending/indirect_cmp.hpp [3:4] + include/boost/pending/is_heap.hpp [3:4] + include/boost/pending/mutable_heap.hpp [3:4] + include/boost/pending/mutable_queue.hpp [3:4] + +KEEP COPYRIGHT_SERVICE_LABEL 1e6c23354a6747a6c3eef56fb2537b44 +BELONGS ya.make + License text: + // Copyright (c) 2006, Stephan Diederich + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/boykov_kolmogorov_max_flow.hpp [1:1] + include/boost/graph/write_dimacs.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 22403f1361a990fb6fd5cc8b876e046d +BELONGS ya.make + License text: + // Copyright (c) 2004 Kristopher Beevers + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/astar_search.hpp [5:5] + +KEEP COPYRIGHT_SERVICE_LABEL 22b8921218f5846e7fc7d4a2ac8c34c0 +BELONGS ya.make + License text: + // Copyright 2004-2006 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/plod_generator.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 26ec38d4689211b14e2c5b53e9a78f76 +BELONGS ya.make + License text: + // Copyright 2009 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/histogram_sort.hpp [1:1] + include/boost/graph/topology.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 29b0154b5b9497e05eafdea58aee1ec9 +BELONGS ya.make + License text: + // Copyright 2000 University of Notre Dame. + // Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/edge_connectivity.hpp [2:3] + include/boost/graph/edmonds_karp_max_flow.hpp [2:3] + include/boost/graph/push_relabel_max_flow.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL 2e933bb084c95d7e3472974501e28c75 +BELONGS ya.make + License text: + // Copyright (c) Jeremy Siek 2001, Marc Wintermantel 2002 + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/bandwidth.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 351746b3263b8ecde03d30e68809a8c2 +BELONGS ya.make + License text: + // Copyright 2005 Trustees of Indiana University + // Authors: Andrew Lumsdaine, Douglas Gregor + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/simple_point.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL 35f3967788124fb1166bf637d6cd211a +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/transitive_closure.hpp [1:4] + +KEEP COPYRIGHT_SERVICE_LABEL 368bc0676fed97d8e20cb5e9e1a4530f +BELONGS ya.make + License text: + // Copyright (C) 2009 Andrew Sutton + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/labeled_graph_traits.hpp [1:1] + include/boost/graph/graph_mutability_traits.hpp [1:1] + include/boost/graph/labeled_graph.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 3761f0e38b5da4769378918141293e40 +BELONGS ya.make + License text: + // Copyright 2002 Rensselaer Polytechnic Institute + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/floyd_warshall_shortest.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 3e8210b2d067c6fa6eca9745ccdb03df +BELONGS ya.make + License text: + // Copyright 2008 + // Author: Matyas W Egyhazy + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/metric_tsp_approx.hpp [3:4] + +KEEP COPYRIGHT_SERVICE_LABEL 471d4b0a42c396158389600e3135b118 +BELONGS ya.make + License text: + // Copyright 2001 University of Notre Dame. + // Copyright 2003 Jeremy Siek + // Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/dll_import_export.hpp [2:4] + include/boost/graph/graphviz.hpp [2:4] + +KEEP COPYRIGHT_SERVICE_LABEL 483fdf5158d0f8518198f5ac2c492f5f +BELONGS ya.make + License text: + // (C) Copyright Jeremy Siek 2001. + // Distributed under the Boost Software License, Version 1.0. (See accompany- + // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/detail/algorithm.hpp [1:3] + include/boost/graph/detail/permutation.hpp [1:3] + include/boost/graph/detail/set_adaptor.hpp [1:3] + include/boost/graph/detail/shadow_iterator.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL 4a4c85d50d7786e732eb8f9d7ce88a13 +BELONGS ya.make + License text: + // (C) Copyright 2007 Andrew Sutton + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/geodesic.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 4c7e1f597f1997587410c32f9a6d6fdb +BELONGS ya.make + License text: + // Copyright (c) 2005 Aaron Windsor + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/max_cardinality_matching.hpp [2:2] + +KEEP COPYRIGHT_SERVICE_LABEL 4cf14bcc6afe3ad08dfd547e89ac0920 +BELONGS ya.make + License text: + // Copyright 2010 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/loop_erased_random_walk.hpp [1:1] + include/boost/graph/random_spanning_tree.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 4d26b7ae91cf6f8491cee13434ff5797 +BELONGS ya.make + License text: + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/detail/algorithm.hpp [19:20] + +KEEP COPYRIGHT_SERVICE_LABEL 572b131daaeb41ada07b46e9bcc351e8 +BELONGS ya.make + License text: + // Copyright (C) 2005-2010 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/one_bit_color_map.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 586afb33401cfbc0d9c28c9f0b024801 +BELONGS ya.make + License text: + // Copyright 2005 Jeremy G. Siek + // Authors: Jeremy G. Siek + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/adj_list_serialize.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL 5bb192a3ec0466664f95da7b439ee5e7 +BELONGS ya.make + License text: + // Copyright 2012 Fernando Vilas + // 2010 Daniel Trebbien + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/maximum_adjacency_search.hpp [3:4] + +KEEP COPYRIGHT_SERVICE_LABEL 670e9fea8b553fd6cefa4f9a295c8a0a +BELONGS ya.make + License text: + // Copyright 2012 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/is_distributed_selector.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 686307e753ad6e1d636dbc622eedb324 +BELONGS ya.make + License text: + // Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de> + // Copyright (C) 2004 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/graphml.hpp [1:2] + +KEEP COPYRIGHT_SERVICE_LABEL 69913f770ab644c0c626ffe368b41c06 +BELONGS ya.make + License text: + // (C) Copyright Jeremiah Willcock 2004 + // Distributed under the Boost Software License, Version 1.0. (See + // accompanying file LICENSE_1_0.txt or copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/pending/fenced_priority_queue.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL 6b1ab40ae46ff90ccb7c47e8c55973bc +BELONGS ya.make + License text: + // Copyright Daniel Trebbien 2010. + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or the copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/buffer_concepts.hpp [1:3] + include/boost/graph/stoer_wagner_min_cut.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL 6faaf754e301184e7a07944b24799553 +BELONGS ya.make + License text: + // Copyright 2004 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/bc_clustering.hpp [1:1] + include/boost/graph/betweenness_centrality.hpp [1:1] + include/boost/graph/circle_layout.hpp [1:1] + include/boost/graph/gursoy_atun_layout.hpp [1:1] + include/boost/graph/kamada_kawai_spring_layout.hpp [1:1] + include/boost/graph/leda_graph.hpp [2:6] + include/boost/graph/overloading.hpp [1:1] + include/boost/graph/random_layout.hpp [1:1] + include/boost/graph/sequential_vertex_coloring.hpp [2:4] + include/boost/graph/small_world_generator.hpp [1:1] + include/boost/graph/vertex_and_edge_range.hpp [1:1] + include/boost/pending/relaxed_heap.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 7154f956948b41d87bf8a2b73a07d675 +BELONGS ya.make + License text: + // (C) Copyright Jeremy Siek 1999. + // Distributed under the Boost Software License, Version 1.0. (See + // accompanying file LICENSE_1_0.txt or copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/tree_traits.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL 740b8b21c73d73ca167354e62df16207 +BELONGS ya.make + License text: + * Copyright (c) 2010 Matthias Walter (xammy@xammy.homelinux.net) + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/bipartite.hpp [3:3] + +KEEP COPYRIGHT_SERVICE_LABEL 779f3f74aa28c6ec9cbf99f210980137 +BELONGS ya.make + License text: + // Copyright 2007 Stanford University + // Authors: David Gleich + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/core_numbers.hpp [3:4] + +KEEP COPYRIGHT_SERVICE_LABEL 7da1e963669f385bf3784df6bc8f2553 +BELONGS ya.make + License text: + // Copyright (C) 2005-2006 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/two_bit_color_map.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 807dea3c55c068fbbaf4810187c7c84b +BELONGS ya.make + License text: + // (C) Copyright 2007-2009 Andrew Sutton + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/bron_kerbosch_all_cliques.hpp [1:1] + include/boost/graph/closeness_centrality.hpp [1:1] + include/boost/graph/clustering_coefficient.hpp [1:1] + include/boost/graph/degree_centrality.hpp [1:1] + include/boost/graph/detail/index.hpp [1:1] + include/boost/graph/directed_graph.hpp [1:1] + include/boost/graph/eccentricity.hpp [1:1] + include/boost/graph/exterior_property.hpp [1:1] + include/boost/graph/numeric_values.hpp [1:1] + include/boost/graph/property_maps/constant_property_map.hpp [1:1] + include/boost/graph/property_maps/container_property_map.hpp [1:1] + include/boost/graph/property_maps/matrix_property_map.hpp [1:1] + include/boost/graph/tiernan_all_cycles.hpp [1:1] + include/boost/graph/undirected_graph.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 89b41c99892d77117372460a7f90d72f +BELONGS ya.make + License text: + // Copyright 2004-5 The Trustees of Indiana University. + // Copyright 2002 Brad King and Douglas Gregor + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/page_rank.hpp [1:2] + +KEEP COPYRIGHT_SERVICE_LABEL 8aaadc898368c37b5d90c024f9104351 +BELONGS ya.make + License text: + // Copyright (C) 2012, Michele Caini. + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/two_graphs_common_spanning_trees.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL 9207c14a0f73cfde357a50e86305b641 +BELONGS ya.make + License text: + // Copyright 2004-9 Trustees of Indiana University + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/read_graphviz_new.hpp [1:1] + include/boost/graph/detail/read_graphviz_spirit.hpp [1:1] + src/read_graphviz_new.cpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL 96b2ef2696a6c6919d3372f54d0dcce4 +BELONGS ya.make + License text: + // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. + // Copyright 2009 Trustees of Indiana University. + // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/d_ary_heap.hpp [3:4] + include/boost/graph/detail/incremental_components.hpp [2:4] + include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp [2:4] + include/boost/graph/grid_graph.hpp [2:3] + include/boost/graph/incremental_components.hpp [3:5] + include/boost/graph/lookup_edge.hpp [2:3] + include/boost/graph/mcgregor_common_subgraphs.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL 98be8460f5eeedee67d327e5aa099ae2 +BELONGS ya.make + License text: + // Copyright 2004-5 The Trustees of Indiana University. + // Copyright 2002 Brad King and Douglas Gregor + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/page_rank.hpp [1:2] + +KEEP COPYRIGHT_SERVICE_LABEL 9cf9d5ea6d40a88eeda2127bd41fc81a +BELONGS ya.make + License text: + // Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) + // Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark + // (jlandersen@imada.sdu.dk) + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/vf2_sub_graph_iso.hpp [2:4] + +KEEP COPYRIGHT_SERVICE_LABEL 9d08918c66a0d366cbbae02999f8438d +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/transitive_closure.hpp [1:4] + include/boost/graph/vector_as_graph.hpp [2:5] + +KEEP COPYRIGHT_SERVICE_LABEL a717e4b7c213ca28bbeaec4750bb98ec +BELONGS ya.make + License text: + // Copyright 2004, 2005 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/erdos_renyi_generator.hpp [1:1] + include/boost/graph/fruchterman_reingold.hpp [1:1] + include/boost/graph/mesh_graph_generator.hpp [1:1] + include/boost/graph/point_traits.hpp [1:1] + include/boost/graph/rmat_graph_generator.hpp [1:1] + include/boost/graph/ssca_graph_generator.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL a7831931571cb11df5942e281a68009f +BELONGS ya.make + License text: + * Copyright (c) 1994 + * Hewlett-Packard Company + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/detail/algorithm.hpp [7:8] + +KEEP COPYRIGHT_SERVICE_LABEL a9d5074bdc20d985f64135ae02f955a0 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/pending/container_traits.hpp [1:5] + +KEEP COPYRIGHT_SERVICE_LABEL ab71254ad02f316b826c74cda23fc7de +BELONGS ya.make + License text: + // Copyright 2001 Universite Joseph Fourier, Grenoble. + // Author: Francois Faure + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/adjacency_list_io.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL ac019423baf07909ddd9038922e85359 +BELONGS ya.make + License text: + // Copyright 2005 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/indexed_properties.hpp [1:1] + include/boost/graph/dimacs.hpp [1:1] + include/boost/graph/graph_stats.hpp [1:1] + include/boost/graph/metis.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL b1820d2cd3cc81402964cf6c2c64f349 +BELONGS ya.make + License text: + // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. + // Copyright 2010 Thomas Claveirole + // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/adjacency_list.hpp [2:4] + include/boost/graph/detail/adjacency_list.hpp [3:5] + +KEEP COPYRIGHT_SERVICE_LABEL b608aafcf17c3fbc3a9abfa54ff163ce +BELONGS ya.make + License text: + // Copyright (C) 2007 Douglas Gregor + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/named_graph.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL ba5506df7530081f1cb89a1a0c3dde35 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/vector_as_graph.hpp [2:5] + +KEEP COPYRIGHT_SERVICE_LABEL baf28d14712b3b53f3b722d4d80fdb6c +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/pending/container_traits.hpp [1:5] + +KEEP COPYRIGHT_SERVICE_LABEL bd84a09c4319b7c30ed8c9bc63531fff +BELONGS ya.make + License text: + // Copyright (c) 2018 Yi Ji + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/maximum_weighted_matching.hpp [2:2] + +KEEP COPYRIGHT_SERVICE_LABEL bda792b52a7a784797c1280c82f443a0 +BELONGS ya.make + License text: + // (C) Copyright David Abrahams 2000. + // Distributed under the Boost Software License, Version 1.0. (See + // accompanying file LICENSE_1_0.txt or copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/reverse_graph.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL c02bfefa74f87417f2dbc10a0395ffac +BELONGS ya.make + License text: + // Copyright 2018 Peter Dimov + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/detail/empty_header.hpp [4:4] + include/boost/graph/detail/mpi_include.hpp [4:4] + +KEEP COPYRIGHT_SERVICE_LABEL c3a440d06912f47e5190235167d26eea +BELONGS ya.make + License text: + // Copyright 2001 University of Notre Dame. + // Copyright 2006 Trustees of Indiana University + // Authors: Jeremy G. Siek and Douglas Gregor <dgregor@cs.indiana.edu> + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/adjacency_matrix.hpp [2:4] + +KEEP COPYRIGHT_SERVICE_LABEL c43f1a8f551d96ac636a4afde37c7277 +BELONGS ya.make + License text: + // (C) Copyright 2009 Eric Bose-Wolf + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/transitive_reduction.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL c44aa21684966e124d964b7f61ceb274 +BELONGS ya.make + License text: + // Copyright (C) 2006 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/st_connected.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL c6f32cbdc60da329c029d3eceb822cb5 +BELONGS ya.make + License text: + // Copyright 2001 Indiana University + // Author: Jeremy G. Siek + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/iteration_macros.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL c8b2225195e675e39283e940da8d4aca +BELONGS ya.make + License text: + // Copyright 2013 Maciej Piechotka + // Authors: Maciej Piechotka + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/edge_coloring.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL c91df6862997c9f36164f1308b236bf7 +BELONGS ya.make + License text: + // Copyright 2007 Aaron Windsor + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/boyer_myrvold_planar_test.hpp [2:2] + include/boost/graph/is_kuratowski_subgraph.hpp [2:2] + include/boost/graph/is_straight_line_drawing.hpp [2:2] + include/boost/graph/make_biconnected_planar.hpp [2:2] + include/boost/graph/make_connected.hpp [2:2] + include/boost/graph/make_maximal_planar.hpp [2:2] + include/boost/graph/planar_detail/add_edge_visitors.hpp [2:2] + include/boost/graph/planar_detail/bucket_sort.hpp [2:2] + +KEEP COPYRIGHT_SERVICE_LABEL cc20f3be80fcae2741d451fd54843c93 +BELONGS ya.make + License text: + // Copyright 2001 University of Notre Dame. + // Copyright 2006 Trustees of Indiana University + // Authors: Jeremy G. Siek and Douglas Gregor <dgregor@cs.indiana.edu> + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/adjacency_matrix.hpp [2:4] + include/boost/graph/dll_import_export.hpp [2:4] + include/boost/graph/graphviz.hpp [2:4] + include/boost/graph/subgraph.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL cde0b758663026af6e7dea405ee6bf38 +BELONGS ya.make + License text: + // Copyright Louis Dionne 2013 + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/hawick_circuits.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL d08ee88acc4c1b352aea89d4523daace +BELONGS ya.make + License text: + // Copyright 2009, Andrew Sutton + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/graph_concepts.hpp [6:6] + +KEEP COPYRIGHT_SERVICE_LABEL d52e2e3deec2da9a498dcf40b8dc3655 +BELONGS ya.make + License text: + // Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) + // ETH Zurich, Center of Structure Technologies + // (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/) + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/profile.hpp [3:5] + include/boost/graph/sloan_ordering.hpp [3:5] + include/boost/graph/wavefront.hpp [3:5] + +KEEP COPYRIGHT_SERVICE_LABEL d91946878c8cc10edec238acbae07c4c +BELONGS ya.make + License text: + // Copyright 2005-2009 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/compressed_sparse_row_graph.hpp [1:1] + include/boost/graph/detail/compressed_sparse_row_struct.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL d9d3f9179a9781a228af49eebba2dba2 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/leda_graph.hpp [2:6] + +KEEP COPYRIGHT_SERVICE_LABEL e52d2d00c0bddf195fcd2e865710a087 +BELONGS ya.make + License text: + // Copyright (C) 2001 Jeremy Siek, Douglas Gregor, Brian Osman + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/isomorphism.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL e660351224f73455ec6e8b19ff54015b +BELONGS ya.make + License text: + // Copyright 2013 University of Warsaw. + // Authors: Piotr Wygocki + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/cycle_canceling.hpp [2:3] + include/boost/graph/detail/augment.hpp [2:3] + include/boost/graph/find_flow_cost.hpp [2:3] + include/boost/graph/successive_shortest_path_nonnegative_weights.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL e948c32bb4fec5a27e9bbe3a45398269 +BELONGS ya.make + License text: + // (C) Copyright Jeremy Siek 2006 + // Distributed under the Boost Software License, Version 1.0. (See + // accompanying file LICENSE_1_0.txt or copy at + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/pending/property_serialize.hpp [1:3] + +KEEP COPYRIGHT_SERVICE_LABEL e9c139c5d04d10ee2bf656ff900cbbaf +BELONGS ya.make + License text: + // Copyright (c) Aaron Windsor 2007 + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/chrobak_payne_drawing.hpp [2:2] + include/boost/graph/planar_canonical_ordering.hpp [2:2] + include/boost/graph/planar_detail/boyer_myrvold_impl.hpp [2:2] + include/boost/graph/planar_detail/face_handles.hpp [2:2] + include/boost/graph/planar_detail/face_iterators.hpp [2:2] + include/boost/graph/planar_face_traversal.hpp [2:2] + +KEEP COPYRIGHT_SERVICE_LABEL edd357e5bb31d28a8d2f7af650d68345 +BELONGS ya.make + License text: + // Copyright (C) 2006-2009 Dmitry Bufistov and Andrey Parfenov + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/howard_cycle_ratio.hpp [1:1] + +KEEP COPYRIGHT_SERVICE_LABEL f135edc02c00b6582ebdd933caabbc00 +BELONGS ya.make + License text: + // Copyright 1997, 1998, 1999, 2000 University of Notre Dame. + // Copyright 2003 Bruce Barr + // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/depth_first_search.hpp [2:4] + +KEEP COPYRIGHT_SERVICE_LABEL f1f8468601bd581bae0bf23eba4b070b +BELONGS ya.make + License text: + // Copyright (c) Jeremy Siek 2001 + // Copyright (c) Douglas Gregor 2004 + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/biconnected_components.hpp [1:2] + +KEEP COPYRIGHT_SERVICE_LABEL f2afe39f6ff7491f267ce9bc28a07daa +BELONGS ya.make + License text: + // Copyright 1997-2001 University of Notre Dame. + // Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/connected_components.hpp [3:4] + include/boost/graph/copy.hpp [3:4] + include/boost/graph/incremental_components.hpp [3:5] + include/boost/graph/minimum_degree_ordering.hpp [3:4] + include/boost/graph/stanford_graph.hpp [2:3] + +KEEP COPYRIGHT_SERVICE_LABEL fd6578dd286e9257f73d8cc59e377eb7 +BELONGS ya.make + License text: + // Copyright (C) 2005-2009 Jongsoo Park <jongsoo.park -at- gmail.com> + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/dominator_tree.hpp [2:2] + +KEEP COPYRIGHT_SERVICE_LABEL fda42ec6f8d7fcf06eb7924a33f02d3c +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/cuthill_mckee_ordering.hpp [2:5] + include/boost/graph/detail/sparse_ordering.hpp [2:5] + include/boost/graph/king_ordering.hpp [2:5] + +KEEP COPYRIGHT_SERVICE_LABEL ff121923a9c0b6799597434faafbacb1 +BELONGS ya.make + License text: + // Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de> + // Copyright (C) 2004 The Trustees of Indiana University. + Scancode info: + Original SPDX id: COPYRIGHT_SERVICE_LABEL + Score : 100.00 + Match type : COPYRIGHT + Files with this license: + include/boost/graph/graphml.hpp [1:2] + src/graphml.cpp [1:2] diff --git a/contrib/restricted/boost/graph/.yandex_meta/devtools.licenses.report b/contrib/restricted/boost/graph/.yandex_meta/devtools.licenses.report new file mode 100644 index 0000000000..5826ab2c9c --- /dev/null +++ b/contrib/restricted/boost/graph/.yandex_meta/devtools.licenses.report @@ -0,0 +1,421 @@ +# File format ($ symbol means the beginning of a line): +# +# $ # this message +# $ # ======================= +# $ # comments (all commentaries should starts with some number of spaces and # symbol) +# $ IGNORE_FILES {file1.ext1} {file2.ext2} - (optional) ignore listed files when generating license macro and credits +# $ RENAME {original license id} TO {new license id} # user comments - (optional) use {new license id} instead {original license id} in ya.make files +# $ # user comments +# $ +# ${action} {license id} {license text hash} +# $BELONGS ./ya/make/file/relative/path/1/ya.make ./ya/make/2/ya.make +# ${all_file_action} filename +# $ # user commentaries (many lines) +# $ generated description - files with this license, license text... (some number of lines that starts with some number of spaces, do not modify) +# ${action} {license spdx} {license text hash} +# $BELONGS ./ya/make/file/relative/path/3/ya.make +# ${all_file_action} filename +# $ # user commentaries +# $ generated description +# $ ... +# +# You can modify action, all_file_action and add commentaries +# Available actions: +# keep - keep license in contrib and use in credits +# skip - skip license +# remove - remove all files with this license +# rename - save license text/links into licenses texts file, but not store SPDX into LINCENSE macro. You should store correct license id into devtools.license.spdx.txt file +# +# {all file action} records will be generated when license text contains filename that exists on filesystem (in contrib directory) +# We suppose that that files can contain some license info +# Available all file actions: +# FILE_IGNORE - ignore file (do nothing) +# FILE_INCLUDE - include all file data into licenses text file +# ======================= + +KEEP BSL-1.0 05954ae47dedb48ccaf95b3af88bc2aa +BELONGS ya.make + License text: + // Use, modification and distribution is subject to the Boost Software + // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 96.88 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/detail/labeled_graph_traits.hpp [3:5] + include/boost/graph/dimacs.hpp [3:5] + include/boost/graph/edmunds_karp_max_flow.hpp [3:5] + include/boost/graph/graph_mutability_traits.hpp [3:5] + include/boost/graph/graph_stats.hpp [3:5] + include/boost/graph/graphml.hpp [4:6] + include/boost/graph/howard_cycle_ratio.hpp [3:5] + include/boost/graph/labeled_graph.hpp [3:5] + include/boost/graph/mesh_graph_generator.hpp [3:5] + include/boost/graph/metis.hpp [3:5] + include/boost/graph/named_graph.hpp [3:5] + include/boost/graph/overloading.hpp [3:5] + include/boost/graph/point_traits.hpp [3:5] + include/boost/graph/rmat_graph_generator.hpp [3:5] + include/boost/graph/ssca_graph_generator.hpp [3:5] + include/boost/graph/st_connected.hpp [3:5] + include/boost/graph/vertex_and_edge_range.hpp [3:5] + include/boost/pending/relaxed_heap.hpp [3:5] + src/graphml.cpp [4:6] + +KEEP BSL-1.0 2cc71fe4bd12718a9884bf7ff37269f3 +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/bc_clustering.hpp [3:5] + include/boost/graph/betweenness_centrality.hpp [3:5] + include/boost/graph/circle_layout.hpp [3:5] + include/boost/graph/compressed_sparse_row_graph.hpp [3:5] + include/boost/graph/detail/compressed_sparse_row_struct.hpp [3:5] + include/boost/graph/detail/histogram_sort.hpp [3:5] + include/boost/graph/detail/indexed_properties.hpp [3:5] + include/boost/graph/detail/is_distributed_selector.hpp [3:5] + include/boost/graph/detail/read_graphviz_new.hpp [3:5] + include/boost/graph/detail/read_graphviz_spirit.hpp [3:5] + include/boost/graph/dominator_tree.hpp [4:6] + include/boost/graph/erdos_renyi_generator.hpp [3:5] + include/boost/graph/floyd_warshall_shortest.hpp [3:5] + include/boost/graph/fruchterman_reingold.hpp [3:5] + include/boost/graph/gursoy_atun_layout.hpp [3:5] + include/boost/graph/kamada_kawai_spring_layout.hpp [3:5] + include/boost/graph/loop_erased_random_walk.hpp [3:5] + include/boost/graph/max_cardinality_matching.hpp [4:6] + include/boost/graph/maximum_weighted_matching.hpp [4:6] + include/boost/graph/one_bit_color_map.hpp [3:5] + include/boost/graph/page_rank.hpp [4:6] + include/boost/graph/plod_generator.hpp [3:5] + include/boost/graph/random_layout.hpp [3:5] + include/boost/graph/random_spanning_tree.hpp [3:5] + include/boost/graph/small_world_generator.hpp [3:5] + include/boost/graph/topology.hpp [3:5] + include/boost/graph/two_bit_color_map.hpp [3:5] + src/read_graphviz_new.cpp [3:5] + +KEEP BSL-1.0 3483ad6500a5ec5c1eed3d256900b057 +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/boykov_kolmogorov_max_flow.hpp [28:30] + include/boost/graph/write_dimacs.hpp [28:30] + +KEEP BSL-1.0 47a0454637d4fa45d78eb2557ccd70c4 +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. (See + // accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/adj_list_serialize.hpp [5:7] + include/boost/graph/adjacency_iterator.hpp [5:7] + include/boost/graph/adjacency_list.hpp [6:8] + include/boost/graph/adjacency_list_io.hpp [5:7] + include/boost/graph/adjacency_matrix.hpp [6:8] + include/boost/graph/astar_search.hpp [7:9] + include/boost/graph/bandwidth.hpp [3:5] + include/boost/graph/bellman_ford_shortest_paths.hpp [6:8] + include/boost/graph/biconnected_components.hpp [4:6] + include/boost/graph/boyer_myrvold_planar_test.hpp [4:6] + include/boost/graph/breadth_first_search.hpp [6:8] + include/boost/graph/chrobak_payne_drawing.hpp [4:6] + include/boost/graph/connected_components.hpp [6:8] + include/boost/graph/copy.hpp [6:8] + include/boost/graph/core_numbers.hpp [6:8] + include/boost/graph/create_condensation_graph.hpp [5:7] + include/boost/graph/cuthill_mckee_ordering.hpp [7:9] + include/boost/graph/cycle_canceling.hpp [5:7] + include/boost/graph/dag_shortest_paths.hpp [5:7] + include/boost/graph/depth_first_search.hpp [6:8] + include/boost/graph/detail/adj_list_edge_iterator.hpp [6:8] + include/boost/graph/detail/adjacency_list.hpp [7:9] + include/boost/graph/detail/array_binary_tree.hpp [6:8] + include/boost/graph/detail/augment.hpp [5:7] + include/boost/graph/detail/connected_components.hpp [5:7] + include/boost/graph/detail/d_ary_heap.hpp [6:8] + include/boost/graph/detail/edge.hpp [6:8] + include/boost/graph/detail/incidence_iterator.hpp [6:8] + include/boost/graph/detail/incremental_components.hpp [6:8] + include/boost/graph/detail/list_base.hpp [5:7] + include/boost/graph/detail/permutation.hpp [2:4] + include/boost/graph/detail/self_avoiding_walk.hpp [5:7] + include/boost/graph/detail/set_adaptor.hpp [2:4] + include/boost/graph/detail/shadow_iterator.hpp [2:4] + include/boost/graph/detail/sparse_ordering.hpp [7:9] + include/boost/graph/dijkstra_shortest_paths.hpp [5:7] + include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp [6:8] + include/boost/graph/dll_import_export.hpp [6:8] + include/boost/graph/edge_coloring.hpp [5:7] + include/boost/graph/edge_connectivity.hpp [5:7] + include/boost/graph/edge_list.hpp [5:7] + include/boost/graph/edmonds_karp_max_flow.hpp [5:7] + include/boost/graph/exception.hpp [5:7] + include/boost/graph/filtered_graph.hpp [5:7] + include/boost/graph/find_flow_cost.hpp [5:7] + include/boost/graph/graph_archetypes.hpp [5:7] + include/boost/graph/graph_as_tree.hpp [6:8] + include/boost/graph/graph_concepts.hpp [8:10] + include/boost/graph/graph_selectors.hpp [5:7] + include/boost/graph/graph_traits.hpp [5:7] + include/boost/graph/graph_utility.hpp [6:8] + include/boost/graph/graphviz.hpp [6:8] + include/boost/graph/grid_graph.hpp [5:7] + include/boost/graph/incremental_components.hpp [7:9] + include/boost/graph/is_kuratowski_subgraph.hpp [4:6] + include/boost/graph/is_straight_line_drawing.hpp [4:6] + include/boost/graph/isomorphism.hpp [3:5] + include/boost/graph/iteration_macros.hpp [5:7] + include/boost/graph/iteration_macros_undef.hpp [5:7] + include/boost/graph/johnson_all_pairs_shortest.hpp [5:7] + include/boost/graph/king_ordering.hpp [7:9] + include/boost/graph/kruskal_min_spanning_tree.hpp [6:8] + include/boost/graph/leda_graph.hpp [8:10] + include/boost/graph/lookup_edge.hpp [5:7] + include/boost/graph/make_biconnected_planar.hpp [4:6] + include/boost/graph/make_connected.hpp [4:6] + include/boost/graph/make_maximal_planar.hpp [4:6] + include/boost/graph/matrix_as_graph.hpp [6:8] + include/boost/graph/maximum_adjacency_search.hpp [6:8] + include/boost/graph/mcgregor_common_subgraphs.hpp [5:7] + include/boost/graph/metric_tsp_approx.hpp [6:8] + include/boost/graph/minimum_degree_ordering.hpp [6:8] + include/boost/graph/named_function_params.hpp [5:7] + include/boost/graph/neighbor_bfs.hpp [6:8] + include/boost/graph/planar_canonical_ordering.hpp [4:6] + include/boost/graph/planar_detail/add_edge_visitors.hpp [4:6] + include/boost/graph/planar_detail/boyer_myrvold_impl.hpp [4:6] + include/boost/graph/planar_detail/bucket_sort.hpp [4:6] + include/boost/graph/planar_detail/face_handles.hpp [4:6] + include/boost/graph/planar_detail/face_iterators.hpp [4:6] + include/boost/graph/planar_face_traversal.hpp [4:6] + include/boost/graph/prim_minimum_spanning_tree.hpp [5:7] + include/boost/graph/profile.hpp [7:9] + include/boost/graph/properties.hpp [5:7] + include/boost/graph/property_iter_range.hpp [4:6] + include/boost/graph/push_relabel_max_flow.hpp [5:7] + include/boost/graph/random.hpp [6:8] + include/boost/graph/read_dimacs.hpp [5:7] + include/boost/graph/relax.hpp [5:7] + include/boost/graph/reverse_graph.hpp [2:4] + include/boost/graph/sequential_vertex_coloring.hpp [6:8] + include/boost/graph/simple_point.hpp [5:7] + include/boost/graph/sloan_ordering.hpp [7:9] + include/boost/graph/smallest_last_ordering.hpp [5:7] + include/boost/graph/stanford_graph.hpp [5:7] + include/boost/graph/strong_components.hpp [6:8] + include/boost/graph/subgraph.hpp [5:7] + include/boost/graph/successive_shortest_path_nonnegative_weights.hpp [5:7] + include/boost/graph/topological_sort.hpp [6:8] + include/boost/graph/transitive_closure.hpp [3:5] + include/boost/graph/transpose_graph.hpp [6:8] + include/boost/graph/tree_traits.hpp [2:4] + include/boost/graph/undirected_dfs.hpp [6:8] + include/boost/graph/vector_as_graph.hpp [7:9] + include/boost/graph/vf2_sub_graph_iso.hpp [10:12] + include/boost/graph/visitors.hpp [5:7] + include/boost/graph/wavefront.hpp [7:9] + include/boost/pending/bucket_sorter.hpp [6:8] + include/boost/pending/disjoint_sets.hpp [6:8] + include/boost/pending/fibonacci_heap.hpp [2:4] + include/boost/pending/indirect_cmp.hpp [6:8] + include/boost/pending/is_heap.hpp [6:8] + include/boost/pending/mutable_heap.hpp [6:8] + include/boost/pending/mutable_queue.hpp [6:8] + +KEEP BSL-1.0 50dc18b27f34dab68ff41aa3f7880dda +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/two_graphs_common_spanning_trees.hpp [2:4] + +KEEP BSL-1.0 56683ba341300dc4497f873f670c97b9 +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or copy at + // http://boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 96.30 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/r_c_shortest_paths.hpp [4:6] + +KEEP BSL-1.0 8abbac2c705b0911702566954b0ebe9b +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. (See + // accompanying file LICENSE_1_0.txt or copy at + // http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/pending/container_traits.hpp [4:6] + include/boost/pending/detail/disjoint_sets.hpp [2:4] + include/boost/pending/detail/property.hpp [2:4] + include/boost/pending/fenced_priority_queue.hpp [2:4] + include/boost/pending/property.hpp [2:4] + include/boost/pending/property_serialize.hpp [2:4] + include/boost/pending/queue.hpp [2:4] + include/boost/pending/stringtok.hpp [2:4] + +KEEP Mit-Old-Style 99b210ed9efe704d061e43a6c4c4beb3 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: LicenseRef-scancode-mit-old-style + Score : 100.00 + Match type : TEXT + Links : http://fedoraproject.org/wiki/Licensing:MIT#Old_Style, https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/mit-old-style.LICENSE + Files with this license: + include/boost/detail/algorithm.hpp [22:28] + +KEEP BSL-1.0 a4b06853a77321815bca2cbd7654b649 +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. (See accompany- + // ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 96.30 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/detail/algorithm.hpp [2:3] + +KEEP BSL-1.0 b03e7ad31a88c7f7892fe8557944edb4 +BELONGS ya.make + License text: + // Use, modification and distribution are subject to the + // Boost Software License, Version 1.0 (See accompanying file + // LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 93.75 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/bron_kerbosch_all_cliques.hpp [3:5] + include/boost/graph/closeness_centrality.hpp [3:5] + include/boost/graph/clustering_coefficient.hpp [3:5] + include/boost/graph/degree_centrality.hpp [3:5] + include/boost/graph/detail/empty_header.hpp [6:8] + include/boost/graph/detail/geodesic.hpp [3:5] + include/boost/graph/detail/index.hpp [3:5] + include/boost/graph/detail/mpi_include.hpp [6:8] + include/boost/graph/directed_graph.hpp [3:5] + include/boost/graph/eccentricity.hpp [3:5] + include/boost/graph/exterior_property.hpp [3:5] + include/boost/graph/geodesic_distance.hpp [3:5] + include/boost/graph/numeric_values.hpp [3:5] + include/boost/graph/property_maps/constant_property_map.hpp [3:5] + include/boost/graph/property_maps/container_property_map.hpp [3:5] + include/boost/graph/property_maps/matrix_property_map.hpp [3:5] + include/boost/graph/property_maps/null_property_map.hpp [3:5] + include/boost/graph/tiernan_all_cycles.hpp [3:5] + include/boost/graph/transitive_reduction.hpp [3:5] + include/boost/graph/undirected_graph.hpp [3:5] + +KEEP Mit-Old-Style b202f5e6061e3eeef6c7dcc2414164b3 +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: LicenseRef-scancode-mit-old-style + Score : 100.00 + Match type : TEXT + Links : http://fedoraproject.org/wiki/Licensing:MIT#Old_Style, https://github.com/nexB/scancode-toolkit/tree/develop/src/licensedcode/data/licenses/mit-old-style.LICENSE + Files with this license: + include/boost/detail/algorithm.hpp [10:16] + +KEEP BSL-1.0 bb0492d92471ff074c380f255ab94b94 +BELONGS ya.make + License text: + // Use, modification and distribution is subject to the Boost Software + // License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy + // at http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 96.88 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/hawick_circuits.hpp [3:5] + +KEEP BSL-1.0 bf0fd55850dbf83aac86f825081dbe20 +BELONGS ya.make + License text: + // Distributed under the Boost Software License, Version 1.0. + // (See accompanying file LICENSE_1_0.txt or the copy at + // http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 96.43 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/buffer_concepts.hpp [2:4] + include/boost/graph/stoer_wagner_min_cut.hpp [2:4] + +KEEP MIT e8fa61ad26065c016c4c968298a683bd +BELONGS ya.make + Note: matched license text is too long. Read it in the source files. + Scancode info: + Original SPDX id: MIT + Score : 100.00 + Match type : TEXT + Links : http://opensource.org/licenses/mit-license.php, https://spdx.org/licenses/MIT + Files with this license: + include/boost/graph/boykov_kolmogorov_max_flow.hpp [5:24] + include/boost/graph/write_dimacs.hpp [5:24] + +KEEP BSL-1.0 f20f9faff5dff60d6b8844771d700dd5 +BELONGS ya.make + License text: + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + Scancode info: + Original SPDX id: BSL-1.0 + Score : 100.00 + Match type : NOTICE + Links : http://www.boost.org/LICENSE_1_0.txt, http://www.boost.org/users/license.html, https://spdx.org/licenses/BSL-1.0 + Files with this license: + include/boost/graph/bipartite.hpp [7:9] diff --git a/contrib/restricted/boost/graph/.yandex_meta/licenses.list.txt b/contrib/restricted/boost/graph/.yandex_meta/licenses.list.txt new file mode 100644 index 0000000000..9498d0c9c3 --- /dev/null +++ b/contrib/restricted/boost/graph/.yandex_meta/licenses.list.txt @@ -0,0 +1,477 @@ +====================BSL-1.0==================== + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or the copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) + + +====================BSL-1.0==================== +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + + +====================COPYRIGHT==================== + * Copyright (c) 1994 + * Hewlett-Packard Company + + +====================COPYRIGHT==================== + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + + +====================COPYRIGHT==================== + * Copyright (c) 2010 Matthias Walter (xammy@xammy.homelinux.net) + + +====================COPYRIGHT==================== +// Copyright Daniel Trebbien 2010. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or the copy at + + +====================COPYRIGHT==================== +// Copyright (C) 2012, Michele Caini. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// (C) Copyright David Abrahams 2000. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// (C) Copyright Jeremiah Willcock 2004 +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// (C) Copyright Jeremy Siek 1999. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// (C) Copyright Jeremy Siek 2004 +// (C) Copyright Thomas Claveirole 2010 +// (C) Copyright Ignacy Gawedzki 2010 +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// (C) Copyright Jeremy Siek 2006 +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// Copyright (c) 2006, Stephan Diederich + + +====================COPYRIGHT==================== +// (C) Copyright 2007 Andrew Sutton + + +====================COPYRIGHT==================== +// (C) Copyright 2007-2009 Andrew Sutton + + +====================COPYRIGHT==================== +// (C) Copyright 2009 Eric Bose-Wolf + + +====================COPYRIGHT==================== +// (C) Copyright Andrew Sutton 2007 + + +====================COPYRIGHT==================== +// (C) Copyright Francois Faure, iMAGIS-GRAVIR / UJF, 2001. + + +====================COPYRIGHT==================== +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + + +====================COPYRIGHT==================== +// (c) Copyright Juergen Hunold 2008 +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// Copyright (C) 2001 Jeremy Siek, Douglas Gregor, Brian Osman + + +====================COPYRIGHT==================== +// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su> +// Copyright (C) 2001 Jeremy Siek <jsiek@cs.indiana.edu> +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at + + +====================COPYRIGHT==================== +// Copyright (C) 2005-2006 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright (C) 2005-2009 Jongsoo Park <jongsoo.park -at- gmail.com> + + +====================COPYRIGHT==================== +// Copyright (C) 2005-2010 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de> +// Copyright (C) 2004 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright (C) 2006 Tiago de Paula Peixoto <tiago@forked.de> +// Copyright (C) 2004,2009 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright (C) 2006 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright (C) 2006-2009 Dmitry Bufistov and Andrey Parfenov + + +====================COPYRIGHT==================== +// Copyright (C) 2007 Douglas Gregor + + +====================COPYRIGHT==================== +// Copyright (C) 2009 Andrew Sutton + + +====================COPYRIGHT==================== +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark +// (jlandersen@imada.sdu.dk) + + +====================COPYRIGHT==================== +// Copyright (c) 2004 Kristopher Beevers + + +====================COPYRIGHT==================== +// Copyright (c) 2005 Aaron Windsor + + +====================COPYRIGHT==================== +// Copyright (c) 2018 Yi Ji + + +====================COPYRIGHT==================== +// Copyright (c) Aaron Windsor 2007 + + +====================COPYRIGHT==================== +// Copyright (c) Jeremy Siek 2001 +// Copyright (c) Douglas Gregor 2004 + + +====================COPYRIGHT==================== +// Copyright (c) Jeremy Siek 2001, Marc Wintermantel 2002 + + +====================COPYRIGHT==================== +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright (C) Vladimir Prus 2003 +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + + +====================COPYRIGHT==================== +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2003 Bruce Barr +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + + +====================COPYRIGHT==================== +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004 The Trustees of Indiana University. +// Copyright 2007 University of Karlsruhe +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor, +// Jens Mueller + + +====================COPYRIGHT==================== +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004, 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// Doug Gregor, D. Kevin McGrath + + +====================COPYRIGHT==================== +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2006 The Trustees of Indiana University. +// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su> +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor + + +====================COPYRIGHT==================== +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2009 Trustees of Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen + + +====================COPYRIGHT==================== +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2010 Thomas Claveirole +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Thomas Claveirole + + +====================COPYRIGHT==================== +// Copyright 1997-2001 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + + +====================COPYRIGHT==================== +// Copyright 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee + + +====================COPYRIGHT==================== +// Copyright 2001 Indiana University +// Author: Jeremy G. Siek + + +====================COPYRIGHT==================== +// Copyright 2001 Universite Joseph Fourier, Grenoble. +// Author: Francois Faure + + +====================COPYRIGHT==================== +// Copyright 2001 University of Notre Dame. +// Copyright 2003 Jeremy Siek +// Authors: Lie-Quan Lee, Jeremy Siek, and Douglas Gregor + + +====================COPYRIGHT==================== +// Copyright 2001 University of Notre Dame. +// Copyright 2006 Trustees of Indiana University +// Authors: Jeremy G. Siek and Douglas Gregor <dgregor@cs.indiana.edu> + + +====================COPYRIGHT==================== +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek + + +====================COPYRIGHT==================== +// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) +// ETH Zurich, Center of Structure Technologies +// (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/) + + +====================COPYRIGHT==================== +// Copyright 2002 Rensselaer Polytechnic Institute + + +====================COPYRIGHT==================== +// Copyright 2004 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2004, 2005 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2004-2006 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2004-5 The Trustees of Indiana University. +// Copyright 2002 Brad King and Douglas Gregor + + +====================COPYRIGHT==================== +// Copyright 2004-9 Trustees of Indiana University + + +====================COPYRIGHT==================== +// Copyright 2005 Jeremy G. Siek +// Authors: Jeremy G. Siek + + +====================COPYRIGHT==================== +// Copyright 2005 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Douglas Gregor + + +====================COPYRIGHT==================== +// Copyright 2005-2009 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2007 Aaron Windsor + + +====================COPYRIGHT==================== +// Copyright 2007 Stanford University +// Authors: David Gleich + + +====================COPYRIGHT==================== +// Copyright 2008 +// Author: Matyas W Egyhazy + + +====================COPYRIGHT==================== +// Copyright 2009 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2009, Andrew Sutton + + +====================COPYRIGHT==================== +// Copyright 2010 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2012 Fernando Vilas +// 2010 Daniel Trebbien + + +====================COPYRIGHT==================== +// Copyright 2012 The Trustees of Indiana University. + + +====================COPYRIGHT==================== +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka + + +====================COPYRIGHT==================== +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki + + +====================COPYRIGHT==================== +// Copyright 2018 Peter Dimov + + +====================COPYRIGHT==================== +// Copyright Louis Dionne 2013 + + +====================COPYRIGHT==================== +// Copyright Michael Drexl 2005, 2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at + + +====================MIT==================== +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE. + + +====================Mit-Old-Style==================== + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + + +====================Mit-Old-Style==================== + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. diff --git a/contrib/restricted/boost/graph/include/boost/detail/algorithm.hpp b/contrib/restricted/boost/graph/include/boost/detail/algorithm.hpp new file mode 100644 index 0000000000..9b3195cbf0 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/detail/algorithm.hpp @@ -0,0 +1,83 @@ +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See accompany- +// ing file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt) + +/* + * + * Copyright (c) 1994 + * Hewlett-Packard Company + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Hewlett-Packard Company makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + * + * + * Copyright (c) 1996 + * Silicon Graphics Computer Systems, Inc. + * + * Permission to use, copy, modify, distribute and sell this software + * and its documentation for any purpose is hereby granted without fee, + * provided that the above copyright notice appear in all copies and + * that both that copyright notice and this permission notice appear + * in supporting documentation. Silicon Graphics makes no + * representations about the suitability of this software for any + * purpose. It is provided "as is" without express or implied warranty. + */ + +#ifndef BOOST_ALGORITHM_HPP +#define BOOST_ALGORITHM_HPP + +// Algorithms on sequences +// +// The functions in this file have not yet gone through formal +// review, and are subject to change. This is a work in progress. +// They have been checked into the detail directory because +// there are some graph algorithms that use these functions. + +#include <algorithm> +#include <vector> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/algorithm/copy.hpp> +#include <boost/range/algorithm/equal.hpp> +#include <boost/range/algorithm/sort.hpp> +#include <boost/range/algorithm/stable_sort.hpp> +#include <boost/range/algorithm/find_if.hpp> +#include <boost/range/algorithm/count.hpp> +#include <boost/range/algorithm/count_if.hpp> +#include <boost/range/algorithm_ext/is_sorted.hpp> +#include <boost/range/algorithm_ext/iota.hpp> + +namespace boost +{ + +template < typename InputIterator, typename Predicate > +bool any_if(InputIterator first, InputIterator last, Predicate p) +{ + return std::find_if(first, last, p) != last; +} + +template < typename Container, typename Predicate > +bool any_if(const Container& c, Predicate p) +{ + return any_if(boost::begin(c), boost::end(c), p); +} + +template < typename InputIterator, typename T > +bool container_contains(InputIterator first, InputIterator last, T value) +{ + return std::find(first, last, value) != last; +} +template < typename Container, typename T > +bool container_contains(const Container& c, const T& value) +{ + return container_contains(boost::begin(c), boost::end(c), value); +} + +} // namespace boost + +#endif // BOOST_ALGORITHM_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/adj_list_serialize.hpp b/contrib/restricted/boost/graph/include/boost/graph/adj_list_serialize.hpp new file mode 100644 index 0000000000..85f7e2ed41 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/adj_list_serialize.hpp @@ -0,0 +1,130 @@ +//======================================================================= +// Copyright 2005 Jeremy G. Siek +// Authors: Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_ADJ_LIST_SERIALIZE_HPP +#define BOOST_GRAPH_ADJ_LIST_SERIALIZE_HPP + +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/pending/property_serialize.hpp> +#include <boost/config.hpp> +#include <boost/detail/workaround.hpp> + +#include <boost/serialization/collections_save_imp.hpp> +#include <boost/serialization/collections_load_imp.hpp> +#include <boost/serialization/split_free.hpp> + +namespace boost +{ + +namespace serialization +{ + + // Turn off tracking for adjacency_list. It's not polymorphic, and we + // need to do this to enable saving of non-const adjacency lists. + template < class OEL, class VL, class D, class VP, class EP, class GP, + class EL > + struct tracking_level< boost::adjacency_list< OEL, VL, D, VP, EP, GP, EL > > + { + typedef mpl::integral_c_tag tag; + typedef mpl::int_< track_never > type; + BOOST_STATIC_CONSTANT(int, value = tracking_level::type::value); + }; + + template < class Archive, class OEL, class VL, class D, class VP, class EP, + class GP, class EL > + inline void save(Archive& ar, + const boost::adjacency_list< OEL, VL, D, VP, EP, GP, EL >& graph, + const unsigned int /* file_version */ + ) + { + typedef adjacency_list< OEL, VL, D, VP, EP, GP, EL > Graph; + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + int V = num_vertices(graph); + int E = num_edges(graph); + ar << BOOST_SERIALIZATION_NVP(V); + ar << BOOST_SERIALIZATION_NVP(E); + + // assign indices to vertices + std::map< Vertex, int > indices; + int num = 0; + BGL_FORALL_VERTICES_T(v, graph, Graph) + { + indices[v] = num++; + ar << serialization::make_nvp( + "vertex_property", get(vertex_all_t(), graph, v)); + } + + // write edges + BGL_FORALL_EDGES_T(e, graph, Graph) + { + ar << serialization::make_nvp("u", indices[source(e, graph)]); + ar << serialization::make_nvp("v", indices[target(e, graph)]); + ar << serialization::make_nvp( + "edge_property", get(edge_all_t(), graph, e)); + } + + ar << serialization::make_nvp( + "graph_property", get_property(graph, graph_all_t())); + } + + template < class Archive, class OEL, class VL, class D, class VP, class EP, + class GP, class EL > + inline void load( + Archive& ar, boost::adjacency_list< OEL, VL, D, VP, EP, GP, EL >& graph, + const unsigned int /* file_version */ + ) + { + typedef adjacency_list< OEL, VL, D, VP, EP, GP, EL > Graph; + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::edge_descriptor Edge; + + unsigned int V; + ar >> BOOST_SERIALIZATION_NVP(V); + unsigned int E; + ar >> BOOST_SERIALIZATION_NVP(E); + + std::vector< Vertex > verts(V); + int i = 0; + while (V-- > 0) + { + Vertex v = add_vertex(graph); + verts[i++] = v; + ar >> serialization::make_nvp( + "vertex_property", get(vertex_all_t(), graph, v)); + } + while (E-- > 0) + { + int u; + int v; + ar >> BOOST_SERIALIZATION_NVP(u); + ar >> BOOST_SERIALIZATION_NVP(v); + Edge e; + bool inserted; + boost::tie(e, inserted) = add_edge(verts[u], verts[v], graph); + ar >> serialization::make_nvp( + "edge_property", get(edge_all_t(), graph, e)); + } + ar >> serialization::make_nvp( + "graph_property", get_property(graph, graph_all_t())); + } + + template < class Archive, class OEL, class VL, class D, class VP, class EP, + class GP, class EL > + inline void serialize(Archive& ar, + boost::adjacency_list< OEL, VL, D, VP, EP, GP, EL >& graph, + const unsigned int file_version) + { + boost::serialization::split_free(ar, graph, file_version); + } + +} // serialization +} // boost + +#endif // BOOST_GRAPH_ADJ_LIST_SERIALIZE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/adjacency_list_io.hpp b/contrib/restricted/boost/graph/include/boost/graph/adjacency_list_io.hpp new file mode 100644 index 0000000000..4a85bebd99 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/adjacency_list_io.hpp @@ -0,0 +1,405 @@ +//======================================================================= +// Copyright 2001 Universite Joseph Fourier, Grenoble. +// Author: Francois Faure +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_ADJACENCY_LIST_IO_HPP +#define BOOST_GRAPH_ADJACENCY_LIST_IO_HPP + +#include <iostream> +#include <vector> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <cctype> + +// Method read to parse an adjacency list from an input stream. Examples: +// cin >> read( G ); +// cin >> read( G, NodePropertySubset(), EdgepropertySubset() ); +// +// Method write to print an adjacency list to an output stream. Examples: +// cout << write( G ); +// cout << write( G, NodePropertySubset(), EdgepropertySubset() ); + +namespace boost +{ + +/* outline + - basic property input + - get property subset + - graph parser + - property printer + - graph printer + - user methods +*/ + +//=========================================================================== +// basic property input + +template < class Tag, class Value, class Next > +std::istream& operator>>(std::istream& in, property< Tag, Value, Next >& p) +{ + in >> p.m_value >> p.m_base; // houpla !! + return in; +} + +template < class Tag, class Value > +std::istream& operator>>( + std::istream& in, property< Tag, Value, no_property >& p) +{ + in >> p.m_value; + return in; +} + +inline std::istream& operator>>(std::istream& in, no_property&) { return in; } + +// basic property input +//=========================================================================== +// get property subsets + +// get a single property tagged Stag +template < class Tag, class Value, class Next, class V, class Stag > +void get(property< Tag, Value, Next >& p, const V& v, Stag s) +{ + get(p.m_base, v, s); +} + +template < class Value, class Next, class V, class Stag > +void get(property< Stag, Value, Next >& p, const V& v, Stag) +{ + p.m_value = v; +} + +// get a subset of properties tagged Stag +template < class Tag, class Value, class Next, class Stag, class Svalue, + class Snext > +void getSubset( + property< Tag, Value, Next >& p, const property< Stag, Svalue, Snext >& s) +{ + get(p, s.m_value, Stag()); + getSubset(p, s.m_base); +} + +template < class Tag, class Value, class Next, class Stag, class Svalue > +void getSubset(property< Tag, Value, Next >& p, + const property< Stag, Svalue, no_property >& s) +{ + get(p, s.m_value, Stag()); +} + +inline void getSubset(no_property&, const no_property&) {} + +#if !defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) +template < typename T, typename U > void getSubset(T& p, const U& s) { p = s; } + +template < typename T > void getSubset(T&, const no_property&) {} + +#endif + +// get property subset +//=========================================================================== +// graph parser +typedef enum +{ + PARSE_NUM_NODES, + PARSE_VERTEX, + PARSE_EDGE +} GraphParserState; + +template < class Graph_t, class VertexProperty, class EdgeProperty, + class VertexPropertySubset, class EdgePropertySubset > +struct GraphParser +{ + + typedef Graph_t Graph; + + GraphParser(Graph* g) : graph(g) {} + + GraphParser& operator()(std::istream& in) + { + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + std::vector< Vertex > nodes; + + GraphParserState state = PARSE_VERTEX; + + unsigned int numLine = 1; + char c; + while (in.get(c)) + { + if (c == '#') + skip(in); + else if (c == 'n') + state = PARSE_NUM_NODES; + else if (c == 'v') + state = PARSE_VERTEX; + else if (c == 'e') + state = PARSE_EDGE; + else if (c == '\n') + numLine++; + else if (!std::isspace(c)) + { + in.putback(c); + if (state == PARSE_VERTEX) + { + VertexPropertySubset readProp; + if (in >> readProp) + { + VertexProperty vp; + getSubset(vp, readProp); + nodes.push_back(add_vertex(vp, *graph)); + } + else + std::cerr << "read vertex, parse error at line" + << numLine << std::endl; + } + else if (state == PARSE_EDGE) + { + int source, target; + EdgePropertySubset readProp; + in >> source >> target; + if (in >> readProp) + { + EdgeProperty ep; + getSubset(ep, readProp); + add_edge(nodes[source], nodes[target], ep, *graph); + } + else + std::cerr << "read edge, parse error at line" << numLine + << std::endl; + } + else + { // state == PARSE_NUM_NODES + int n; + if (in >> n) + { + for (int i = 0; i < n; ++i) + nodes.push_back(add_vertex(*graph)); + } + else + std::cerr << "read num_nodes, parse error at line " + << numLine << std::endl; + } + } + } + return (*this); + } + +protected: + Graph* graph; + + void skip(std::istream& in) + { + char c = 0; + while (c != '\n' && !in.eof()) + in.get(c); + in.putback(c); + } +}; + +// parser +//======================================================================= +// property printer + +#if defined(BOOST_GRAPH_NO_BUNDLED_PROPERTIES) +template < class Graph, class Property > struct PropertyPrinter +{ + typedef typename Property::value_type Value; + typedef typename Property::tag_type Tag; + typedef typename Property::next_type Next; + + PropertyPrinter(const Graph& g) : graph(&g) {} + + template < class Val > + PropertyPrinter& operator()(std::ostream& out, const Val& v) + { + typename property_map< Graph, Tag >::const_type ps = get(Tag(), *graph); + out << ps[v] << " "; + PropertyPrinter< Graph, Next > print(*graph); + print(out, v); + return (*this); + } + +private: + const Graph* graph; +}; +#else +template < class Graph, typename Property > struct PropertyPrinter +{ + PropertyPrinter(const Graph& g) : graph(&g) {} + + template < class Val > + PropertyPrinter& operator()(std::ostream& out, const Val& v) + { + out << (*graph)[v] << " "; + return (*this); + } + +private: + const Graph* graph; +}; + +template < class Graph, typename Tag, typename Value, typename Next > +struct PropertyPrinter< Graph, property< Tag, Value, Next > > +{ + PropertyPrinter(const Graph& g) : graph(&g) {} + + template < class Val > + PropertyPrinter& operator()(std::ostream& out, const Val& v) + { + typename property_map< Graph, Tag >::const_type ps = get(Tag(), *graph); + out << ps[v] << " "; + PropertyPrinter< Graph, Next > print(*graph); + print(out, v); + return (*this); + } + +private: + const Graph* graph; +}; +#endif + +template < class Graph > struct PropertyPrinter< Graph, no_property > +{ + PropertyPrinter(const Graph&) {} + + template < class Val > + PropertyPrinter& operator()(std::ostream&, const Val&) + { + return *this; + } +}; + +// property printer +//========================================================================= +// graph printer + +template < class Graph_t, class EdgeProperty > struct EdgePrinter +{ + + typedef Graph_t Graph; + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + EdgePrinter(const Graph& g) : graph(g) {} + + const EdgePrinter& operator()(std::ostream& out) const + { + // assign indices to vertices + std::map< Vertex, int > indices; + int num = 0; + BGL_FORALL_VERTICES_T(v, graph, Graph) { indices[v] = num++; } + + // write edges + PropertyPrinter< Graph, EdgeProperty > print_Edge(graph); + out << "e" << std::endl; + BGL_FORALL_EDGES_T(e, graph, Graph) + { + out << indices[source(e, graph)] << " " << indices[target(e, graph)] + << " "; + print_Edge(out, e); + out << std::endl; + } + out << std::endl; + return (*this); + } + +protected: + const Graph& graph; +}; + +template < class Graph, class V, class E > +struct GraphPrinter : public EdgePrinter< Graph, E > +{ + GraphPrinter(const Graph& g) : EdgePrinter< Graph, E >(g) {} + + const GraphPrinter& operator()(std::ostream& out) const + { + PropertyPrinter< Graph, V > printNode(this->graph); + out << "v" << std::endl; + BGL_FORALL_VERTICES_T(v, this->graph, Graph) + { + printNode(out, v); + out << std::endl; + } + + EdgePrinter< Graph, E >::operator()(out); + return (*this); + } +}; + +template < class Graph, class E > +struct GraphPrinter< Graph, no_property, E > : public EdgePrinter< Graph, E > +{ + GraphPrinter(const Graph& g) : EdgePrinter< Graph, E >(g) {} + + const GraphPrinter& operator()(std::ostream& out) const + { + out << "n " << num_vertices(this->graph) << std::endl; + EdgePrinter< Graph, E >::operator()(out); + return (*this); + } +}; + +// graph printer +//========================================================================= +// user methods + +/// input stream for reading a graph +template < class Graph, class VP, class EP, class VPS, class EPS > +std::istream& operator>>( + std::istream& in, GraphParser< Graph, VP, EP, VPS, EPS > gp) +{ + gp(in); + return in; +} + +/// graph parser for given subsets of internal vertex and edge properties +template < class EL, class VL, class D, class VP, class EP, class GP, class VPS, + class EPS > +GraphParser< adjacency_list< EL, VL, D, VP, EP, GP >, VP, EP, VPS, EPS > read( + adjacency_list< EL, VL, D, VP, EP, GP >& g, VPS vps, EPS eps) +{ + return GraphParser< adjacency_list< EL, VL, D, VP, EP, GP >, VP, EP, VPS, + EPS >(&g); +} + +/// graph parser for all internal vertex and edge properties +template < class EL, class VL, class D, class VP, class EP, class GP > +GraphParser< adjacency_list< EL, VL, D, VP, EP, GP >, VP, EP, VP, EP > read( + adjacency_list< EL, VL, D, VP, EP, GP >& g) +{ + return GraphParser< adjacency_list< EL, VL, D, VP, EP, GP >, VP, EP, VP, + EP >(&g); +} + +/// output stream for writing a graph +template < class Graph, class VP, class EP > +std::ostream& operator<<( + std::ostream& out, const GraphPrinter< Graph, VP, EP >& gp) +{ + gp(out); + return out; +} + +/// write the graph with given property subsets +template < class EL, class VL, class D, class VP, class EP, class GP, class VPS, + class EPS > +GraphPrinter< adjacency_list< EL, VL, D, VP, EP, GP >, VPS, EPS > write( + const adjacency_list< EL, VL, D, VP, EP, GP >& g, VPS, EPS) +{ + return GraphPrinter< adjacency_list< EL, VL, D, VP, EP, GP >, VPS, EPS >(g); +} + +/// write the graph with all internal vertex and edge properties +template < class EL, class VL, class D, class VP, class EP, class GP > +GraphPrinter< adjacency_list< EL, VL, D, VP, EP, GP >, VP, EP > write( + const adjacency_list< EL, VL, D, VP, EP, GP >& g) +{ + return GraphPrinter< adjacency_list< EL, VL, D, VP, EP, GP >, VP, EP >(g); +} + +// user methods +//========================================================================= +} // boost +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/adjacency_matrix.hpp b/contrib/restricted/boost/graph/include/boost/graph/adjacency_matrix.hpp new file mode 100644 index 0000000000..8d6990cb30 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/adjacency_matrix.hpp @@ -0,0 +1,1296 @@ +//======================================================================= +// Copyright 2001 University of Notre Dame. +// Copyright 2006 Trustees of Indiana University +// Authors: Jeremy G. Siek and Douglas Gregor <dgregor@cs.indiana.edu> +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_ADJACENCY_MATRIX_HPP +#define BOOST_ADJACENCY_MATRIX_HPP + +#include <boost/config.hpp> +#include <vector> +#include <memory> +#include <iterator> +#include <boost/assert.hpp> +#include <boost/limits.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_mutability_traits.hpp> +#include <boost/graph/graph_selectors.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/graph/adjacency_iterator.hpp> +#include <boost/graph/detail/edge.hpp> +#include <boost/iterator/iterator_adaptor.hpp> +#include <boost/iterator/filter_iterator.hpp> +#include <boost/range/irange.hpp> +#include <boost/graph/properties.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/static_assert.hpp> +#include <boost/type_traits.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/property_map/transform_value_property_map.hpp> +#include <boost/property_map/function_property_map.hpp> + +namespace boost +{ + +namespace detail +{ + + template < class Directed, class Vertex > + class matrix_edge_desc_impl : public edge_desc_impl< Directed, Vertex > + { + typedef edge_desc_impl< Directed, Vertex > Base; + + public: + matrix_edge_desc_impl() {} + matrix_edge_desc_impl( + bool exists, Vertex s, Vertex d, const void* ep = 0) + : Base(s, d, ep), m_exists(exists) + { + } + bool exists() const { return m_exists; } + + private: + bool m_exists; + }; + + struct does_edge_exist + { + template < class Edge > bool operator()(const Edge& e) const + { + return e.exists(); + } + }; + + // Note to self... The int for get_edge_exists and set_edge exist helps + // make these calls unambiguous. + template < typename EdgeProperty > + bool get_edge_exists( + const std::pair< bool, EdgeProperty >& stored_edge, int) + { + return stored_edge.first; + } + template < typename EdgeProperty > + void set_edge_exists( + std::pair< bool, EdgeProperty >& stored_edge, bool flag, int) + { + stored_edge.first = flag; + } + + template < typename EdgeProxy > + bool get_edge_exists(const EdgeProxy& edge_proxy, ...) + { + return edge_proxy; + } + template < typename EdgeProxy > + EdgeProxy& set_edge_exists(EdgeProxy& edge_proxy, bool flag, ...) + { + edge_proxy = flag; + return edge_proxy; // just to avoid never used warning + } + + // NOTE: These functions collide with the get_property function for + // accessing bundled graph properties. Be excplicit when using them. + template < typename EdgeProperty > + const EdgeProperty& get_edge_property( + const std::pair< bool, EdgeProperty >& stored_edge) + { + return stored_edge.second; + } + template < typename EdgeProperty > + EdgeProperty& get_edge_property( + std::pair< bool, EdgeProperty >& stored_edge) + { + return stored_edge.second; + } + + template < typename StoredEdgeProperty, typename EdgeProperty > + inline void set_edge_property( + std::pair< bool, StoredEdgeProperty >& stored_edge, + const EdgeProperty& ep, int) + { + stored_edge.second = ep; + } + + inline const no_property& get_edge_property(const char&) + { + static no_property s_prop; + return s_prop; + } + inline no_property& get_edge_property(char&) + { + static no_property s_prop; + return s_prop; + } + template < typename EdgeProxy, typename EdgeProperty > + inline void set_edge_property(EdgeProxy, const EdgeProperty&, ...) + { + } + + //======================================================================= + // Directed Out Edge Iterator + + template < typename VertexDescriptor, typename MatrixIter, + typename VerticesSizeType, typename EdgeDescriptor > + struct dir_adj_matrix_out_edge_iter + : iterator_adaptor< dir_adj_matrix_out_edge_iter< VertexDescriptor, + MatrixIter, VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + { + typedef iterator_adaptor< + dir_adj_matrix_out_edge_iter< VertexDescriptor, MatrixIter, + VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + super_t; + + dir_adj_matrix_out_edge_iter() {} + + dir_adj_matrix_out_edge_iter(const MatrixIter& i, + const VertexDescriptor& src, const VerticesSizeType& n) + : super_t(i), m_src(src), m_targ(0), m_n(n) + { + } + + void increment() + { + ++this->base_reference(); + ++m_targ; + } + + inline EdgeDescriptor dereference() const + { + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, + m_targ, &get_edge_property(*this->base())); + } + VertexDescriptor m_src, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Directed In Edge Iterator + + template < typename VertexDescriptor, typename MatrixIter, + typename VerticesSizeType, typename EdgeDescriptor > + struct dir_adj_matrix_in_edge_iter + : iterator_adaptor< dir_adj_matrix_in_edge_iter< VertexDescriptor, + MatrixIter, VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + { + typedef iterator_adaptor< + dir_adj_matrix_in_edge_iter< VertexDescriptor, MatrixIter, + VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + super_t; + + dir_adj_matrix_in_edge_iter() {} + + dir_adj_matrix_in_edge_iter(const MatrixIter& i, const MatrixIter& last, + const VertexDescriptor& tgt, const VerticesSizeType& n) + : super_t(i), m_last(last), m_src(0), m_targ(tgt), m_n(n) + { + } + + void increment() + { + if (VerticesSizeType(m_last - this->base_reference()) >= m_n) + { + this->base_reference() += m_n; + ++m_src; + } + else + { + this->base_reference() = m_last; + } + } + + inline EdgeDescriptor dereference() const + { + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, + m_targ, &get_edge_property(*this->base())); + } + MatrixIter m_last; + VertexDescriptor m_src, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Undirected Out Edge Iterator + + template < typename VertexDescriptor, typename MatrixIter, + typename VerticesSizeType, typename EdgeDescriptor > + struct undir_adj_matrix_out_edge_iter + : iterator_adaptor< undir_adj_matrix_out_edge_iter< VertexDescriptor, + MatrixIter, VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + { + typedef iterator_adaptor< + undir_adj_matrix_out_edge_iter< VertexDescriptor, MatrixIter, + VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + super_t; + + undir_adj_matrix_out_edge_iter() {} + + undir_adj_matrix_out_edge_iter(const MatrixIter& i, + const VertexDescriptor& src, const VerticesSizeType& n) + : super_t(i), m_src(src), m_inc(src), m_targ(0), m_n(n) + { + } + + void increment() + { + if (m_targ < m_src) // first half + { + ++this->base_reference(); + } + else if (m_targ < m_n - 1) + { // second half + ++m_inc; + this->base_reference() += m_inc; + } + else + { // past-the-end + this->base_reference() += m_n - m_src; + } + ++m_targ; + } + + inline EdgeDescriptor dereference() const + { + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, + m_targ, &get_edge_property(*this->base())); + } + + VertexDescriptor m_src, m_inc, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Undirected In Edge Iterator + + template < typename VertexDescriptor, typename MatrixIter, + typename VerticesSizeType, typename EdgeDescriptor > + struct undir_adj_matrix_in_edge_iter + : iterator_adaptor< undir_adj_matrix_in_edge_iter< VertexDescriptor, + MatrixIter, VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + { + typedef iterator_adaptor< + undir_adj_matrix_in_edge_iter< VertexDescriptor, MatrixIter, + VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + super_t; + + undir_adj_matrix_in_edge_iter() {} + + undir_adj_matrix_in_edge_iter(const MatrixIter& i, + const VertexDescriptor& src, const VerticesSizeType& n) + : super_t(i), m_src(src), m_inc(src), m_targ(0), m_n(n) + { + } + + void increment() + { + if (m_targ < m_src) // first half + { + ++this->base_reference(); + } + else if (m_targ < m_n - 1) + { // second half + ++m_inc; + this->base_reference() += m_inc; + } + else + { // past-the-end + this->base_reference() += m_n - m_src; + } + ++m_targ; + } + + inline EdgeDescriptor dereference() const + { + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_targ, + m_src, &get_edge_property(*this->base())); + } + + VertexDescriptor m_src, m_inc, m_targ; + VerticesSizeType m_n; + }; + + //======================================================================= + // Edge Iterator + + template < typename Directed, typename MatrixIter, + typename VerticesSizeType, typename EdgeDescriptor > + struct adj_matrix_edge_iter + : iterator_adaptor< adj_matrix_edge_iter< Directed, MatrixIter, + VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + { + typedef iterator_adaptor< adj_matrix_edge_iter< Directed, MatrixIter, + VerticesSizeType, EdgeDescriptor >, + MatrixIter, EdgeDescriptor, use_default, EdgeDescriptor, + std::ptrdiff_t > + super_t; + + adj_matrix_edge_iter() {} + + adj_matrix_edge_iter(const MatrixIter& i, const MatrixIter& start, + const VerticesSizeType& n) + : super_t(i), m_start(start), m_src(0), m_targ(0), m_n(n) + { + } + + void increment() + { + increment_dispatch(this->base_reference(), Directed()); + } + + void increment_dispatch(MatrixIter& i, directedS) + { + ++i; + if (m_targ == m_n - 1) + { + m_targ = 0; + ++m_src; + } + else + { + ++m_targ; + } + } + + void increment_dispatch(MatrixIter& i, undirectedS) + { + ++i; + if (m_targ == m_src) + { + m_targ = 0; + ++m_src; + } + else + { + ++m_targ; + } + } + + inline EdgeDescriptor dereference() const + { + return EdgeDescriptor(get_edge_exists(*this->base(), 0), m_src, + m_targ, &get_edge_property(*this->base())); + } + + MatrixIter m_start; + VerticesSizeType m_src, m_targ, m_n; + }; + +} // namespace detail + +//========================================================================= +// Adjacency Matrix Traits +template < typename Directed = directedS > class adjacency_matrix_traits +{ + typedef typename Directed::is_directed_t is_directed; + +public: + // The bidirectionalS tag is not allowed with the adjacency_matrix + // graph type. Instead, use directedS, which also provides the + // functionality required for a Bidirectional Graph (in_edges, + // in_degree, etc.). + BOOST_STATIC_ASSERT(!(is_same< Directed, bidirectionalS >::value)); + + typedef typename mpl::if_< is_directed, bidirectional_tag, + undirected_tag >::type directed_category; + + typedef disallow_parallel_edge_tag edge_parallel_category; + + typedef std::size_t vertex_descriptor; + + typedef detail::matrix_edge_desc_impl< directed_category, + vertex_descriptor > + edge_descriptor; +}; + +struct adjacency_matrix_class_tag +{ +}; + +struct adj_matrix_traversal_tag : public virtual adjacency_matrix_tag, + public virtual vertex_list_graph_tag, + public virtual incidence_graph_tag, + public virtual adjacency_graph_tag, + public virtual edge_list_graph_tag +{ +}; + +//========================================================================= +// Adjacency Matrix Class +template < typename Directed = directedS, typename VertexProperty = no_property, + typename EdgeProperty = no_property, typename GraphProperty = no_property, + typename Allocator = std::allocator< bool > > +class adjacency_matrix +{ + typedef adjacency_matrix self; + typedef adjacency_matrix_traits< Directed > Traits; + +public: + // The bidirectionalS tag is not allowed with the adjacency_matrix + // graph type. Instead, use directedS, which also provides the + // functionality required for a Bidirectional Graph (in_edges, + // in_degree, etc.). + BOOST_STATIC_ASSERT(!(is_same< Directed, bidirectionalS >::value)); + + typedef GraphProperty graph_property_type; + typedef typename lookup_one_property< GraphProperty, graph_bundle_t >::type + graph_bundled; + + typedef VertexProperty vertex_property_type; + typedef + typename lookup_one_property< VertexProperty, vertex_bundle_t >::type + vertex_bundled; + + typedef EdgeProperty edge_property_type; + typedef typename lookup_one_property< EdgeProperty, edge_bundle_t >::type + edge_bundled; + +public: // should be private + typedef + typename mpl::if_< typename has_property< edge_property_type >::type, + std::pair< bool, edge_property_type >, char >::type StoredEdge; +#if defined(BOOST_NO_STD_ALLOCATOR) + typedef std::vector< StoredEdge > Matrix; +#else +#if defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename Allocator::template rebind< StoredEdge >::other Alloc; +#else + typedef typename std::allocator_traits< Allocator >::template rebind_alloc< + StoredEdge > + Alloc; +#endif + typedef std::vector< StoredEdge, Alloc > Matrix; +#endif + typedef typename Matrix::iterator MatrixIter; + typedef typename Matrix::size_type size_type; + +public: + // Graph concept required types + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::directed_category directed_category; + typedef typename Traits::edge_parallel_category edge_parallel_category; + typedef adj_matrix_traversal_tag traversal_category; + + static vertex_descriptor null_vertex() + { + return (std::numeric_limits< vertex_descriptor >::max)(); + } + + // private: if friends worked, these would be private + + typedef detail::dir_adj_matrix_out_edge_iter< vertex_descriptor, MatrixIter, + size_type, edge_descriptor > + DirOutEdgeIter; + + typedef detail::undir_adj_matrix_out_edge_iter< vertex_descriptor, + MatrixIter, size_type, edge_descriptor > + UnDirOutEdgeIter; + + typedef typename mpl::if_< typename Directed::is_directed_t, DirOutEdgeIter, + UnDirOutEdgeIter >::type unfiltered_out_edge_iter; + + typedef detail::dir_adj_matrix_in_edge_iter< vertex_descriptor, MatrixIter, + size_type, edge_descriptor > + DirInEdgeIter; + + typedef detail::undir_adj_matrix_in_edge_iter< vertex_descriptor, + MatrixIter, size_type, edge_descriptor > + UnDirInEdgeIter; + + typedef typename mpl::if_< typename Directed::is_directed_t, DirInEdgeIter, + UnDirInEdgeIter >::type unfiltered_in_edge_iter; + + typedef detail::adj_matrix_edge_iter< Directed, MatrixIter, size_type, + edge_descriptor > + unfiltered_edge_iter; + +public: + // IncidenceGraph concept required types + typedef filter_iterator< detail::does_edge_exist, unfiltered_out_edge_iter > + out_edge_iterator; + + typedef size_type degree_size_type; + + // BidirectionalGraph required types + typedef filter_iterator< detail::does_edge_exist, unfiltered_in_edge_iter > + in_edge_iterator; + + // AdjacencyGraph required types + typedef typename adjacency_iterator_generator< self, vertex_descriptor, + out_edge_iterator >::type adjacency_iterator; + + // VertexListGraph required types + typedef size_type vertices_size_type; + typedef integer_range< vertex_descriptor > VertexList; + typedef typename VertexList::iterator vertex_iterator; + + // EdgeListGraph required types + typedef size_type edges_size_type; + typedef filter_iterator< detail::does_edge_exist, unfiltered_edge_iter > + edge_iterator; + + // PropertyGraph required types + typedef adjacency_matrix_class_tag graph_tag; + + // Constructor required by MutableGraph + adjacency_matrix( + vertices_size_type n_vertices, const GraphProperty& p = GraphProperty()) + : m_matrix(Directed::is_directed ? (n_vertices * n_vertices) + : (n_vertices * (n_vertices + 1) / 2)) + , m_vertex_set(0, n_vertices) + , m_vertex_properties(n_vertices) + , m_num_edges(0) + , m_property(p) + { + } + + template < typename EdgeIterator > + adjacency_matrix(EdgeIterator first, EdgeIterator last, + vertices_size_type n_vertices, const GraphProperty& p = GraphProperty()) + : m_matrix(Directed::is_directed ? (n_vertices * n_vertices) + : (n_vertices * (n_vertices + 1) / 2)) + , m_vertex_set(0, n_vertices) + , m_vertex_properties(n_vertices) + , m_num_edges(0) + , m_property(p) + { + for (; first != last; ++first) + { + add_edge(first->first, first->second, *this); + } + } + + template < typename EdgeIterator, typename EdgePropertyIterator > + adjacency_matrix(EdgeIterator first, EdgeIterator last, + EdgePropertyIterator ep_iter, vertices_size_type n_vertices, + const GraphProperty& p = GraphProperty()) + : m_matrix(Directed::is_directed ? (n_vertices * n_vertices) + : (n_vertices * (n_vertices + 1) / 2)) + , m_vertex_set(0, n_vertices) + , m_vertex_properties(n_vertices) + , m_num_edges(0) + , m_property(p) + { + for (; first != last; ++first, ++ep_iter) + { + add_edge(first->first, first->second, *ep_iter, *this); + } + } + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + // Directly access a vertex or edge bundle + vertex_bundled& operator[](vertex_descriptor v) + { + return get(vertex_bundle, *this, v); + } + + const vertex_bundled& operator[](vertex_descriptor v) const + { + return get(vertex_bundle, *this, v); + } + + edge_bundled& operator[](edge_descriptor e) + { + return get(edge_bundle, *this, e); + } + + const edge_bundled& operator[](edge_descriptor e) const + { + return get(edge_bundle, *this, e); + } + + graph_bundled& operator[](graph_bundle_t) { return get_property(*this); } + + const graph_bundled& operator[](graph_bundle_t) const + { + return get_property(*this); + } +#endif + + // private: if friends worked, these would be private + + typename Matrix::const_reference get_edge( + vertex_descriptor u, vertex_descriptor v) const + { + if (Directed::is_directed) + return m_matrix[u * m_vertex_set.size() + v]; + else + { + if (v > u) + std::swap(u, v); + return m_matrix[u * (u + 1) / 2 + v]; + } + } + typename Matrix::reference get_edge( + vertex_descriptor u, vertex_descriptor v) + { + if (Directed::is_directed) + return m_matrix[u * m_vertex_set.size() + v]; + else + { + if (v > u) + std::swap(u, v); + return m_matrix[u * (u + 1) / 2 + v]; + } + } + + Matrix m_matrix; + VertexList m_vertex_set; + std::vector< vertex_property_type > m_vertex_properties; + size_type m_num_edges; + graph_property_type m_property; +}; + +//========================================================================= +// Functions required by the AdjacencyMatrix concept + +template < typename D, typename VP, typename EP, typename GP, typename A > +std::pair< typename adjacency_matrix< D, VP, EP, GP, A >::edge_descriptor, + bool > +edge(typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor u, + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor v, + const adjacency_matrix< D, VP, EP, GP, A >& g) +{ + bool exists = detail::get_edge_exists(g.get_edge(u, v), 0); + typename adjacency_matrix< D, VP, EP, GP, A >::edge_descriptor e( + exists, u, v, &detail::get_edge_property(g.get_edge(u, v))); + return std::make_pair(e, exists); +} + +//========================================================================= +// Functions required by the IncidenceGraph concept + +// O(1) +template < typename VP, typename EP, typename GP, typename A > +std::pair< + typename adjacency_matrix< directedS, VP, EP, GP, A >::out_edge_iterator, + typename adjacency_matrix< directedS, VP, EP, GP, A >::out_edge_iterator > +out_edges( + typename adjacency_matrix< directedS, VP, EP, GP, A >::vertex_descriptor u, + const adjacency_matrix< directedS, VP, EP, GP, A >& g_) +{ + typedef adjacency_matrix< directedS, VP, EP, GP, A > Graph; + Graph& g = const_cast< Graph& >(g_); + typename Graph::vertices_size_type offset = u * g.m_vertex_set.size(); + typename Graph::MatrixIter f = g.m_matrix.begin() + offset; + typename Graph::MatrixIter l = f + g.m_vertex_set.size(); + typename Graph::unfiltered_out_edge_iter first(f, u, g.m_vertex_set.size()), + last(l, u, g.m_vertex_set.size()); + detail::does_edge_exist pred; + typedef typename Graph::out_edge_iterator out_edge_iterator; + return std::make_pair(out_edge_iterator(pred, first, last), + out_edge_iterator(pred, last, last)); +} + +// O(1) +template < typename VP, typename EP, typename GP, typename A > +std::pair< + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::out_edge_iterator, + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::out_edge_iterator > +out_edges( + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::vertex_descriptor + u, + const adjacency_matrix< undirectedS, VP, EP, GP, A >& g_) +{ + typedef adjacency_matrix< undirectedS, VP, EP, GP, A > Graph; + Graph& g = const_cast< Graph& >(g_); + typename Graph::vertices_size_type offset = u * (u + 1) / 2; + typename Graph::MatrixIter f = g.m_matrix.begin() + offset; + typename Graph::MatrixIter l = g.m_matrix.end(); + + typename Graph::unfiltered_out_edge_iter first(f, u, g.m_vertex_set.size()), + last(l, u, g.m_vertex_set.size()); + + detail::does_edge_exist pred; + typedef typename Graph::out_edge_iterator out_edge_iterator; + return std::make_pair(out_edge_iterator(pred, first, last), + out_edge_iterator(pred, last, last)); +} + +// O(N) +template < typename D, typename VP, typename EP, typename GP, typename A > +typename adjacency_matrix< D, VP, EP, GP, A >::degree_size_type out_degree( + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor u, + const adjacency_matrix< D, VP, EP, GP, A >& g) +{ + typename adjacency_matrix< D, VP, EP, GP, A >::degree_size_type n = 0; + typename adjacency_matrix< D, VP, EP, GP, A >::out_edge_iterator f, l; + for (boost::tie(f, l) = out_edges(u, g); f != l; ++f) + ++n; + return n; +} + +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Dir, typename Vertex > +typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor source( + const detail::matrix_edge_desc_impl< Dir, Vertex >& e, + const adjacency_matrix< D, VP, EP, GP, A >&) +{ + return e.m_source; +} + +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Dir, typename Vertex > +typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor target( + const detail::matrix_edge_desc_impl< Dir, Vertex >& e, + const adjacency_matrix< D, VP, EP, GP, A >&) +{ + return e.m_target; +} + +//========================================================================= +// Functions required by the BidirectionalGraph concept + +// O(1) +template < typename VP, typename EP, typename GP, typename A > +std::pair< + typename adjacency_matrix< directedS, VP, EP, GP, A >::in_edge_iterator, + typename adjacency_matrix< directedS, VP, EP, GP, A >::in_edge_iterator > +in_edges( + typename adjacency_matrix< directedS, VP, EP, GP, A >::vertex_descriptor u, + const adjacency_matrix< directedS, VP, EP, GP, A >& g_) +{ + typedef adjacency_matrix< directedS, VP, EP, GP, A > Graph; + Graph& g = const_cast< Graph& >(g_); + typename Graph::MatrixIter f = g.m_matrix.begin() + u; + typename Graph::MatrixIter l = g.m_matrix.end(); + typename Graph::unfiltered_in_edge_iter first( + f, l, u, g.m_vertex_set.size()), + last(l, l, u, g.m_vertex_set.size()); + detail::does_edge_exist pred; + typedef typename Graph::in_edge_iterator in_edge_iterator; + return std::make_pair(in_edge_iterator(pred, first, last), + in_edge_iterator(pred, last, last)); +} + +// O(1) +template < typename VP, typename EP, typename GP, typename A > +std::pair< + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::in_edge_iterator, + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::in_edge_iterator > +in_edges( + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::vertex_descriptor + u, + const adjacency_matrix< undirectedS, VP, EP, GP, A >& g_) +{ + typedef adjacency_matrix< undirectedS, VP, EP, GP, A > Graph; + Graph& g = const_cast< Graph& >(g_); + typename Graph::vertices_size_type offset = u * (u + 1) / 2; + typename Graph::MatrixIter f = g.m_matrix.begin() + offset; + typename Graph::MatrixIter l = g.m_matrix.end(); + + typename Graph::unfiltered_in_edge_iter first(f, u, g.m_vertex_set.size()), + last(l, u, g.m_vertex_set.size()); + + detail::does_edge_exist pred; + typedef typename Graph::in_edge_iterator in_edge_iterator; + return std::make_pair(in_edge_iterator(pred, first, last), + in_edge_iterator(pred, last, last)); +} + +// O(N) +template < typename D, typename VP, typename EP, typename GP, typename A > +typename adjacency_matrix< D, VP, EP, GP, A >::degree_size_type in_degree( + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor u, + const adjacency_matrix< D, VP, EP, GP, A >& g) +{ + typename adjacency_matrix< D, VP, EP, GP, A >::degree_size_type n = 0; + typename adjacency_matrix< D, VP, EP, GP, A >::in_edge_iterator f, l; + for (boost::tie(f, l) = in_edges(u, g); f != l; ++f) + ++n; + return n; +} + +//========================================================================= +// Functions required by the AdjacencyGraph concept + +template < typename D, typename VP, typename EP, typename GP, typename A > +std::pair< typename adjacency_matrix< D, VP, EP, GP, A >::adjacency_iterator, + typename adjacency_matrix< D, VP, EP, GP, A >::adjacency_iterator > +adjacent_vertices( + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor u, + const adjacency_matrix< D, VP, EP, GP, A >& g_) +{ + typedef adjacency_matrix< D, VP, EP, GP, A > Graph; + const Graph& cg = static_cast< const Graph& >(g_); + Graph& g = const_cast< Graph& >(cg); + typedef typename Graph::adjacency_iterator adjacency_iterator; + typename Graph::out_edge_iterator first, last; + boost::tie(first, last) = out_edges(u, g); + return std::make_pair( + adjacency_iterator(first, &g), adjacency_iterator(last, &g)); +} + +//========================================================================= +// Functions required by the VertexListGraph concept + +template < typename D, typename VP, typename EP, typename GP, typename A > +std::pair< typename adjacency_matrix< D, VP, EP, GP, A >::vertex_iterator, + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_iterator > +vertices(const adjacency_matrix< D, VP, EP, GP, A >& g_) +{ + typedef adjacency_matrix< D, VP, EP, GP, A > Graph; + Graph& g = const_cast< Graph& >(g_); + return std::make_pair(g.m_vertex_set.begin(), g.m_vertex_set.end()); +} + +template < typename D, typename VP, typename EP, typename GP, typename A > +typename adjacency_matrix< D, VP, EP, GP, A >::vertices_size_type num_vertices( + const adjacency_matrix< D, VP, EP, GP, A >& g) +{ + return g.m_vertex_set.size(); +} + +//========================================================================= +// Functions required by the EdgeListGraph concept + +template < typename D, typename VP, typename EP, typename GP, typename A > +std::pair< typename adjacency_matrix< D, VP, EP, GP, A >::edge_iterator, + typename adjacency_matrix< D, VP, EP, GP, A >::edge_iterator > +edges(const adjacency_matrix< D, VP, EP, GP, A >& g_) +{ + typedef adjacency_matrix< D, VP, EP, GP, A > Graph; + Graph& g = const_cast< Graph& >(g_); + + typename Graph::unfiltered_edge_iter first( + g.m_matrix.begin(), g.m_matrix.begin(), g.m_vertex_set.size()), + last(g.m_matrix.end(), g.m_matrix.begin(), g.m_vertex_set.size()); + detail::does_edge_exist pred; + typedef typename Graph::edge_iterator edge_iterator; + return std::make_pair( + edge_iterator(pred, first, last), edge_iterator(pred, last, last)); +} + +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A > +typename adjacency_matrix< D, VP, EP, GP, A >::edges_size_type num_edges( + const adjacency_matrix< D, VP, EP, GP, A >& g) +{ + return g.m_num_edges; +} + +//========================================================================= +// Functions required by the MutableGraph concept + +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A, + typename EP2 > +std::pair< typename adjacency_matrix< D, VP, EP, GP, A >::edge_descriptor, + bool > +add_edge(typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor u, + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor v, + const EP2& ep, adjacency_matrix< D, VP, EP, GP, A >& g) +{ + typedef typename adjacency_matrix< D, VP, EP, GP, A >::edge_descriptor + edge_descriptor; + if (detail::get_edge_exists(g.get_edge(u, v), 0) == false) + { + ++(g.m_num_edges); + detail::set_edge_property(g.get_edge(u, v), EP(ep), 0); + detail::set_edge_exists(g.get_edge(u, v), true, 0); + return std::make_pair(edge_descriptor(true, u, v, + &detail::get_edge_property(g.get_edge(u, v))), + true); + } + else + return std::make_pair(edge_descriptor(true, u, v, + &detail::get_edge_property(g.get_edge(u, v))), + false); +} +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A > +std::pair< typename adjacency_matrix< D, VP, EP, GP, A >::edge_descriptor, + bool > +add_edge(typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor u, + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor v, + adjacency_matrix< D, VP, EP, GP, A >& g) +{ + EP ep; + return add_edge(u, v, ep, g); +} + +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A > +void remove_edge( + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor u, + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor v, + adjacency_matrix< D, VP, EP, GP, A >& g) +{ + // Don'remove the edge unless it already exists. + if (detail::get_edge_exists(g.get_edge(u, v), 0)) + { + --(g.m_num_edges); + detail::set_edge_exists(g.get_edge(u, v), false, 0); + } +} + +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A > +void remove_edge( + typename adjacency_matrix< D, VP, EP, GP, A >::edge_descriptor e, + adjacency_matrix< D, VP, EP, GP, A >& g) +{ + remove_edge(source(e, g), target(e, g), g); +} + +template < typename D, typename VP, typename EP, typename GP, typename A > +inline typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor +add_vertex(adjacency_matrix< D, VP, EP, GP, A >& g) +{ + // UNDER CONSTRUCTION + BOOST_ASSERT(false); + return *vertices(g).first; +} + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename VP2 > +inline typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor +add_vertex(const VP2& /*vp*/, adjacency_matrix< D, VP, EP, GP, A >& g) +{ + // UNDER CONSTRUCTION + BOOST_ASSERT(false); + return *vertices(g).first; +} + +template < typename D, typename VP, typename EP, typename GP, typename A > +inline void remove_vertex( + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor /*u*/, + adjacency_matrix< D, VP, EP, GP, A >& /*g*/) +{ + // UNDER CONSTRUCTION + BOOST_ASSERT(false); +} + +// O(V) +template < typename VP, typename EP, typename GP, typename A > +void clear_vertex( + typename adjacency_matrix< directedS, VP, EP, GP, A >::vertex_descriptor u, + adjacency_matrix< directedS, VP, EP, GP, A >& g) +{ + typename adjacency_matrix< directedS, VP, EP, GP, A >::vertex_iterator vi, + vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + remove_edge(u, *vi, g); + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + remove_edge(*vi, u, g); +} + +// O(V) +template < typename VP, typename EP, typename GP, typename A > +void clear_vertex( + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::vertex_descriptor + u, + adjacency_matrix< undirectedS, VP, EP, GP, A >& g) +{ + typename adjacency_matrix< undirectedS, VP, EP, GP, A >::vertex_iterator vi, + vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + remove_edge(u, *vi, g); +} + +//========================================================================= +// Functions required by the PropertyGraph concept + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Prop, typename Kind > +struct adj_mat_pm_helper; + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Prop > +struct adj_mat_pm_helper< D, VP, EP, GP, A, Prop, vertex_property_tag > +{ + typedef typename graph_traits< + adjacency_matrix< D, VP, EP, GP, A > >::vertex_descriptor arg_type; + typedef typed_identity_property_map< arg_type > vi_map_type; + typedef iterator_property_map< typename std::vector< VP >::iterator, + vi_map_type > + all_map_type; + typedef iterator_property_map< typename std::vector< VP >::const_iterator, + vi_map_type > + all_map_const_type; + typedef transform_value_property_map< + detail::lookup_one_property_f< VP, Prop >, all_map_type > + type; + typedef transform_value_property_map< + detail::lookup_one_property_f< const VP, Prop >, all_map_const_type > + const_type; + typedef typename property_traits< type >::reference single_nonconst_type; + typedef typename property_traits< const_type >::reference single_const_type; + + static type get_nonconst(adjacency_matrix< D, VP, EP, GP, A >& g, Prop prop) + { + return type( + prop, all_map_type(g.m_vertex_properties.begin(), vi_map_type())); + } + + static const_type get_const( + const adjacency_matrix< D, VP, EP, GP, A >& g, Prop prop) + { + return const_type(prop, + all_map_const_type(g.m_vertex_properties.begin(), vi_map_type())); + } + + static single_nonconst_type get_nonconst_one( + adjacency_matrix< D, VP, EP, GP, A >& g, Prop prop, arg_type v) + { + return lookup_one_property< VP, Prop >::lookup( + g.m_vertex_properties[v], prop); + } + + static single_const_type get_const_one( + const adjacency_matrix< D, VP, EP, GP, A >& g, Prop prop, arg_type v) + { + return lookup_one_property< const VP, Prop >::lookup( + g.m_vertex_properties[v], prop); + } +}; + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +struct adj_mat_pm_helper< D, VP, EP, GP, A, Tag, edge_property_tag > +{ + typedef typename graph_traits< + adjacency_matrix< D, VP, EP, GP, A > >::edge_descriptor edge_descriptor; + + template < typename IsConst > struct lookup_property_from_edge + { + Tag tag; + lookup_property_from_edge(Tag tag) : tag(tag) {} + typedef typename boost::mpl::if_< IsConst, const EP, EP >::type + ep_type_nonref; + typedef ep_type_nonref& ep_type; + typedef typename lookup_one_property< ep_type_nonref, Tag >::type& + result_type; + result_type operator()(edge_descriptor e) const + { + return lookup_one_property< ep_type_nonref, Tag >::lookup( + *static_cast< ep_type_nonref* >(e.get_property()), tag); + } + }; + + typedef function_property_map< + lookup_property_from_edge< boost::mpl::false_ >, + typename graph_traits< + adjacency_matrix< D, VP, EP, GP, A > >::edge_descriptor > + type; + typedef function_property_map< + lookup_property_from_edge< boost::mpl::true_ >, + typename graph_traits< + adjacency_matrix< D, VP, EP, GP, A > >::edge_descriptor > + const_type; + typedef edge_descriptor arg_type; + typedef + typename lookup_property_from_edge< boost::mpl::false_ >::result_type + single_nonconst_type; + typedef typename lookup_property_from_edge< boost::mpl::true_ >::result_type + single_const_type; + + static type get_nonconst(adjacency_matrix< D, VP, EP, GP, A >& /* g */, Tag tag) + { + return type(tag); + } + + static const_type get_const( + const adjacency_matrix< D, VP, EP, GP, A >& /* g */, Tag tag) + { + return const_type(tag); + } + + static single_nonconst_type get_nonconst_one( + adjacency_matrix< D, VP, EP, GP, A >& /* g */, Tag tag, edge_descriptor e) + { + return lookup_one_property< EP, Tag >::lookup( + *static_cast< EP* >(e.get_property()), tag); + } + + static single_const_type get_const_one( + const adjacency_matrix< D, VP, EP, GP, A >& /* g */, Tag tag, + edge_descriptor e) + { + return lookup_one_property< const EP, Tag >::lookup( + *static_cast< const EP* >(e.get_property()), tag); + } +}; + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +struct property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag > +: adj_mat_pm_helper< D, VP, EP, GP, A, Tag, + typename detail::property_kind_from_graph< + adjacency_matrix< D, VP, EP, GP, A >, Tag >::type > +{ +}; + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +typename property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag >::type get( + Tag tag, adjacency_matrix< D, VP, EP, GP, A >& g) +{ + return property_map< adjacency_matrix< D, VP, EP, GP, A >, + Tag >::get_nonconst(g, tag); +} + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +typename property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag >::const_type +get(Tag tag, const adjacency_matrix< D, VP, EP, GP, A >& g) +{ + return property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag >::get_const( + g, tag); +} + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +typename property_map< adjacency_matrix< D, VP, EP, GP, A >, + Tag >::single_nonconst_type +get(Tag tag, adjacency_matrix< D, VP, EP, GP, A >& g, + typename property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag >::arg_type + a) +{ + return property_map< adjacency_matrix< D, VP, EP, GP, A >, + Tag >::get_nonconst_one(g, tag, a); +} + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +typename property_map< adjacency_matrix< D, VP, EP, GP, A >, + Tag >::single_const_type +get(Tag tag, const adjacency_matrix< D, VP, EP, GP, A >& g, + typename property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag >::arg_type + a) +{ + return property_map< adjacency_matrix< D, VP, EP, GP, A >, + Tag >::get_const_one(g, tag, a); +} + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +void put(Tag tag, adjacency_matrix< D, VP, EP, GP, A >& g, + typename property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag >::arg_type + a, + typename property_map< adjacency_matrix< D, VP, EP, GP, A >, + Tag >::single_const_type val) +{ + property_map< adjacency_matrix< D, VP, EP, GP, A >, Tag >::get_nonconst_one( + g, tag, a) + = val; +} + +// O(1) +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag, typename Value > +inline void set_property( + adjacency_matrix< D, VP, EP, GP, A >& g, Tag tag, const Value& value) +{ + get_property_value(g.m_property, tag) = value; +} + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +inline + typename graph_property< adjacency_matrix< D, VP, EP, GP, A >, Tag >::type& + get_property(adjacency_matrix< D, VP, EP, GP, A >& g, Tag tag) +{ + return get_property_value(g.m_property, tag); +} + +template < typename D, typename VP, typename EP, typename GP, typename A, + typename Tag > +inline const typename graph_property< adjacency_matrix< D, VP, EP, GP, A >, + Tag >::type& +get_property(const adjacency_matrix< D, VP, EP, GP, A >& g, Tag tag) +{ + return get_property_value(g.m_property, tag); +} + +//========================================================================= +// Vertex Property Map + +template < typename D, typename VP, typename EP, typename GP, typename A > +struct property_map< adjacency_matrix< D, VP, EP, GP, A >, vertex_index_t > +{ + typedef + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor Vertex; + typedef typed_identity_property_map< Vertex > type; + typedef type const_type; +}; + +template < typename D, typename VP, typename EP, typename GP, typename A > +typename property_map< adjacency_matrix< D, VP, EP, GP, A >, + vertex_index_t >::const_type +get(vertex_index_t, adjacency_matrix< D, VP, EP, GP, A >&) +{ + return typename property_map< adjacency_matrix< D, VP, EP, GP, A >, + vertex_index_t >::const_type(); +} + +template < typename D, typename VP, typename EP, typename GP, typename A > +typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor get( + vertex_index_t, adjacency_matrix< D, VP, EP, GP, A >&, + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor v) +{ + return v; +} + +template < typename D, typename VP, typename EP, typename GP, typename A > +typename property_map< adjacency_matrix< D, VP, EP, GP, A >, + vertex_index_t >::const_type +get(vertex_index_t, const adjacency_matrix< D, VP, EP, GP, A >&) +{ + return typename property_map< adjacency_matrix< D, VP, EP, GP, A >, + vertex_index_t >::const_type(); +} + +template < typename D, typename VP, typename EP, typename GP, typename A > +typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor get( + vertex_index_t, const adjacency_matrix< D, VP, EP, GP, A >&, + typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor v) +{ + return v; +} + +//========================================================================= +// Other Functions + +template < typename D, typename VP, typename EP, typename GP, typename A > +typename adjacency_matrix< D, VP, EP, GP, A >::vertex_descriptor vertex( + typename adjacency_matrix< D, VP, EP, GP, A >::vertices_size_type n, + const adjacency_matrix< D, VP, EP, GP, A >&) +{ + return n; +} + +template < typename D, typename VP, typename EP, typename GP, typename A > +struct graph_mutability_traits< adjacency_matrix< D, VP, EP, GP, A > > +{ + typedef mutable_edge_property_graph_tag category; +}; + +} // namespace boost + +#endif // BOOST_ADJACENCY_MATRIX_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/astar_search.hpp b/contrib/restricted/boost/graph/include/boost/graph/astar_search.hpp new file mode 100644 index 0000000000..02f4b1cb49 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/astar_search.hpp @@ -0,0 +1,655 @@ + + +// +//======================================================================= +// Copyright (c) 2004 Kristopher Beevers +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_ASTAR_SEARCH_HPP +#define BOOST_GRAPH_ASTAR_SEARCH_HPP + +#include <functional> +#include <vector> +#include <boost/limits.hpp> +#include <boost/throw_exception.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/graph/relax.hpp> +#include <boost/graph/exception.hpp> +#include <boost/graph/breadth_first_search.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/detail/d_ary_heap.hpp> +#include <boost/graph/property_maps/constant_property_map.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/property_map/vector_property_map.hpp> +#include <boost/property_map/function_property_map.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +template < class Heuristic, class Graph > struct AStarHeuristicConcept +{ + void constraints() + { + BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Heuristic >)); + h(u); + } + Heuristic h; + typename graph_traits< Graph >::vertex_descriptor u; +}; + +template < class Graph, class CostType > class astar_heuristic +{ +public: + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef Vertex argument_type; + typedef CostType result_type; + astar_heuristic() {} + CostType operator()(Vertex u) { return static_cast< CostType >(0); } +}; + +template < class Visitor, class Graph > struct AStarVisitorConcept +{ + void constraints() + { + BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Visitor >)); + vis.initialize_vertex(u, g); + vis.discover_vertex(u, g); + vis.examine_vertex(u, g); + vis.examine_edge(e, g); + vis.edge_relaxed(e, g); + vis.edge_not_relaxed(e, g); + vis.black_target(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename graph_traits< Graph >::vertex_descriptor u; + typename graph_traits< Graph >::edge_descriptor e; +}; + +template < class Visitors = null_visitor > +class astar_visitor : public bfs_visitor< Visitors > +{ +public: + astar_visitor() {} + astar_visitor(Visitors vis) : bfs_visitor< Visitors >(vis) {} + + template < class Edge, class Graph > + void edge_relaxed(Edge e, const Graph& g) + { + invoke_visitors(this->m_vis, e, g, on_edge_relaxed()); + } + template < class Edge, class Graph > + void edge_not_relaxed(Edge e, const Graph& g) + { + invoke_visitors(this->m_vis, e, g, on_edge_not_relaxed()); + } + +private: + template < class Edge, class Graph > void tree_edge(Edge e, const Graph& g) + { + } + template < class Edge, class Graph > + void non_tree_edge(Edge e, const Graph& g) + { + } +}; +template < class Visitors > +astar_visitor< Visitors > make_astar_visitor(Visitors vis) +{ + return astar_visitor< Visitors >(vis); +} +typedef astar_visitor<> default_astar_visitor; + +namespace detail +{ + + template < class AStarHeuristic, class UniformCostVisitor, + class UpdatableQueue, class PredecessorMap, class CostMap, + class DistanceMap, class WeightMap, class ColorMap, + class BinaryFunction, class BinaryPredicate > + struct astar_bfs_visitor + { + + typedef typename property_traits< CostMap >::value_type C; + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + typedef + typename property_traits< DistanceMap >::value_type distance_type; + + astar_bfs_visitor(AStarHeuristic h, UniformCostVisitor vis, + UpdatableQueue& Q, PredecessorMap p, CostMap c, DistanceMap d, + WeightMap w, ColorMap col, BinaryFunction combine, + BinaryPredicate compare, C zero) + : m_h(h) + , m_vis(vis) + , m_Q(Q) + , m_predecessor(p) + , m_cost(c) + , m_distance(d) + , m_weight(w) + , m_color(col) + , m_combine(combine) + , m_compare(compare) + , m_zero(zero) + { + } + + template < class Vertex, class Graph > + void initialize_vertex(Vertex u, const Graph& g) + { + m_vis.initialize_vertex(u, g); + } + template < class Vertex, class Graph > + void discover_vertex(Vertex u, const Graph& g) + { + m_vis.discover_vertex(u, g); + } + template < class Vertex, class Graph > + void examine_vertex(Vertex u, const Graph& g) + { + m_vis.examine_vertex(u, g); + } + template < class Vertex, class Graph > + void finish_vertex(Vertex u, const Graph& g) + { + m_vis.finish_vertex(u, g); + } + template < class Edge, class Graph > + void examine_edge(Edge e, const Graph& g) + { + if (m_compare(get(m_weight, e), m_zero)) + BOOST_THROW_EXCEPTION(negative_edge()); + m_vis.examine_edge(e, g); + } + template < class Edge, class Graph > + void non_tree_edge(Edge, const Graph&) + { + } + + template < class Edge, class Graph > + void tree_edge(Edge e, const Graph& g) + { + using boost::get; + bool m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + + if (m_decreased) + { + m_vis.edge_relaxed(e, g); + put(m_cost, target(e, g), + m_combine( + get(m_distance, target(e, g)), m_h(target(e, g)))); + } + else + m_vis.edge_not_relaxed(e, g); + } + + template < class Edge, class Graph > + void gray_target(Edge e, const Graph& g) + { + using boost::get; + bool m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + + if (m_decreased) + { + put(m_cost, target(e, g), + m_combine( + get(m_distance, target(e, g)), m_h(target(e, g)))); + m_Q.update(target(e, g)); + m_vis.edge_relaxed(e, g); + } + else + m_vis.edge_not_relaxed(e, g); + } + + template < class Edge, class Graph > + void black_target(Edge e, const Graph& g) + { + using boost::get; + bool m_decreased = relax(e, g, m_weight, m_predecessor, m_distance, + m_combine, m_compare); + + if (m_decreased) + { + m_vis.edge_relaxed(e, g); + put(m_cost, target(e, g), + m_combine( + get(m_distance, target(e, g)), m_h(target(e, g)))); + m_Q.push(target(e, g)); + put(m_color, target(e, g), Color::gray()); + m_vis.black_target(e, g); + } + else + m_vis.edge_not_relaxed(e, g); + } + + AStarHeuristic m_h; + UniformCostVisitor m_vis; + UpdatableQueue& m_Q; + PredecessorMap m_predecessor; + CostMap m_cost; + DistanceMap m_distance; + WeightMap m_weight; + ColorMap m_color; + BinaryFunction m_combine; + BinaryPredicate m_compare; + C m_zero; + }; + +} // namespace detail + +template < typename VertexListGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, typename CostMap, + typename DistanceMap, typename WeightMap, typename ColorMap, + typename VertexIndexMap, typename CompareFunction, typename CombineFunction, + typename CostInf, typename CostZero > +inline void astar_search_no_init(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, PredecessorMap predecessor, + CostMap cost, DistanceMap distance, WeightMap weight, ColorMap color, + VertexIndexMap index_map, CompareFunction compare, CombineFunction combine, + CostInf /*inf*/, CostZero zero) +{ + typedef typename graph_traits< VertexListGraph >::vertex_descriptor Vertex; + typedef boost::vector_property_map< std::size_t, VertexIndexMap > + IndexInHeapMap; + IndexInHeapMap index_in_heap(index_map); + typedef d_ary_heap_indirect< Vertex, 4, IndexInHeapMap, CostMap, + CompareFunction > + MutableQueue; + MutableQueue Q(cost, index_in_heap, compare); + + detail::astar_bfs_visitor< AStarHeuristic, AStarVisitor, MutableQueue, + PredecessorMap, CostMap, DistanceMap, WeightMap, ColorMap, + CombineFunction, CompareFunction > + bfs_vis(h, vis, Q, predecessor, cost, distance, weight, color, combine, + compare, zero); + + breadth_first_visit(g, s, Q, bfs_vis, color); +} + +namespace graph_detail +{ + template < typename A, typename B > struct select1st + { + typedef std::pair< A, B > argument_type; + typedef A result_type; + A operator()(const std::pair< A, B >& p) const { return p.first; } + }; +} + +template < typename VertexListGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, typename CostMap, + typename DistanceMap, typename WeightMap, typename CompareFunction, + typename CombineFunction, typename CostInf, typename CostZero > +inline void astar_search_no_init_tree(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, PredecessorMap predecessor, + CostMap cost, DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, CostInf /*inf*/, + CostZero zero) +{ + typedef typename graph_traits< VertexListGraph >::vertex_descriptor Vertex; + typedef typename property_traits< DistanceMap >::value_type Distance; + typedef d_ary_heap_indirect< std::pair< Distance, Vertex >, 4, + null_property_map< std::pair< Distance, Vertex >, std::size_t >, + function_property_map< graph_detail::select1st< Distance, Vertex >, + std::pair< Distance, Vertex > >, + CompareFunction > + MutableQueue; + MutableQueue Q(make_function_property_map< std::pair< Distance, Vertex > >( + graph_detail::select1st< Distance, Vertex >()), + null_property_map< std::pair< Distance, Vertex >, std::size_t >(), + compare); + + vis.discover_vertex(s, g); + Q.push(std::make_pair(get(cost, s), s)); + while (!Q.empty()) + { + Vertex v; + Distance v_rank; + boost::tie(v_rank, v) = Q.top(); + Q.pop(); + vis.examine_vertex(v, g); + BGL_FORALL_OUTEDGES_T(v, e, g, VertexListGraph) + { + Vertex w = target(e, g); + vis.examine_edge(e, g); + Distance e_weight = get(weight, e); + if (compare(e_weight, zero)) + BOOST_THROW_EXCEPTION(negative_edge()); + bool decreased + = relax(e, g, weight, predecessor, distance, combine, compare); + if (decreased) + { + vis.edge_relaxed(e, g); + Distance w_rank = combine(get(distance, w), h(w)); + put(cost, w, w_rank); + vis.discover_vertex(w, g); + Q.push(std::make_pair(w_rank, w)); + } + else + { + vis.edge_not_relaxed(e, g); + } + } + vis.finish_vertex(v, g); + } +} + +// Non-named parameter interface +template < typename VertexListGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, typename CostMap, + typename DistanceMap, typename WeightMap, typename VertexIndexMap, + typename ColorMap, typename CompareFunction, typename CombineFunction, + typename CostInf, typename CostZero > +inline void astar_search(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, PredecessorMap predecessor, + CostMap cost, DistanceMap distance, WeightMap weight, + VertexIndexMap index_map, ColorMap color, CompareFunction compare, + CombineFunction combine, CostInf inf, CostZero zero) +{ + + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + typename graph_traits< VertexListGraph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + put(color, *ui, Color::white()); + put(distance, *ui, inf); + put(cost, *ui, inf); + put(predecessor, *ui, *ui); + vis.initialize_vertex(*ui, g); + } + put(distance, s, zero); + put(cost, s, h(s)); + + astar_search_no_init(g, s, h, vis, predecessor, cost, distance, weight, + color, index_map, compare, combine, inf, zero); +} + +// Non-named parameter interface +template < typename VertexListGraph, typename AStarHeuristic, + typename AStarVisitor, typename PredecessorMap, typename CostMap, + typename DistanceMap, typename WeightMap, typename CompareFunction, + typename CombineFunction, typename CostInf, typename CostZero > +inline void astar_search_tree(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, AStarVisitor vis, PredecessorMap predecessor, + CostMap cost, DistanceMap distance, WeightMap weight, + CompareFunction compare, CombineFunction combine, CostInf inf, + CostZero zero) +{ + + typename graph_traits< VertexListGraph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + put(distance, *ui, inf); + put(cost, *ui, inf); + put(predecessor, *ui, *ui); + vis.initialize_vertex(*ui, g); + } + put(distance, s, zero); + put(cost, s, h(s)); + + astar_search_no_init_tree(g, s, h, vis, predecessor, cost, distance, weight, + compare, combine, inf, zero); +} + +// Named parameter interfaces +template < typename VertexListGraph, typename AStarHeuristic, typename P, + typename T, typename R > +void astar_search(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params< P, T, R >& params) +{ + using namespace boost::graph::keywords; + typedef bgl_named_params< P, T, R > params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + + // Distance type is the value type of the distance map if there is one, + // otherwise the value type of the weight map. + typedef + typename boost::detail::override_const_property_result< arg_pack_type, + boost::graph::keywords::tag::weight_map, edge_weight_t, + VertexListGraph >::type weight_map_type; + typedef typename boost::property_traits< weight_map_type >::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max< D >()]; + const D zero_actual = D(); + const D zero_d = arg_pack[_distance_zero | zero_actual]; + null_visitor null_vis; + astar_visitor< null_visitor > default_visitor(null_vis); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::visitor, dummy_property_map& >::type vis + = arg_pack[_visitor | default_visitor]; + dummy_property_map dummy_prop; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::predecessor_map, + dummy_property_map& >::type pred_map + = arg_pack[_predecessor_map | dummy_prop]; + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::rank_map, D > + rank_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::rank_map, D >::map_type r_map + = rank_map_gen(g, arg_pack); + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::distance_map, D > + dist_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::distance_map, D >::map_type dist_map + = dist_map_gen(g, arg_pack); + weight_map_type w_map = detail::override_const_property( + arg_pack, _weight_map, g, edge_weight); + typename boost::detail::override_const_property_result< arg_pack_type, + boost::graph::keywords::tag::vertex_index_map, vertex_index_t, + VertexListGraph >::type v_i_map + = detail::override_const_property( + arg_pack, _vertex_index_map, g, vertex_index); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::color_map, + boost::default_color_type >::map_type c_map + = boost::detail::make_color_map_from_arg_pack(g, arg_pack); + std::less< D > default_compare; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_compare, std::less< D >& >::type + dist_comp + = arg_pack[_distance_compare | default_compare]; + closed_plus< D > default_combine(inf); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_combine, closed_plus< D >& >::type + dist_comb + = arg_pack[_distance_combine | default_combine]; + astar_search(g, s, h, vis, pred_map, r_map, dist_map, w_map, v_i_map, c_map, + dist_comp, dist_comb, inf, zero_d); +} + +template < typename VertexListGraph, typename AStarHeuristic, typename P, + typename T, typename R > +void astar_search_tree(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params< P, T, R >& params) +{ + using namespace boost::graph::keywords; + typedef bgl_named_params< P, T, R > params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + + // Distance type is the value type of the distance map if there is one, + // otherwise the value type of the weight map. + typedef + typename boost::detail::override_const_property_result< arg_pack_type, + boost::graph::keywords::tag::weight_map, edge_weight_t, + VertexListGraph >::type weight_map_type; + typedef typename boost::property_traits< weight_map_type >::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max< D >()]; + const D zero_actual = D(); + const D zero_d = arg_pack[_distance_zero | zero_actual]; + null_visitor null_vis; + astar_visitor< null_visitor > default_visitor(null_vis); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::visitor, dummy_property_map& >::type vis + = arg_pack[_visitor | default_visitor]; + dummy_property_map dummy_prop; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::predecessor_map, + dummy_property_map& >::type pred_map + = arg_pack[_predecessor_map | dummy_prop]; + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::rank_map, D > + rank_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::rank_map, D >::map_type r_map + = rank_map_gen(g, arg_pack); + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::distance_map, D > + dist_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::distance_map, D >::map_type dist_map + = dist_map_gen(g, arg_pack); + weight_map_type w_map = detail::override_const_property( + arg_pack, _weight_map, g, edge_weight); + std::less< D > default_compare; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_compare, std::less< D >& >::type + dist_comp + = arg_pack[_distance_compare | default_compare]; + closed_plus< D > default_combine(inf); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_combine, closed_plus< D >& >::type + dist_comb + = arg_pack[_distance_combine | default_combine]; + astar_search_tree(g, s, h, vis, pred_map, r_map, dist_map, w_map, dist_comp, + dist_comb, inf, zero_d); +} + +template < typename VertexListGraph, typename AStarHeuristic, typename P, + typename T, typename R > +void astar_search_no_init(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params< P, T, R >& params) +{ + using namespace boost::graph::keywords; + typedef bgl_named_params< P, T, R > params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + typedef + typename boost::detail::override_const_property_result< arg_pack_type, + boost::graph::keywords::tag::weight_map, edge_weight_t, + VertexListGraph >::type weight_map_type; + typedef typename boost::property_traits< weight_map_type >::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max< D >()]; + const D zero_actual = D(); + const D zero_d = arg_pack[_distance_zero | zero_actual]; + null_visitor null_vis; + astar_visitor< null_visitor > default_visitor(null_vis); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::visitor, dummy_property_map& >::type vis + = arg_pack[_visitor | default_visitor]; + dummy_property_map dummy_prop; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::predecessor_map, + dummy_property_map& >::type pred_map + = arg_pack[_predecessor_map | dummy_prop]; + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::rank_map, D > + rank_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::rank_map, D >::map_type r_map + = rank_map_gen(g, arg_pack); + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::distance_map, D > + dist_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::distance_map, D >::map_type dist_map + = dist_map_gen(g, arg_pack); + weight_map_type w_map = detail::override_const_property( + arg_pack, _weight_map, g, edge_weight); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::color_map, + boost::default_color_type >::map_type c_map + = boost::detail::make_color_map_from_arg_pack(g, arg_pack); + typename boost::detail::override_const_property_result< arg_pack_type, + boost::graph::keywords::tag::vertex_index_map, vertex_index_t, + VertexListGraph >::type v_i_map + = detail::override_const_property( + arg_pack, _vertex_index_map, g, vertex_index); + std::less< D > default_compare; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_compare, std::less< D >& >::type + dist_comp + = arg_pack[_distance_compare | default_compare]; + closed_plus< D > default_combine(inf); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_combine, closed_plus< D >& >::type + dist_comb + = arg_pack[_distance_combine | default_combine]; + astar_search_no_init(g, s, h, vis, pred_map, r_map, dist_map, w_map, c_map, + v_i_map, dist_comp, dist_comb, inf, zero_d); +} + +template < typename VertexListGraph, typename AStarHeuristic, typename P, + typename T, typename R > +void astar_search_no_init_tree(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + AStarHeuristic h, const bgl_named_params< P, T, R >& params) +{ + using namespace boost::graph::keywords; + typedef bgl_named_params< P, T, R > params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + typedef + typename boost::detail::override_const_property_result< arg_pack_type, + boost::graph::keywords::tag::weight_map, edge_weight_t, + VertexListGraph >::type weight_map_type; + typedef typename boost::property_traits< weight_map_type >::value_type D; + const D inf = arg_pack[_distance_inf || detail::get_max< D >()]; + const D zero_actual = D(); + const D zero_d = arg_pack[_distance_zero | zero_actual]; + null_visitor null_vis; + astar_visitor< null_visitor > default_visitor(null_vis); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::visitor, dummy_property_map& >::type vis + = arg_pack[_visitor | default_visitor]; + dummy_property_map dummy_prop; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::predecessor_map, + dummy_property_map& >::type pred_map + = arg_pack[_predecessor_map | dummy_prop]; + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::rank_map, D > + rank_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::rank_map, D >::map_type r_map + = rank_map_gen(g, arg_pack); + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::distance_map, D > + dist_map_gen(zero_actual); + typename boost::detail::map_maker< VertexListGraph, arg_pack_type, + boost::graph::keywords::tag::distance_map, D >::map_type dist_map + = dist_map_gen(g, arg_pack); + weight_map_type w_map = detail::override_const_property( + arg_pack, _weight_map, g, edge_weight); + std::less< D > default_compare; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_compare, std::less< D >& >::type + dist_comp + = arg_pack[_distance_compare | default_compare]; + closed_plus< D > default_combine(inf); + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::distance_combine, closed_plus< D >& >::type + dist_comb + = arg_pack[_distance_combine | default_combine]; + astar_search_no_init_tree(g, s, h, vis, pred_map, r_map, dist_map, w_map, + dist_comp, dist_comb, inf, zero_d); +} + +} // namespace boost + +#endif // BOOST_GRAPH_ASTAR_SEARCH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/bandwidth.hpp b/contrib/restricted/boost/graph/include/boost/graph/bandwidth.hpp new file mode 100644 index 0000000000..e3f99adf51 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/bandwidth.hpp @@ -0,0 +1,94 @@ +// Copyright (c) Jeremy Siek 2001, Marc Wintermantel 2002 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_BANDWIDTH_HPP +#define BOOST_GRAPH_BANDWIDTH_HPP + +#include <algorithm> // for std::min and std::max +#include <boost/config.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/detail/numeric_traits.hpp> + +namespace boost +{ + +template < typename Graph, typename VertexIndexMap > +typename graph_traits< Graph >::vertices_size_type ith_bandwidth( + typename graph_traits< Graph >::vertex_descriptor i, const Graph& g, + VertexIndexMap index) +{ + BOOST_USING_STD_MAX(); + using std::abs; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + vertices_size_type b = 0; + typename graph_traits< Graph >::out_edge_iterator e, end; + for (boost::tie(e, end) = out_edges(i, g); e != end; ++e) + { + int f_i = get(index, i); + int f_j = get(index, target(*e, g)); + b = max BOOST_PREVENT_MACRO_SUBSTITUTION( + b, vertices_size_type(abs(f_i - f_j))); + } + return b; +} + +template < typename Graph > +typename graph_traits< Graph >::vertices_size_type ith_bandwidth( + typename graph_traits< Graph >::vertex_descriptor i, const Graph& g) +{ + return ith_bandwidth(i, g, get(vertex_index, g)); +} + +template < typename Graph, typename VertexIndexMap > +typename graph_traits< Graph >::vertices_size_type bandwidth( + const Graph& g, VertexIndexMap index) +{ + BOOST_USING_STD_MAX(); + using std::abs; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + vertices_size_type b = 0; + typename graph_traits< Graph >::edge_iterator i, end; + for (boost::tie(i, end) = edges(g); i != end; ++i) + { + int f_i = get(index, source(*i, g)); + int f_j = get(index, target(*i, g)); + b = max BOOST_PREVENT_MACRO_SUBSTITUTION( + b, vertices_size_type(abs(f_i - f_j))); + } + return b; +} + +template < typename Graph > +typename graph_traits< Graph >::vertices_size_type bandwidth(const Graph& g) +{ + return bandwidth(g, get(vertex_index, g)); +} + +template < typename Graph, typename VertexIndexMap > +typename graph_traits< Graph >::vertices_size_type edgesum( + const Graph& g, VertexIndexMap index_map) +{ + typedef typename graph_traits< Graph >::vertices_size_type size_type; + typedef + typename detail::numeric_traits< size_type >::difference_type diff_t; + size_type sum = 0; + typename graph_traits< Graph >::edge_iterator i, end; + for (boost::tie(i, end) = edges(g); i != end; ++i) + { + diff_t f_u = get(index_map, source(*i, g)); + diff_t f_v = get(index_map, target(*i, g)); + using namespace std; // to call abs() unqualified + sum += abs(f_u - f_v); + } + return sum; +} + +} // namespace boost + +#endif // BOOST_GRAPH_BANDWIDTH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/bc_clustering.hpp b/contrib/restricted/boost/graph/include/boost/graph/bc_clustering.hpp new file mode 100644 index 0000000000..dd26bdf397 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/bc_clustering.hpp @@ -0,0 +1,169 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP +#define BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP + +#include <boost/algorithm/minmax_element.hpp> +#include <boost/graph/betweenness_centrality.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_utility.hpp> +#include <boost/pending/indirect_cmp.hpp> +#include <vector> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +/** Threshold termination function for the betweenness centrality + * clustering algorithm. + */ +template < typename T > struct bc_clustering_threshold +{ + typedef T centrality_type; + + /// Terminate clustering when maximum absolute edge centrality is + /// below the given threshold. + explicit bc_clustering_threshold(T threshold) + : threshold(threshold), dividend(1.0) + { + } + + /** + * Terminate clustering when the maximum edge centrality is below + * the given threshold. + * + * @param threshold the threshold value + * + * @param g the graph on which the threshold will be calculated + * + * @param normalize when true, the threshold is compared against the + * normalized edge centrality based on the input graph; otherwise, + * the threshold is compared against the absolute edge centrality. + */ + template < typename Graph > + bc_clustering_threshold(T threshold, const Graph& g, bool normalize = true) + : threshold(threshold), dividend(1.0) + { + if (normalize) + { + typename graph_traits< Graph >::vertices_size_type n + = num_vertices(g); + dividend = T((n - 1) * (n - 2)) / T(2); + } + } + + /** Returns true when the given maximum edge centrality (potentially + * normalized) falls below the threshold. + */ + template < typename Graph, typename Edge > + bool operator()(T max_centrality, Edge, const Graph&) + { + return (max_centrality / dividend) < threshold; + } + +protected: + T threshold; + T dividend; +}; + +/** Graph clustering based on edge betweenness centrality. + * + * This algorithm implements graph clustering based on edge + * betweenness centrality. It is an iterative algorithm, where in each + * step it compute the edge betweenness centrality (via @ref + * brandes_betweenness_centrality) and removes the edge with the + * maximum betweenness centrality. The @p done function object + * determines when the algorithm terminates (the edge found when the + * algorithm terminates will not be removed). + * + * @param g The graph on which clustering will be performed. The type + * of this parameter (@c MutableGraph) must be a model of the + * VertexListGraph, IncidenceGraph, EdgeListGraph, and Mutable Graph + * concepts. + * + * @param done The function object that indicates termination of the + * algorithm. It must be a ternary function object thats accepts the + * maximum centrality, the descriptor of the edge that will be + * removed, and the graph @p g. + * + * @param edge_centrality (UTIL/OUT) The property map that will store + * the betweenness centrality for each edge. When the algorithm + * terminates, it will contain the edge centralities for the + * graph. The type of this property map must model the + * ReadWritePropertyMap concept. Defaults to an @c + * iterator_property_map whose value type is + * @c Done::centrality_type and using @c get(edge_index, g) for the + * index map. + * + * @param vertex_index (IN) The property map that maps vertices to + * indices in the range @c [0, num_vertices(g)). This type of this + * property map must model the ReadablePropertyMap concept and its + * value type must be an integral type. Defaults to + * @c get(vertex_index, g). + */ +template < typename MutableGraph, typename Done, typename EdgeCentralityMap, + typename VertexIndexMap > +void betweenness_centrality_clustering(MutableGraph& g, Done done, + EdgeCentralityMap edge_centrality, VertexIndexMap vertex_index) +{ + typedef typename property_traits< EdgeCentralityMap >::value_type + centrality_type; + typedef typename graph_traits< MutableGraph >::edge_iterator edge_iterator; + typedef + typename graph_traits< MutableGraph >::edge_descriptor edge_descriptor; + + if (has_no_edges(g)) + return; + + // Function object that compares the centrality of edges + indirect_cmp< EdgeCentralityMap, std::less< centrality_type > > cmp( + edge_centrality); + + bool is_done; + do + { + brandes_betweenness_centrality(g, + edge_centrality_map(edge_centrality) + .vertex_index_map(vertex_index)); + std::pair< edge_iterator, edge_iterator > edges_iters = edges(g); + edge_descriptor e + = *boost::first_max_element(edges_iters.first, edges_iters.second, cmp); + is_done = done(get(edge_centrality, e), e, g); + if (!is_done) + remove_edge(e, g); + } while (!is_done && !has_no_edges(g)); +} + +/** + * \overload + */ +template < typename MutableGraph, typename Done, typename EdgeCentralityMap > +void betweenness_centrality_clustering( + MutableGraph& g, Done done, EdgeCentralityMap edge_centrality) +{ + betweenness_centrality_clustering( + g, done, edge_centrality, get(vertex_index, g)); +} + +/** + * \overload + */ +template < typename MutableGraph, typename Done > +void betweenness_centrality_clustering(MutableGraph& g, Done done) +{ + typedef typename Done::centrality_type centrality_type; + std::vector< centrality_type > edge_centrality(num_edges(g)); + betweenness_centrality_clustering(g, done, + make_iterator_property_map(edge_centrality.begin(), get(edge_index, g)), + get(vertex_index, g)); +} + +} // end namespace boost + +#endif // BOOST_GRAPH_BETWEENNESS_CENTRALITY_CLUSTERING_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/bellman_ford_shortest_paths.hpp b/contrib/restricted/boost/graph/include/boost/graph/bellman_ford_shortest_paths.hpp new file mode 100644 index 0000000000..2aa4e80833 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/bellman_ford_shortest_paths.hpp @@ -0,0 +1,226 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +/* + This file implements the function + + template <class EdgeListGraph, class Size, class P, class T, class R> + bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, + const bgl_named_params<P, T, R>& params) + + */ + +#ifndef BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP +#define BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP + +#include <boost/config.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/relax.hpp> +#include <boost/graph/visitors.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +template < class Visitor, class Graph > struct BellmanFordVisitorConcept +{ + void constraints() + { + BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Visitor >)); + vis.examine_edge(e, g); + vis.edge_relaxed(e, g); + vis.edge_not_relaxed(e, g); + vis.edge_minimized(e, g); + vis.edge_not_minimized(e, g); + } + Visitor vis; + Graph g; + typename graph_traits< Graph >::edge_descriptor e; +}; + +template < class Visitors = null_visitor > class bellman_visitor +{ +public: + bellman_visitor() {} + bellman_visitor(Visitors vis) : m_vis(vis) {} + + template < class Edge, class Graph > void examine_edge(Edge u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_examine_edge()); + } + template < class Edge, class Graph > void edge_relaxed(Edge u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_edge_relaxed()); + } + template < class Edge, class Graph > void edge_not_relaxed(Edge u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_edge_not_relaxed()); + } + template < class Edge, class Graph > void edge_minimized(Edge u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_edge_minimized()); + } + template < class Edge, class Graph > + void edge_not_minimized(Edge u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_edge_not_minimized()); + } + +protected: + Visitors m_vis; +}; +template < class Visitors > +bellman_visitor< Visitors > make_bellman_visitor(Visitors vis) +{ + return bellman_visitor< Visitors >(vis); +} +typedef bellman_visitor<> default_bellman_visitor; + +template < class EdgeListGraph, class Size, class WeightMap, + class PredecessorMap, class DistanceMap, class BinaryFunction, + class BinaryPredicate, class BellmanFordVisitor > +bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N, WeightMap weight, + PredecessorMap pred, DistanceMap distance, BinaryFunction combine, + BinaryPredicate compare, BellmanFordVisitor v) +{ + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< EdgeListGraph >)); + typedef graph_traits< EdgeListGraph > GTraits; + typedef typename GTraits::edge_descriptor Edge; + typedef typename GTraits::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< DistanceMap, Vertex >)); + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< WeightMap, Edge >)); + + typename GTraits::edge_iterator i, end; + + for (Size k = 0; k < N; ++k) + { + bool at_least_one_edge_relaxed = false; + for (boost::tie(i, end) = edges(g); i != end; ++i) + { + v.examine_edge(*i, g); + if (relax(*i, g, weight, pred, distance, combine, compare)) + { + at_least_one_edge_relaxed = true; + v.edge_relaxed(*i, g); + } + else + v.edge_not_relaxed(*i, g); + } + if (!at_least_one_edge_relaxed) + break; + } + + for (boost::tie(i, end) = edges(g); i != end; ++i) + if (compare(combine(get(distance, source(*i, g)), get(weight, *i)), + get(distance, target(*i, g)))) + { + v.edge_not_minimized(*i, g); + return false; + } + else + v.edge_minimized(*i, g); + + return true; +} + +namespace detail +{ + + template < typename VertexAndEdgeListGraph, typename Size, + typename WeightMap, typename PredecessorMap, typename DistanceMap, + typename P, typename T, typename R > + bool bellman_dispatch2(VertexAndEdgeListGraph& g, + typename graph_traits< VertexAndEdgeListGraph >::vertex_descriptor s, + Size N, WeightMap weight, PredecessorMap pred, DistanceMap distance, + const bgl_named_params< P, T, R >& params) + { + typedef typename property_traits< DistanceMap >::value_type D; + bellman_visitor<> null_vis; + typedef typename property_traits< WeightMap >::value_type weight_type; + typename graph_traits< VertexAndEdgeListGraph >::vertex_iterator v, + v_end; + for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) + { + put(distance, *v, (std::numeric_limits< weight_type >::max)()); + put(pred, *v, *v); + } + put(distance, s, weight_type(0)); + return bellman_ford_shortest_paths(g, N, weight, pred, distance, + choose_param( + get_param(params, distance_combine_t()), closed_plus< D >()), + choose_param( + get_param(params, distance_compare_t()), std::less< D >()), + choose_param(get_param(params, graph_visitor), null_vis)); + } + + template < typename VertexAndEdgeListGraph, typename Size, + typename WeightMap, typename PredecessorMap, typename DistanceMap, + typename P, typename T, typename R > + bool bellman_dispatch2(VertexAndEdgeListGraph& g, param_not_found, Size N, + WeightMap weight, PredecessorMap pred, DistanceMap distance, + const bgl_named_params< P, T, R >& params) + { + typedef typename property_traits< DistanceMap >::value_type D; + bellman_visitor<> null_vis; + return bellman_ford_shortest_paths(g, N, weight, pred, distance, + choose_param( + get_param(params, distance_combine_t()), closed_plus< D >()), + choose_param( + get_param(params, distance_compare_t()), std::less< D >()), + choose_param(get_param(params, graph_visitor), null_vis)); + } + + template < class EdgeListGraph, class Size, class WeightMap, + class DistanceMap, class P, class T, class R > + bool bellman_dispatch(EdgeListGraph& g, Size N, WeightMap weight, + DistanceMap distance, const bgl_named_params< P, T, R >& params) + { + dummy_property_map dummy_pred; + return detail::bellman_dispatch2(g, get_param(params, root_vertex_t()), + N, weight, + choose_param(get_param(params, vertex_predecessor), dummy_pred), + distance, params); + } +} // namespace detail + +template < class EdgeListGraph, class Size, class P, class T, class R > +bool bellman_ford_shortest_paths( + EdgeListGraph& g, Size N, const bgl_named_params< P, T, R >& params) +{ + return detail::bellman_dispatch(g, N, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_pmap(get_param(params, vertex_distance), g, vertex_distance), + params); +} + +template < class EdgeListGraph, class Size > +bool bellman_ford_shortest_paths(EdgeListGraph& g, Size N) +{ + bgl_named_params< int, int > params(0); + return bellman_ford_shortest_paths(g, N, params); +} + +template < class VertexAndEdgeListGraph, class P, class T, class R > +bool bellman_ford_shortest_paths( + VertexAndEdgeListGraph& g, const bgl_named_params< P, T, R >& params) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< VertexAndEdgeListGraph >)); + return detail::bellman_dispatch(g, num_vertices(g), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_pmap(get_param(params, vertex_distance), g, vertex_distance), + params); +} +} // namespace boost + +#endif // BOOST_GRAPH_BELLMAN_FORD_SHORTEST_PATHS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/betweenness_centrality.hpp b/contrib/restricted/boost/graph/include/boost/graph/betweenness_centrality.hpp new file mode 100644 index 0000000000..b6148e46ab --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/betweenness_centrality.hpp @@ -0,0 +1,645 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP +#define BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP + +#include <stack> +#include <vector> +#include <boost/graph/overloading.hpp> +#include <boost/graph/dijkstra_shortest_paths.hpp> +#include <boost/graph/breadth_first_search.hpp> +#include <boost/graph/relax.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/type_traits/is_convertible.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/mpl/if.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/named_function_params.hpp> +#include <algorithm> + +namespace boost +{ + +namespace detail +{ + namespace graph + { + + /** + * Customized visitor passed to Dijkstra's algorithm by Brandes' + * betweenness centrality algorithm. This visitor is responsible for + * keeping track of the order in which vertices are discovered, the + * predecessors on the shortest path(s) to a vertex, and the number + * of shortest paths. + */ + template < typename Graph, typename WeightMap, typename IncomingMap, + typename DistanceMap, typename PathCountMap > + struct brandes_dijkstra_visitor : public bfs_visitor<> + { + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + typedef + typename graph_traits< Graph >::edge_descriptor edge_descriptor; + + brandes_dijkstra_visitor( + std::stack< vertex_descriptor >& ordered_vertices, + WeightMap weight, IncomingMap incoming, DistanceMap distance, + PathCountMap path_count) + : ordered_vertices(ordered_vertices) + , weight(weight) + , incoming(incoming) + , distance(distance) + , path_count(path_count) + { + } + + /** + * Whenever an edge e = (v, w) is relaxed, the incoming edge list + * for w is set to {(v, w)} and the shortest path count of w is set + * to the number of paths that reach {v}. + */ + void edge_relaxed(edge_descriptor e, const Graph& g) + { + vertex_descriptor v = source(e, g), w = target(e, g); + incoming[w].clear(); + incoming[w].push_back(e); + put(path_count, w, get(path_count, v)); + } + + /** + * If an edge e = (v, w) was not relaxed, it may still be the case + * that we've found more equally-short paths, so include {(v, w)} in + * the incoming edges of w and add all of the shortest paths to v to + * the shortest path count of w. + */ + void edge_not_relaxed(edge_descriptor e, const Graph& g) + { + typedef typename property_traits< WeightMap >::value_type + weight_type; + typedef typename property_traits< DistanceMap >::value_type + distance_type; + vertex_descriptor v = source(e, g), w = target(e, g); + distance_type d_v = get(distance, v), d_w = get(distance, w); + weight_type w_e = get(weight, e); + + closed_plus< distance_type > combine; + if (d_w == combine(d_v, w_e)) + { + put(path_count, w, get(path_count, w) + get(path_count, v)); + incoming[w].push_back(e); + } + } + + /// Keep track of vertices as they are reached + void examine_vertex(vertex_descriptor w, const Graph&) + { + ordered_vertices.push(w); + } + + private: + std::stack< vertex_descriptor >& ordered_vertices; + WeightMap weight; + IncomingMap incoming; + DistanceMap distance; + PathCountMap path_count; + }; + + /** + * Function object that calls Dijkstra's shortest paths algorithm + * using the Dijkstra visitor for the Brandes betweenness centrality + * algorithm. + */ + template < typename WeightMap > struct brandes_dijkstra_shortest_paths + { + brandes_dijkstra_shortest_paths(WeightMap weight_map) + : weight_map(weight_map) + { + } + + template < typename Graph, typename IncomingMap, + typename DistanceMap, typename PathCountMap, + typename VertexIndexMap > + void operator()(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + std::stack< typename graph_traits< Graph >::vertex_descriptor >& + ov, + IncomingMap incoming, DistanceMap distance, + PathCountMap path_count, VertexIndexMap vertex_index) + { + typedef brandes_dijkstra_visitor< Graph, WeightMap, IncomingMap, + DistanceMap, PathCountMap > + visitor_type; + visitor_type visitor( + ov, weight_map, incoming, distance, path_count); + + dijkstra_shortest_paths(g, s, + boost::weight_map(weight_map) + .vertex_index_map(vertex_index) + .distance_map(distance) + .visitor(visitor)); + } + + private: + WeightMap weight_map; + }; + + /** + * Function object that invokes breadth-first search for the + * unweighted form of the Brandes betweenness centrality algorithm. + */ + struct brandes_unweighted_shortest_paths + { + /** + * Customized visitor passed to breadth-first search, which + * records predecessor and the number of shortest paths to each + * vertex. + */ + template < typename Graph, typename IncomingMap, + typename DistanceMap, typename PathCountMap > + struct visitor_type : public bfs_visitor<> + { + typedef typename graph_traits< Graph >::edge_descriptor + edge_descriptor; + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + + visitor_type(IncomingMap incoming, DistanceMap distance, + PathCountMap path_count, + std::stack< vertex_descriptor >& ordered_vertices) + : incoming(incoming) + , distance(distance) + , path_count(path_count) + , ordered_vertices(ordered_vertices) + { + } + + /// Keep track of vertices as they are reached + void examine_vertex(vertex_descriptor v, Graph&) + { + ordered_vertices.push(v); + } + + /** + * Whenever an edge e = (v, w) is labelled a tree edge, the + * incoming edge list for w is set to {(v, w)} and the shortest + * path count of w is set to the number of paths that reach {v}. + */ + void tree_edge(edge_descriptor e, Graph& g) + { + vertex_descriptor v = source(e, g); + vertex_descriptor w = target(e, g); + put(distance, w, get(distance, v) + 1); + + put(path_count, w, get(path_count, v)); + incoming[w].push_back(e); + } + + /** + * If an edge e = (v, w) is not a tree edge, it may still be the + * case that we've found more equally-short paths, so include + * (v, w) in the incoming edge list of w and add all of the + * shortest paths to v to the shortest path count of w. + */ + void non_tree_edge(edge_descriptor e, Graph& g) + { + vertex_descriptor v = source(e, g); + vertex_descriptor w = target(e, g); + if (get(distance, w) == get(distance, v) + 1) + { + put(path_count, w, + get(path_count, w) + get(path_count, v)); + incoming[w].push_back(e); + } + } + + private: + IncomingMap incoming; + DistanceMap distance; + PathCountMap path_count; + std::stack< vertex_descriptor >& ordered_vertices; + }; + + template < typename Graph, typename IncomingMap, + typename DistanceMap, typename PathCountMap, + typename VertexIndexMap > + void operator()(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + std::stack< typename graph_traits< Graph >::vertex_descriptor >& + ov, + IncomingMap incoming, DistanceMap distance, + PathCountMap path_count, VertexIndexMap vertex_index) + { + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + + visitor_type< Graph, IncomingMap, DistanceMap, PathCountMap > + visitor(incoming, distance, path_count, ov); + + std::vector< default_color_type > colors(num_vertices(g), + color_traits< default_color_type >::white()); + boost::queue< vertex_descriptor > Q; + breadth_first_visit(g, s, Q, visitor, + make_iterator_property_map(colors.begin(), vertex_index)); + } + }; + + // When the edge centrality map is a dummy property map, no + // initialization is needed. + template < typename Iter > + inline void init_centrality_map( + std::pair< Iter, Iter >, dummy_property_map) + { + } + + // When we have a real edge centrality map, initialize all of the + // centralities to zero. + template < typename Iter, typename Centrality > + void init_centrality_map( + std::pair< Iter, Iter > keys, Centrality centrality_map) + { + typedef typename property_traits< Centrality >::value_type + centrality_type; + while (keys.first != keys.second) + { + put(centrality_map, *keys.first, centrality_type(0)); + ++keys.first; + } + } + + // When the edge centrality map is a dummy property map, no update + // is performed. + template < typename Key, typename T > + inline void update_centrality(dummy_property_map, const Key&, const T&) + { + } + + // When we have a real edge centrality map, add the value to the map + template < typename CentralityMap, typename Key, typename T > + inline void update_centrality( + CentralityMap centrality_map, Key k, const T& x) + { + put(centrality_map, k, get(centrality_map, k) + x); + } + + template < typename Iter > + inline void divide_centrality_by_two( + std::pair< Iter, Iter >, dummy_property_map) + { + } + + template < typename Iter, typename CentralityMap > + inline void divide_centrality_by_two( + std::pair< Iter, Iter > keys, CentralityMap centrality_map) + { + typename property_traits< CentralityMap >::value_type two(2); + while (keys.first != keys.second) + { + put(centrality_map, *keys.first, + get(centrality_map, *keys.first) / two); + ++keys.first; + } + } + + template < typename Graph, typename CentralityMap, + typename EdgeCentralityMap, typename IncomingMap, + typename DistanceMap, typename DependencyMap, typename PathCountMap, + typename VertexIndexMap, typename ShortestPaths > + void brandes_betweenness_centrality_impl(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index, ShortestPaths shortest_paths) + { + typedef + typename graph_traits< Graph >::vertex_iterator vertex_iterator; + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + + // Initialize centrality + init_centrality_map(vertices(g), centrality); + init_centrality_map(edges(g), edge_centrality_map); + + std::stack< vertex_descriptor > ordered_vertices; + vertex_iterator s, s_end; + for (boost::tie(s, s_end) = vertices(g); s != s_end; ++s) + { + // Initialize for this iteration + vertex_iterator w, w_end; + for (boost::tie(w, w_end) = vertices(g); w != w_end; ++w) + { + incoming[*w].clear(); + put(path_count, *w, 0); + put(dependency, *w, 0); + } + put(path_count, *s, 1); + + // Execute the shortest paths algorithm. This will be either + // Dijkstra's algorithm or a customized breadth-first search, + // depending on whether the graph is weighted or unweighted. + shortest_paths(g, *s, ordered_vertices, incoming, distance, + path_count, vertex_index); + + while (!ordered_vertices.empty()) + { + vertex_descriptor w = ordered_vertices.top(); + ordered_vertices.pop(); + + typedef typename property_traits< IncomingMap >::value_type + incoming_type; + typedef typename incoming_type::iterator incoming_iterator; + typedef + typename property_traits< DependencyMap >::value_type + dependency_type; + + for (incoming_iterator vw = incoming[w].begin(); + vw != incoming[w].end(); ++vw) + { + vertex_descriptor v = source(*vw, g); + dependency_type factor + = dependency_type(get(path_count, v)) + / dependency_type(get(path_count, w)); + factor *= (dependency_type(1) + get(dependency, w)); + put(dependency, v, get(dependency, v) + factor); + update_centrality(edge_centrality_map, *vw, factor); + } + + if (w != *s) + { + update_centrality(centrality, w, get(dependency, w)); + } + } + } + + typedef typename graph_traits< Graph >::directed_category + directed_category; + const bool is_undirected + = is_convertible< directed_category*, undirected_tag* >::value; + if (is_undirected) + { + divide_centrality_by_two(vertices(g), centrality); + divide_centrality_by_two(edges(g), edge_centrality_map); + } + } + + } +} // end namespace detail::graph + +template < typename Graph, typename CentralityMap, typename EdgeCentralityMap, + typename IncomingMap, typename DistanceMap, typename DependencyMap, + typename PathCountMap, typename VertexIndexMap > +void brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index BOOST_GRAPH_ENABLE_IF_MODELS_PARM( + Graph, vertex_list_graph_tag)) +{ + detail::graph::brandes_unweighted_shortest_paths shortest_paths; + + detail::graph::brandes_betweenness_centrality_impl(g, centrality, + edge_centrality_map, incoming, distance, dependency, path_count, + vertex_index, shortest_paths); +} + +template < typename Graph, typename CentralityMap, typename EdgeCentralityMap, + typename IncomingMap, typename DistanceMap, typename DependencyMap, + typename PathCountMap, typename VertexIndexMap, typename WeightMap > +void brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality, // C_B + EdgeCentralityMap edge_centrality_map, + IncomingMap incoming, // P + DistanceMap distance, // d + DependencyMap dependency, // delta + PathCountMap path_count, // sigma + VertexIndexMap vertex_index, + WeightMap weight_map BOOST_GRAPH_ENABLE_IF_MODELS_PARM( + Graph, vertex_list_graph_tag)) +{ + detail::graph::brandes_dijkstra_shortest_paths< WeightMap > shortest_paths( + weight_map); + + detail::graph::brandes_betweenness_centrality_impl(g, centrality, + edge_centrality_map, incoming, distance, dependency, path_count, + vertex_index, shortest_paths); +} + +namespace detail +{ + namespace graph + { + template < typename Graph, typename CentralityMap, + typename EdgeCentralityMap, typename WeightMap, + typename VertexIndexMap > + void brandes_betweenness_centrality_dispatch2(const Graph& g, + CentralityMap centrality, EdgeCentralityMap edge_centrality_map, + WeightMap weight_map, VertexIndexMap vertex_index) + { + typedef typename graph_traits< Graph >::degree_size_type + degree_size_type; + typedef + typename graph_traits< Graph >::edge_descriptor edge_descriptor; + typedef typename mpl::if_c< + (is_same< CentralityMap, dummy_property_map >::value), + EdgeCentralityMap, CentralityMap >::type a_centrality_map; + typedef typename property_traits< a_centrality_map >::value_type + centrality_type; + + typename graph_traits< Graph >::vertices_size_type V + = num_vertices(g); + + std::vector< std::vector< edge_descriptor > > incoming(V); + std::vector< centrality_type > distance(V); + std::vector< centrality_type > dependency(V); + std::vector< degree_size_type > path_count(V); + + brandes_betweenness_centrality(g, centrality, edge_centrality_map, + make_iterator_property_map(incoming.begin(), vertex_index), + make_iterator_property_map(distance.begin(), vertex_index), + make_iterator_property_map(dependency.begin(), vertex_index), + make_iterator_property_map(path_count.begin(), vertex_index), + vertex_index, weight_map); + } + + template < typename Graph, typename CentralityMap, + typename EdgeCentralityMap, typename VertexIndexMap > + void brandes_betweenness_centrality_dispatch2(const Graph& g, + CentralityMap centrality, EdgeCentralityMap edge_centrality_map, + VertexIndexMap vertex_index) + { + typedef typename graph_traits< Graph >::degree_size_type + degree_size_type; + typedef + typename graph_traits< Graph >::edge_descriptor edge_descriptor; + typedef typename mpl::if_c< + (is_same< CentralityMap, dummy_property_map >::value), + EdgeCentralityMap, CentralityMap >::type a_centrality_map; + typedef typename property_traits< a_centrality_map >::value_type + centrality_type; + + typename graph_traits< Graph >::vertices_size_type V + = num_vertices(g); + + std::vector< std::vector< edge_descriptor > > incoming(V); + std::vector< centrality_type > distance(V); + std::vector< centrality_type > dependency(V); + std::vector< degree_size_type > path_count(V); + + brandes_betweenness_centrality(g, centrality, edge_centrality_map, + make_iterator_property_map(incoming.begin(), vertex_index), + make_iterator_property_map(distance.begin(), vertex_index), + make_iterator_property_map(dependency.begin(), vertex_index), + make_iterator_property_map(path_count.begin(), vertex_index), + vertex_index); + } + + template < typename WeightMap > + struct brandes_betweenness_centrality_dispatch1 + { + template < typename Graph, typename CentralityMap, + typename EdgeCentralityMap, typename VertexIndexMap > + static void run(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, + VertexIndexMap vertex_index, WeightMap weight_map) + { + brandes_betweenness_centrality_dispatch2(g, centrality, + edge_centrality_map, weight_map, vertex_index); + } + }; + + template <> + struct brandes_betweenness_centrality_dispatch1< param_not_found > + { + template < typename Graph, typename CentralityMap, + typename EdgeCentralityMap, typename VertexIndexMap > + static void run(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map, + VertexIndexMap vertex_index, param_not_found) + { + brandes_betweenness_centrality_dispatch2( + g, centrality, edge_centrality_map, vertex_index); + } + }; + + template < typename T > struct is_bgl_named_params + { + BOOST_STATIC_CONSTANT(bool, value = false); + }; + + template < typename Param, typename Tag, typename Rest > + struct is_bgl_named_params< bgl_named_params< Param, Tag, Rest > > + { + BOOST_STATIC_CONSTANT(bool, value = true); + }; + + } +} // end namespace detail::graph + +template < typename Graph, typename Param, typename Tag, typename Rest > +void brandes_betweenness_centrality(const Graph& g, + const bgl_named_params< Param, Tag, Rest >& params + BOOST_GRAPH_ENABLE_IF_MODELS_PARM(Graph, vertex_list_graph_tag)) +{ + typedef bgl_named_params< Param, Tag, Rest > named_params; + + typedef typename get_param_type< edge_weight_t, named_params >::type ew; + detail::graph::brandes_betweenness_centrality_dispatch1< ew >::run(g, + choose_param( + get_param(params, vertex_centrality), dummy_property_map()), + choose_param(get_param(params, edge_centrality), dummy_property_map()), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + get_param(params, edge_weight)); +} + +// disable_if is required to work around problem with MSVC 7.1 (it seems to not +// get partial ordering getween this overload and the previous one correct) +template < typename Graph, typename CentralityMap > +typename disable_if< detail::graph::is_bgl_named_params< CentralityMap >, + void >::type +brandes_betweenness_centrality(const Graph& g, + CentralityMap centrality BOOST_GRAPH_ENABLE_IF_MODELS_PARM( + Graph, vertex_list_graph_tag)) +{ + detail::graph::brandes_betweenness_centrality_dispatch2( + g, centrality, dummy_property_map(), get(vertex_index, g)); +} + +template < typename Graph, typename CentralityMap, typename EdgeCentralityMap > +void brandes_betweenness_centrality(const Graph& g, CentralityMap centrality, + EdgeCentralityMap edge_centrality_map BOOST_GRAPH_ENABLE_IF_MODELS_PARM( + Graph, vertex_list_graph_tag)) +{ + detail::graph::brandes_betweenness_centrality_dispatch2( + g, centrality, edge_centrality_map, get(vertex_index, g)); +} + +/** + * Converts "absolute" betweenness centrality (as computed by the + * brandes_betweenness_centrality algorithm) in the centrality map + * into "relative" centrality. The result is placed back into the + * given centrality map. + */ +template < typename Graph, typename CentralityMap > +void relative_betweenness_centrality(const Graph& g, CentralityMap centrality) +{ + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator; + typedef + typename property_traits< CentralityMap >::value_type centrality_type; + + typename graph_traits< Graph >::vertices_size_type n = num_vertices(g); + centrality_type factor + = centrality_type(2) / centrality_type(n * n - 3 * n + 2); + vertex_iterator v, v_end; + for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) + { + put(centrality, *v, factor * get(centrality, *v)); + } +} + +// Compute the central point dominance of a graph. +template < typename Graph, typename CentralityMap > +typename property_traits< CentralityMap >::value_type central_point_dominance( + const Graph& g, + CentralityMap centrality BOOST_GRAPH_ENABLE_IF_MODELS_PARM( + Graph, vertex_list_graph_tag)) +{ + using std::max; + + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator; + typedef + typename property_traits< CentralityMap >::value_type centrality_type; + + typename graph_traits< Graph >::vertices_size_type n = num_vertices(g); + + // Find max centrality + centrality_type max_centrality(0); + vertex_iterator v, v_end; + for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) + { + max_centrality = (max)(max_centrality, get(centrality, *v)); + } + + // Compute central point dominance + centrality_type sum(0); + for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) + { + sum += (max_centrality - get(centrality, *v)); + } + return sum / (n - 1); +} + +} // end namespace boost + +#endif // BOOST_GRAPH_BRANDES_BETWEENNESS_CENTRALITY_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/biconnected_components.hpp b/contrib/restricted/boost/graph/include/boost/graph/biconnected_components.hpp new file mode 100644 index 0000000000..9b70e0eb48 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/biconnected_components.hpp @@ -0,0 +1,440 @@ +// Copyright (c) Jeremy Siek 2001 +// Copyright (c) Douglas Gregor 2004 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// NOTE: this final is generated by libs/graph/doc/biconnected_components.w + +#ifndef BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP +#define BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP + +#include <stack> +#include <vector> +#include <algorithm> // for std::min and std::max +#include <boost/config.hpp> +#include <boost/limits.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/depth_first_search.hpp> +#include <boost/graph/graph_utility.hpp> +#include <boost/concept/assert.hpp> +#include <boost/assert.hpp> + +namespace boost +{ +namespace detail +{ + template < typename ComponentMap, typename DiscoverTimeMap, + typename LowPointMap, typename PredecessorMap, typename OutputIterator, + typename Stack, typename ArticulationVector, typename IndexMap, + typename DFSVisitor > + struct biconnected_components_visitor : public dfs_visitor<> + { + biconnected_components_visitor(ComponentMap comp, std::size_t& c, + std::size_t& children_of_root, DiscoverTimeMap dtm, + std::size_t& dfs_time, LowPointMap lowpt, PredecessorMap pred, + OutputIterator out, Stack& S, + ArticulationVector& is_articulation_point, IndexMap index_map, + DFSVisitor vis) + : comp(comp) + , c(c) + , children_of_root(children_of_root) + , dtm(dtm) + , dfs_time(dfs_time) + , lowpt(lowpt) + , pred(pred) + , out(out) + , S(S) + , is_articulation_point(is_articulation_point) + , index_map(index_map) + , vis(vis) + { + } + + template < typename Vertex, typename Graph > + void initialize_vertex(const Vertex& u, Graph& g) + { + put(pred, u, u); + vis.initialize_vertex(u, g); + } + + template < typename Vertex, typename Graph > + void start_vertex(const Vertex& u, Graph& g) + { + children_of_root = 0; + vis.start_vertex(u, g); + } + + template < typename Vertex, typename Graph > + void discover_vertex(const Vertex& u, Graph& g) + { + put(dtm, u, ++dfs_time); + put(lowpt, u, get(dtm, u)); + vis.discover_vertex(u, g); + } + + template < typename Edge, typename Graph > + void examine_edge(const Edge& e, Graph& g) + { + vis.examine_edge(e, g); + } + + template < typename Edge, typename Graph > + void tree_edge(const Edge& e, Graph& g) + { + typename boost::graph_traits< Graph >::vertex_descriptor src + = source(e, g); + typename boost::graph_traits< Graph >::vertex_descriptor tgt + = target(e, g); + + S.push(e); + put(pred, tgt, src); + if (get(pred, src) == src) + { + ++children_of_root; + } + vis.tree_edge(e, g); + } + + template < typename Edge, typename Graph > + void back_edge(const Edge& e, Graph& g) + { + BOOST_USING_STD_MIN(); + + typename boost::graph_traits< Graph >::vertex_descriptor src + = source(e, g); + typename boost::graph_traits< Graph >::vertex_descriptor tgt + = target(e, g); + if (tgt != get(pred, src)) + { + S.push(e); + put(lowpt, src, + min BOOST_PREVENT_MACRO_SUBSTITUTION( + get(lowpt, src), get(dtm, tgt))); + } + vis.back_edge(e, g); + } + + template < typename Edge, typename Graph > + void forward_or_cross_edge(const Edge& e, Graph& g) + { + vis.forward_or_cross_edge(e, g); + } + + template < typename Vertex, typename Graph > + void finish_vertex(const Vertex& u, Graph& g) + { + BOOST_USING_STD_MIN(); + Vertex parent = get(pred, u); + if (parent == u) + { // Root of tree is special + is_articulation_point[get(index_map, u)] + = (children_of_root > 1); + } + else + { + put(lowpt, parent, + min BOOST_PREVENT_MACRO_SUBSTITUTION( + get(lowpt, parent), get(lowpt, u))); + if (get(lowpt, u) >= get(dtm, parent)) + { + is_articulation_point[get(index_map, parent)] = true; + while (get(dtm, source(S.top(), g)) >= get(dtm, u)) + { + put(comp, S.top(), c); + S.pop(); + } + BOOST_ASSERT(source(S.top(), g) == parent); + BOOST_ASSERT(target(S.top(), g) == u); + put(comp, S.top(), c); + S.pop(); + ++c; + } + } + if (is_articulation_point[get(index_map, u)]) + { + *out++ = u; + } + vis.finish_vertex(u, g); + } + + ComponentMap comp; + std::size_t& c; + std::size_t& children_of_root; + DiscoverTimeMap dtm; + std::size_t& dfs_time; + LowPointMap lowpt; + PredecessorMap pred; + OutputIterator out; + Stack& S; + ArticulationVector& is_articulation_point; + IndexMap index_map; + DFSVisitor vis; + }; + + template < typename Graph, typename ComponentMap, typename OutputIterator, + typename VertexIndexMap, typename DiscoverTimeMap, typename LowPointMap, + typename PredecessorMap, typename DFSVisitor > + std::pair< std::size_t, OutputIterator > biconnected_components_impl( + const Graph& g, ComponentMap comp, OutputIterator out, + VertexIndexMap index_map, DiscoverTimeMap dtm, LowPointMap lowpt, + PredecessorMap pred, DFSVisitor dfs_vis) + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT( + (WritablePropertyMapConcept< ComponentMap, edge_t >)); + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< DiscoverTimeMap, vertex_t >)); + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< LowPointMap, vertex_t >)); + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< PredecessorMap, vertex_t >)); + + std::size_t num_components = 0; + std::size_t children_of_root; + std::size_t dfs_time = 0; + std::stack< edge_t > S; + std::vector< char > is_articulation_point(num_vertices(g)); + + biconnected_components_visitor< ComponentMap, DiscoverTimeMap, + LowPointMap, PredecessorMap, OutputIterator, std::stack< edge_t >, + std::vector< char >, VertexIndexMap, DFSVisitor > + vis(comp, num_components, children_of_root, dtm, dfs_time, lowpt, + pred, out, S, is_articulation_point, index_map, dfs_vis); + + depth_first_search(g, visitor(vis).vertex_index_map(index_map)); + + return std::pair< std::size_t, OutputIterator >( + num_components, vis.out); + } + + template < typename PredecessorMap > struct bicomp_dispatch3 + { + template < typename Graph, typename ComponentMap, + typename OutputIterator, typename VertexIndexMap, + typename DiscoverTimeMap, typename LowPointMap, class P, class T, + class R > + static std::pair< std::size_t, OutputIterator > apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, LowPointMap lowpt, + const bgl_named_params< P, T, R >& params, PredecessorMap pred) + { + return biconnected_components_impl(g, comp, out, index_map, dtm, + lowpt, pred, + choose_param(get_param(params, graph_visitor), + make_dfs_visitor(null_visitor()))); + } + }; + + template <> struct bicomp_dispatch3< param_not_found > + { + template < typename Graph, typename ComponentMap, + typename OutputIterator, typename VertexIndexMap, + typename DiscoverTimeMap, typename LowPointMap, class P, class T, + class R > + static std::pair< std::size_t, OutputIterator > apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, LowPointMap lowpt, + const bgl_named_params< P, T, R >& params, param_not_found) + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + std::vector< vertex_t > pred(num_vertices(g)); + vertex_t vert = graph_traits< Graph >::null_vertex(); + + return biconnected_components_impl(g, comp, out, index_map, dtm, + lowpt, + make_iterator_property_map(pred.begin(), index_map, vert), + choose_param(get_param(params, graph_visitor), + make_dfs_visitor(null_visitor()))); + } + }; + + template < typename LowPointMap > struct bicomp_dispatch2 + { + template < typename Graph, typename ComponentMap, + typename OutputIterator, typename VertexIndexMap, + typename DiscoverTimeMap, typename P, typename T, typename R > + static std::pair< std::size_t, OutputIterator > apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, const bgl_named_params< P, T, R >& params, + LowPointMap lowpt) + { + typedef typename get_param_type< vertex_predecessor_t, + bgl_named_params< P, T, R > >::type dispatch_type; + + return bicomp_dispatch3< dispatch_type >::apply(g, comp, out, + index_map, dtm, lowpt, params, + get_param(params, vertex_predecessor)); + } + }; + + template <> struct bicomp_dispatch2< param_not_found > + { + template < typename Graph, typename ComponentMap, + typename OutputIterator, typename VertexIndexMap, + typename DiscoverTimeMap, typename P, typename T, typename R > + static std::pair< std::size_t, OutputIterator > apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + DiscoverTimeMap dtm, const bgl_named_params< P, T, R >& params, + param_not_found) + { + typedef typename graph_traits< Graph >::vertices_size_type + vertices_size_type; + std::vector< vertices_size_type > lowpt(num_vertices(g)); + vertices_size_type vst(0); + + typedef typename get_param_type< vertex_predecessor_t, + bgl_named_params< P, T, R > >::type dispatch_type; + + return bicomp_dispatch3< dispatch_type >::apply(g, comp, out, + index_map, dtm, + make_iterator_property_map(lowpt.begin(), index_map, vst), + params, get_param(params, vertex_predecessor)); + } + }; + + template < typename DiscoverTimeMap > struct bicomp_dispatch1 + { + template < typename Graph, typename ComponentMap, + typename OutputIterator, typename VertexIndexMap, class P, class T, + class R > + static std::pair< std::size_t, OutputIterator > apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + const bgl_named_params< P, T, R >& params, DiscoverTimeMap dtm) + { + typedef typename get_param_type< vertex_lowpoint_t, + bgl_named_params< P, T, R > >::type dispatch_type; + + return bicomp_dispatch2< dispatch_type >::apply(g, comp, out, + index_map, dtm, params, get_param(params, vertex_lowpoint)); + } + }; + + template <> struct bicomp_dispatch1< param_not_found > + { + template < typename Graph, typename ComponentMap, + typename OutputIterator, typename VertexIndexMap, class P, class T, + class R > + static std::pair< std::size_t, OutputIterator > apply(const Graph& g, + ComponentMap comp, OutputIterator out, VertexIndexMap index_map, + const bgl_named_params< P, T, R >& params, param_not_found) + { + typedef typename graph_traits< Graph >::vertices_size_type + vertices_size_type; + std::vector< vertices_size_type > discover_time(num_vertices(g)); + vertices_size_type vst(0); + + typedef typename get_param_type< vertex_lowpoint_t, + bgl_named_params< P, T, R > >::type dispatch_type; + + return bicomp_dispatch2< dispatch_type >::apply(g, comp, out, + index_map, + make_iterator_property_map( + discover_time.begin(), index_map, vst), + params, get_param(params, vertex_lowpoint)); + } + }; + +} + +template < typename Graph, typename ComponentMap, typename OutputIterator, + typename DiscoverTimeMap, typename LowPointMap > +std::pair< std::size_t, OutputIterator > biconnected_components(const Graph& g, + ComponentMap comp, OutputIterator out, DiscoverTimeMap dtm, + LowPointMap lowpt) +{ + typedef param_not_found dispatch_type; + + return detail::bicomp_dispatch3< dispatch_type >::apply(g, comp, out, + get(vertex_index, g), dtm, lowpt, + bgl_named_params< int, buffer_param_t >(0), param_not_found()); +} + +template < typename Graph, typename ComponentMap, typename OutputIterator, + typename P, typename T, typename R > +std::pair< std::size_t, OutputIterator > biconnected_components(const Graph& g, + ComponentMap comp, OutputIterator out, + const bgl_named_params< P, T, R >& params) +{ + typedef typename get_param_type< vertex_discover_time_t, + bgl_named_params< P, T, R > >::type dispatch_type; + + return detail::bicomp_dispatch1< dispatch_type >::apply(g, comp, out, + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + params, get_param(params, vertex_discover_time)); +} + +template < typename Graph, typename ComponentMap, typename OutputIterator > +std::pair< std::size_t, OutputIterator > biconnected_components( + const Graph& g, ComponentMap comp, OutputIterator out) +{ + return biconnected_components( + g, comp, out, bgl_named_params< int, buffer_param_t >(0)); +} + +namespace graph_detail +{ + struct dummy_output_iterator + { + typedef std::output_iterator_tag iterator_category; + typedef void value_type; + typedef void pointer; + typedef void difference_type; + + struct reference + { + template < typename T > reference& operator=(const T&) + { + return *this; + } + }; + + reference operator*() const { return reference(); } + dummy_output_iterator& operator++() { return *this; } + dummy_output_iterator operator++(int) { return *this; } + }; +} // end namespace graph_detail + +template < typename Graph, typename ComponentMap, typename P, typename T, + typename R > +std::size_t biconnected_components(const Graph& g, ComponentMap comp, + const bgl_named_params< P, T, R >& params) +{ + return biconnected_components( + g, comp, graph_detail::dummy_output_iterator(), params) + .first; +} + +template < typename Graph, typename ComponentMap > +std::size_t biconnected_components(const Graph& g, ComponentMap comp) +{ + return biconnected_components( + g, comp, graph_detail::dummy_output_iterator()) + .first; +} + +template < typename Graph, typename OutputIterator, typename P, typename T, + typename R > +OutputIterator articulation_points(const Graph& g, OutputIterator out, + const bgl_named_params< P, T, R >& params) +{ + return biconnected_components(g, dummy_property_map(), out, params).second; +} + +template < typename Graph, typename OutputIterator > +OutputIterator articulation_points(const Graph& g, OutputIterator out) +{ + return biconnected_components(g, dummy_property_map(), out, + bgl_named_params< int, buffer_param_t >(0)) + .second; +} + +} // namespace boost + +#endif /* BOOST_GRAPH_BICONNECTED_COMPONENTS_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/graph/bipartite.hpp b/contrib/restricted/boost/graph/include/boost/graph/bipartite.hpp new file mode 100644 index 0000000000..21382840c3 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/bipartite.hpp @@ -0,0 +1,403 @@ +/** + * + * Copyright (c) 2010 Matthias Walter (xammy@xammy.homelinux.net) + * + * Authors: Matthias Walter + * + * Distributed under the Boost Software License, Version 1.0. (See + * accompanying file LICENSE_1_0.txt or copy at + * http://www.boost.org/LICENSE_1_0.txt) + * + */ + +#ifndef BOOST_GRAPH_BIPARTITE_HPP +#define BOOST_GRAPH_BIPARTITE_HPP + +#include <utility> +#include <vector> +#include <exception> +#include <boost/graph/properties.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/depth_first_search.hpp> +#include <boost/graph/one_bit_color_map.hpp> + +namespace boost +{ + +namespace detail +{ + + /** + * The bipartite_visitor_error is thrown if an edge cannot be colored. + * The witnesses are the edges incident vertices. + */ + + template < typename Vertex > + struct BOOST_SYMBOL_VISIBLE bipartite_visitor_error : std::exception + { + std::pair< Vertex, Vertex > witnesses; + + bipartite_visitor_error(Vertex a, Vertex b) : witnesses(a, b) {} + + const char* what() const noexcept { return "Graph is not bipartite."; } + }; + + /** + * Functor which colors edges to be non-monochromatic. + */ + + template < typename PartitionMap > struct bipartition_colorize + { + typedef on_tree_edge event_filter; + + bipartition_colorize(PartitionMap partition_map) + : partition_map_(partition_map) + { + } + + template < typename Edge, typename Graph > + void operator()(Edge e, const Graph& g) + { + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor_t; + typedef color_traits< + typename property_traits< PartitionMap >::value_type > + color_traits; + + vertex_descriptor_t source_vertex = source(e, g); + vertex_descriptor_t target_vertex = target(e, g); + if (get(partition_map_, source_vertex) == color_traits::white()) + put(partition_map_, target_vertex, color_traits::black()); + else + put(partition_map_, target_vertex, color_traits::white()); + } + + private: + PartitionMap partition_map_; + }; + + /** + * Creates a bipartition_colorize functor which colors edges + * to be non-monochromatic. + * + * @param partition_map Color map for the bipartition + * @return The functor. + */ + + template < typename PartitionMap > + inline bipartition_colorize< PartitionMap > colorize_bipartition( + PartitionMap partition_map) + { + return bipartition_colorize< PartitionMap >(partition_map); + } + + /** + * Functor which tests an edge to be monochromatic. + */ + + template < typename PartitionMap > struct bipartition_check + { + typedef on_back_edge event_filter; + + bipartition_check(PartitionMap partition_map) + : partition_map_(partition_map) + { + } + + template < typename Edge, typename Graph > + void operator()(Edge e, const Graph& g) + { + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor_t; + + vertex_descriptor_t source_vertex = source(e, g); + vertex_descriptor_t target_vertex = target(e, g); + if (get(partition_map_, source_vertex) + == get(partition_map_, target_vertex)) + throw bipartite_visitor_error< vertex_descriptor_t >( + source_vertex, target_vertex); + } + + private: + PartitionMap partition_map_; + }; + + /** + * Creates a bipartition_check functor which raises an error if a + * monochromatic edge is found. + * + * @param partition_map The map for a bipartition. + * @return The functor. + */ + + template < typename PartitionMap > + inline bipartition_check< PartitionMap > check_bipartition( + PartitionMap partition_map) + { + return bipartition_check< PartitionMap >(partition_map); + } + + /** + * Find the beginning of a common suffix of two sequences + * + * @param sequence1 Pair of bidirectional iterators defining the first + * sequence. + * @param sequence2 Pair of bidirectional iterators defining the second + * sequence. + * @return Pair of iterators pointing to the beginning of the common suffix. + */ + + template < typename BiDirectionalIterator1, + typename BiDirectionalIterator2 > + inline std::pair< BiDirectionalIterator1, BiDirectionalIterator2 > + reverse_mismatch( + std::pair< BiDirectionalIterator1, BiDirectionalIterator1 > sequence1, + std::pair< BiDirectionalIterator2, BiDirectionalIterator2 > sequence2) + { + if (sequence1.first == sequence1.second + || sequence2.first == sequence2.second) + return std::make_pair(sequence1.first, sequence2.first); + + BiDirectionalIterator1 iter1 = sequence1.second; + BiDirectionalIterator2 iter2 = sequence2.second; + + while (true) + { + --iter1; + --iter2; + if (*iter1 != *iter2) + { + ++iter1; + ++iter2; + break; + } + if (iter1 == sequence1.first) + break; + if (iter2 == sequence2.first) + break; + } + + return std::make_pair(iter1, iter2); + } + +} + +/** + * Checks a given graph for bipartiteness and fills the given color map with + * white and black according to the bipartition. If the graph is not + * bipartite, the contents of the color map are undefined. Runs in linear + * time in the size of the graph, if access to the property maps is in + * constant time. + * + * @param graph The given graph. + * @param index_map An index map associating vertices with an index. + * @param partition_map A color map to fill with the bipartition. + * @return true if and only if the given graph is bipartite. + */ + +template < typename Graph, typename IndexMap, typename PartitionMap > +bool is_bipartite( + const Graph& graph, const IndexMap index_map, PartitionMap partition_map) +{ + /// General types and variables + typedef + typename property_traits< PartitionMap >::value_type partition_color_t; + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + + /// Declare dfs visitor + // detail::empty_recorder recorder; + // typedef detail::bipartite_visitor <PartitionMap, + // detail::empty_recorder> dfs_visitor_t; dfs_visitor_t dfs_visitor + // (partition_map, recorder); + + /// Call dfs + try + { + depth_first_search(graph, + vertex_index_map(index_map).visitor(make_dfs_visitor( + std::make_pair(detail::colorize_bipartition(partition_map), + std::make_pair(detail::check_bipartition(partition_map), + put_property(partition_map, + color_traits< partition_color_t >::white(), + on_start_vertex())))))); + } + catch (const detail::bipartite_visitor_error< vertex_descriptor_t >&) + { + return false; + } + + return true; +} + +/** + * Checks a given graph for bipartiteness. + * + * @param graph The given graph. + * @param index_map An index map associating vertices with an index. + * @return true if and only if the given graph is bipartite. + */ + +template < typename Graph, typename IndexMap > +bool is_bipartite(const Graph& graph, const IndexMap index_map) +{ + typedef one_bit_color_map< IndexMap > partition_map_t; + partition_map_t partition_map(num_vertices(graph), index_map); + + return is_bipartite(graph, index_map, partition_map); +} + +/** + * Checks a given graph for bipartiteness. The graph must + * have an internal vertex_index property. Runs in linear time in the + * size of the graph, if access to the property maps is in constant time. + * + * @param graph The given graph. + * @return true if and only if the given graph is bipartite. + */ + +template < typename Graph > bool is_bipartite(const Graph& graph) +{ + return is_bipartite(graph, get(vertex_index, graph)); +} + +/** + * Checks a given graph for bipartiteness and fills a given color map with + * white and black according to the bipartition. If the graph is not + * bipartite, a sequence of vertices, producing an odd-cycle, is written to + * the output iterator. The final iterator value is returned. Runs in linear + * time in the size of the graph, if access to the property maps is in + * constant time. + * + * @param graph The given graph. + * @param index_map An index map associating vertices with an index. + * @param partition_map A color map to fill with the bipartition. + * @param result An iterator to write the odd-cycle vertices to. + * @return The final iterator value after writing. + */ + +template < typename Graph, typename IndexMap, typename PartitionMap, + typename OutputIterator > +OutputIterator find_odd_cycle(const Graph& graph, const IndexMap index_map, + PartitionMap partition_map, OutputIterator result) +{ + /// General types and variables + typedef + typename property_traits< PartitionMap >::value_type partition_color_t; + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + vertex_iterator_t vertex_iter, vertex_end; + + /// Declare predecessor map + typedef std::vector< vertex_descriptor_t > predecessors_t; + typedef iterator_property_map< typename predecessors_t::iterator, IndexMap, + vertex_descriptor_t, vertex_descriptor_t& > + predecessor_map_t; + + predecessors_t predecessors( + num_vertices(graph), graph_traits< Graph >::null_vertex()); + predecessor_map_t predecessor_map(predecessors.begin(), index_map); + + /// Initialize predecessor map + for (boost::tie(vertex_iter, vertex_end) = vertices(graph); + vertex_iter != vertex_end; ++vertex_iter) + { + put(predecessor_map, *vertex_iter, *vertex_iter); + } + + /// Call dfs + try + { + depth_first_search(graph, + vertex_index_map(index_map).visitor(make_dfs_visitor( + std::make_pair(detail::colorize_bipartition(partition_map), + std::make_pair(detail::check_bipartition(partition_map), + std::make_pair( + put_property(partition_map, + color_traits< partition_color_t >::white(), + on_start_vertex()), + record_predecessors( + predecessor_map, on_tree_edge()))))))); + } + catch (const detail::bipartite_visitor_error< vertex_descriptor_t >& error) + { + typedef std::vector< vertex_descriptor_t > path_t; + + path_t path1, path2; + vertex_descriptor_t next, current; + + /// First path + next = error.witnesses.first; + do + { + current = next; + path1.push_back(current); + next = predecessor_map[current]; + } while (current != next); + + /// Second path + next = error.witnesses.second; + do + { + current = next; + path2.push_back(current); + next = predecessor_map[current]; + } while (current != next); + + /// Find beginning of common suffix + std::pair< typename path_t::iterator, typename path_t::iterator > + mismatch = detail::reverse_mismatch( + std::make_pair(path1.begin(), path1.end()), + std::make_pair(path2.begin(), path2.end())); + + /// Copy the odd-length cycle + result = std::copy(path1.begin(), mismatch.first + 1, result); + return std::reverse_copy(path2.begin(), mismatch.second, result); + } + + return result; +} + +/** + * Checks a given graph for bipartiteness. If the graph is not bipartite, a + * sequence of vertices, producing an odd-cycle, is written to the output + * iterator. The final iterator value is returned. Runs in linear time in the + * size of the graph, if access to the property maps is in constant time. + * + * @param graph The given graph. + * @param index_map An index map associating vertices with an index. + * @param result An iterator to write the odd-cycle vertices to. + * @return The final iterator value after writing. + */ + +template < typename Graph, typename IndexMap, typename OutputIterator > +OutputIterator find_odd_cycle( + const Graph& graph, const IndexMap index_map, OutputIterator result) +{ + typedef one_bit_color_map< IndexMap > partition_map_t; + partition_map_t partition_map(num_vertices(graph), index_map); + + return find_odd_cycle(graph, index_map, partition_map, result); +} + +/** + * Checks a given graph for bipartiteness. If the graph is not bipartite, a + * sequence of vertices, producing an odd-cycle, is written to the output + * iterator. The final iterator value is returned. The graph must have an + * internal vertex_index property. Runs in linear time in the size of the + * graph, if access to the property maps is in constant time. + * + * @param graph The given graph. + * @param result An iterator to write the odd-cycle vertices to. + * @return The final iterator value after writing. + */ + +template < typename Graph, typename OutputIterator > +OutputIterator find_odd_cycle(const Graph& graph, OutputIterator result) +{ + return find_odd_cycle(graph, get(vertex_index, graph), result); +} +} + +#endif /// BOOST_GRAPH_BIPARTITE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/boyer_myrvold_planar_test.hpp b/contrib/restricted/boost/graph/include/boost/graph/boyer_myrvold_planar_test.hpp new file mode 100644 index 0000000000..34a476b50e --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/boyer_myrvold_planar_test.hpp @@ -0,0 +1,262 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __BOYER_MYRVOLD_PLANAR_TEST_HPP__ +#define __BOYER_MYRVOLD_PLANAR_TEST_HPP__ + +#include <boost/graph/planar_detail/boyer_myrvold_impl.hpp> +#include <boost/parameter.hpp> +#include <boost/type_traits.hpp> +#include <boost/mpl/bool.hpp> + +namespace boost +{ + +struct no_kuratowski_subgraph_isolation +{ +}; +struct no_planar_embedding +{ +}; + +namespace boyer_myrvold_params +{ + + BOOST_PARAMETER_KEYWORD(tag, graph) + BOOST_PARAMETER_KEYWORD(tag, embedding) + BOOST_PARAMETER_KEYWORD(tag, kuratowski_subgraph) + BOOST_PARAMETER_KEYWORD(tag, vertex_index_map) + BOOST_PARAMETER_KEYWORD(tag, edge_index_map) + + typedef parameter::parameters< parameter::required< tag::graph >, + tag::embedding, tag::kuratowski_subgraph, tag::vertex_index_map, + tag::edge_index_map > + boyer_myrvold_params_t; + + namespace core + { + + template < typename ArgumentPack > + bool dispatched_boyer_myrvold( + ArgumentPack const& args, mpl::true_, mpl::true_) + { + // Dispatch for no planar embedding, no kuratowski subgraph + // isolation + + typedef typename remove_const< typename parameter::value_type< + ArgumentPack, tag::graph >::type >::type graph_t; + + typedef typename property_map< graph_t, vertex_index_t >::const_type + vertex_default_index_map_t; + + typedef typename parameter::value_type< ArgumentPack, + tag::vertex_index_map, vertex_default_index_map_t >::type + vertex_index_map_t; + + graph_t const& g = args[graph]; + vertex_default_index_map_t v_d_map = get(vertex_index, g); + vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map]; + boyer_myrvold_impl< graph_t, vertex_index_map_t, + graph::detail::no_old_handles, graph::detail::no_embedding > + planarity_tester(g, v_i_map); + + return planarity_tester.is_planar() ? true : false; + } + + template < typename ArgumentPack > + bool dispatched_boyer_myrvold( + ArgumentPack const& args, mpl::true_, mpl::false_) + { + // Dispatch for no planar embedding, kuratowski subgraph isolation + typedef typename remove_const< typename parameter::value_type< + ArgumentPack, tag::graph >::type >::type graph_t; + + typedef typename property_map< graph_t, vertex_index_t >::const_type + vertex_default_index_map_t; + + typedef typename parameter::value_type< ArgumentPack, + tag::vertex_index_map, vertex_default_index_map_t >::type + vertex_index_map_t; + + typedef typename property_map< graph_t, edge_index_t >::const_type + edge_default_index_map_t; + + typedef typename parameter::value_type< ArgumentPack, + tag::edge_index_map, edge_default_index_map_t >::type + edge_index_map_t; + + graph_t const& g = args[graph]; + vertex_default_index_map_t v_d_map = get(vertex_index, g); + vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map]; + edge_default_index_map_t e_d_map = get(edge_index, g); + edge_index_map_t e_i_map = args[edge_index_map | e_d_map]; + boyer_myrvold_impl< graph_t, vertex_index_map_t, + graph::detail::store_old_handles, graph::detail::no_embedding > + planarity_tester(g, v_i_map); + + if (planarity_tester.is_planar()) + return true; + else + { + planarity_tester.extract_kuratowski_subgraph( + args[kuratowski_subgraph], e_i_map); + return false; + } + } + + template < typename ArgumentPack > + bool dispatched_boyer_myrvold( + ArgumentPack const& args, mpl::false_, mpl::true_) + { + // Dispatch for planar embedding, no kuratowski subgraph isolation + typedef typename remove_const< typename parameter::value_type< + ArgumentPack, tag::graph >::type >::type graph_t; + + typedef typename property_map< graph_t, vertex_index_t >::const_type + vertex_default_index_map_t; + + typedef typename parameter::value_type< ArgumentPack, + tag::vertex_index_map, vertex_default_index_map_t >::type + vertex_index_map_t; + + graph_t const& g = args[graph]; + vertex_default_index_map_t v_d_map = get(vertex_index, g); + vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map]; + boyer_myrvold_impl< graph_t, vertex_index_map_t, + graph::detail::no_old_handles, +#ifdef BOOST_GRAPH_PREFER_STD_LIB + graph::detail::std_list +#else + graph::detail::recursive_lazy_list +#endif + > + planarity_tester(g, v_i_map); + + if (planarity_tester.is_planar()) + { + planarity_tester.make_edge_permutation(args[embedding]); + return true; + } + else + return false; + } + + template < typename ArgumentPack > + bool dispatched_boyer_myrvold( + ArgumentPack const& args, mpl::false_, mpl::false_) + { + // Dispatch for planar embedding, kuratowski subgraph isolation + typedef typename remove_const< typename parameter::value_type< + ArgumentPack, tag::graph >::type >::type graph_t; + + typedef typename property_map< graph_t, vertex_index_t >::const_type + vertex_default_index_map_t; + + typedef typename parameter::value_type< ArgumentPack, + tag::vertex_index_map, vertex_default_index_map_t >::type + vertex_index_map_t; + + typedef typename property_map< graph_t, edge_index_t >::const_type + edge_default_index_map_t; + + typedef typename parameter::value_type< ArgumentPack, + tag::edge_index_map, edge_default_index_map_t >::type + edge_index_map_t; + + graph_t const& g = args[graph]; + vertex_default_index_map_t v_d_map = get(vertex_index, g); + vertex_index_map_t v_i_map = args[vertex_index_map | v_d_map]; + edge_default_index_map_t e_d_map = get(edge_index, g); + edge_index_map_t e_i_map = args[edge_index_map | e_d_map]; + boyer_myrvold_impl< graph_t, vertex_index_map_t, + graph::detail::store_old_handles, +#ifdef BOOST_BGL_PREFER_STD_LIB + graph::detail::std_list +#else + graph::detail::recursive_lazy_list +#endif + > + planarity_tester(g, v_i_map); + + if (planarity_tester.is_planar()) + { + planarity_tester.make_edge_permutation(args[embedding]); + return true; + } + else + { + planarity_tester.extract_kuratowski_subgraph( + args[kuratowski_subgraph], e_i_map); + return false; + } + } + + template < typename ArgumentPack > + bool boyer_myrvold_planarity_test(ArgumentPack const& args) + { + + typedef typename parameter::binding< ArgumentPack, + tag::kuratowski_subgraph, + const no_kuratowski_subgraph_isolation& >::type + kuratowski_arg_t; + + typedef typename parameter::binding< ArgumentPack, tag::embedding, + const no_planar_embedding& >::type embedding_arg_t; + + return dispatched_boyer_myrvold(args, + boost::is_same< embedding_arg_t, const no_planar_embedding& >(), + boost::is_same< kuratowski_arg_t, + const no_kuratowski_subgraph_isolation& >()); + } + + } // namespace core + +} // namespace boyer_myrvold_params + +template < typename A0 > bool boyer_myrvold_planarity_test(A0 const& arg0) +{ + return boyer_myrvold_params::core::boyer_myrvold_planarity_test( + boyer_myrvold_params::boyer_myrvold_params_t()(arg0)); +} + +template < typename A0, typename A1 > +// bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1) +bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1) +{ + return boyer_myrvold_params::core::boyer_myrvold_planarity_test( + boyer_myrvold_params::boyer_myrvold_params_t()(arg0, arg1)); +} + +template < typename A0, typename A1, typename A2 > +bool boyer_myrvold_planarity_test( + A0 const& arg0, A1 const& arg1, A2 const& arg2) +{ + return boyer_myrvold_params::core::boyer_myrvold_planarity_test( + boyer_myrvold_params::boyer_myrvold_params_t()(arg0, arg1, arg2)); +} + +template < typename A0, typename A1, typename A2, typename A3 > +bool boyer_myrvold_planarity_test( + A0 const& arg0, A1 const& arg1, A2 const& arg2, A3 const& arg3) +{ + return boyer_myrvold_params::core::boyer_myrvold_planarity_test( + boyer_myrvold_params::boyer_myrvold_params_t()(arg0, arg1, arg2, arg3)); +} + +template < typename A0, typename A1, typename A2, typename A3, typename A4 > +bool boyer_myrvold_planarity_test(A0 const& arg0, A1 const& arg1, + A2 const& arg2, A3 const& arg3, A4 const& arg4) +{ + return boyer_myrvold_params::core::boyer_myrvold_planarity_test( + boyer_myrvold_params::boyer_myrvold_params_t()( + arg0, arg1, arg2, arg3, arg4)); +} + +} + +#endif //__BOYER_MYRVOLD_PLANAR_TEST_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/bron_kerbosch_all_cliques.hpp b/contrib/restricted/boost/graph/include/boost/graph/bron_kerbosch_all_cliques.hpp new file mode 100644 index 0000000000..e0f862e837 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/bron_kerbosch_all_cliques.hpp @@ -0,0 +1,312 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_CLIQUE_HPP +#define BOOST_GRAPH_CLIQUE_HPP + +#include <vector> +#include <deque> +#include <boost/config.hpp> + +#include <boost/concept/assert.hpp> + +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/lookup_edge.hpp> + +#include <boost/concept/detail/concept_def.hpp> +namespace boost +{ +namespace concepts +{ + BOOST_concept(CliqueVisitor, (Visitor)(Clique)(Graph)) + { + BOOST_CONCEPT_USAGE(CliqueVisitor) { vis.clique(k, g); } + + private: + Visitor vis; + Graph g; + Clique k; + }; +} /* namespace concepts */ +using concepts::CliqueVisitorConcept; +} /* namespace boost */ +#include <boost/concept/detail/concept_undef.hpp> + +namespace boost +{ +// The algorithm implemented in this paper is based on the so-called +// Algorithm 457, published as: +// +// @article{362367, +// author = {Coen Bron and Joep Kerbosch}, +// title = {Algorithm 457: finding all cliques of an undirected graph}, +// journal = {Communications of the ACM}, +// volume = {16}, +// number = {9}, +// year = {1973}, +// issn = {0001-0782}, +// pages = {575--577}, +// doi = {http://doi.acm.org/10.1145/362342.362367}, +// publisher = {ACM Press}, +// address = {New York, NY, USA}, +// } +// +// Sort of. This implementation is adapted from the 1st version of the +// algorithm and does not implement the candidate selection optimization +// described as published - it could, it just doesn't yet. +// +// The algorithm is given as proportional to (3.14)^(n/3) power. This is +// not the same as O(...), but based on time measures and approximation. +// +// Unfortunately, this implementation may be less efficient on non- +// AdjacencyMatrix modeled graphs due to the non-constant implementation +// of the edge(u,v,g) functions. +// +// TODO: It might be worthwhile to provide functionality for passing +// a connectivity matrix to improve the efficiency of those lookups +// when needed. This could simply be passed as a BooleanMatrix +// s.t. edge(u,v,B) returns true or false. This could easily be +// abstracted for adjacency matricies. +// +// The following paper is interesting for a number of reasons. First, +// it lists a number of other such algorithms and second, it describes +// a new algorithm (that does not appear to require the edge(u,v,g) +// function and appears fairly efficient. It is probably worth investigating. +// +// @article{DBLP:journals/tcs/TomitaTT06, +// author = {Etsuji Tomita and Akira Tanaka and Haruhisa Takahashi}, +// title = {The worst-case time complexity for generating all maximal +// cliques and computational experiments}, journal = {Theor. Comput. +// Sci.}, volume = {363}, number = {1}, year = {2006}, pages = {28-42} +// ee = {https://doi.org/10.1016/j.tcs.2006.06.015} +// } + +/** + * The default clique_visitor supplies an empty visitation function. + */ +struct clique_visitor +{ + template < typename VertexSet, typename Graph > + void clique(const VertexSet&, Graph&) + { + } +}; + +/** + * The max_clique_visitor records the size of the maximum clique (but not the + * clique itself). + */ +struct max_clique_visitor +{ + max_clique_visitor(std::size_t& max) : maximum(max) {} + + template < typename Clique, typename Graph > + inline void clique(const Clique& p, const Graph& g) + { + BOOST_USING_STD_MAX(); + maximum = max BOOST_PREVENT_MACRO_SUBSTITUTION(maximum, p.size()); + } + std::size_t& maximum; +}; + +inline max_clique_visitor find_max_clique(std::size_t& max) +{ + return max_clique_visitor(max); +} + +namespace detail +{ + template < typename Graph > + inline bool is_connected_to_clique(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor u, + typename graph_traits< Graph >::vertex_descriptor v, + typename graph_traits< Graph >::undirected_category) + { + return lookup_edge(u, v, g).second; + } + + template < typename Graph > + inline bool is_connected_to_clique(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor u, + typename graph_traits< Graph >::vertex_descriptor v, + typename graph_traits< Graph >::directed_category) + { + // Note that this could alternate between using an || to determine + // full connectivity. I believe that this should produce strongly + // connected components. Note that using && instead of || will + // change the results to a fully connected subgraph (i.e., symmetric + // edges between all vertices s.t., if a->b, then b->a. + return lookup_edge(u, v, g).second && lookup_edge(v, u, g).second; + } + + template < typename Graph, typename Container > + inline void filter_unconnected_vertices(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor v, + const Container& in, Container& out) + { + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + + typename graph_traits< Graph >::directed_category cat; + typename Container::const_iterator i, end = in.end(); + for (i = in.begin(); i != end; ++i) + { + if (is_connected_to_clique(g, v, *i, cat)) + { + out.push_back(*i); + } + } + } + + template < typename Graph, + typename Clique, // compsub type + typename Container, // candidates/not type + typename Visitor > + void extend_clique(const Graph& g, Clique& clique, Container& cands, + Container& nots, Visitor vis, std::size_t min) + { + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< Visitor, Clique, Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + // Is there vertex in nots that is connected to all vertices + // in the candidate set? If so, no clique can ever be found. + // This could be broken out into a separate function. + { + typename Container::iterator ni, nend = nots.end(); + typename Container::iterator ci, cend = cands.end(); + for (ni = nots.begin(); ni != nend; ++ni) + { + for (ci = cands.begin(); ci != cend; ++ci) + { + // if we don't find an edge, then we're okay. + if (!lookup_edge(*ni, *ci, g).second) + break; + } + // if we iterated all the way to the end, then *ni + // is connected to all *ci + if (ci == cend) + break; + } + // if we broke early, we found *ni connected to all *ci + if (ni != nend) + return; + } + + // TODO: the original algorithm 457 describes an alternative + // (albeit really complicated) mechanism for selecting candidates. + // The given optimizaiton seeks to bring about the above + // condition sooner (i.e., there is a vertex in the not set + // that is connected to all candidates). unfortunately, the + // method they give for doing this is fairly unclear. + + // basically, for every vertex in not, we should know how many + // vertices it is disconnected from in the candidate set. if + // we fix some vertex in the not set, then we want to keep + // choosing vertices that are not connected to that fixed vertex. + // apparently, by selecting fix point with the minimum number + // of disconnections (i.e., the maximum number of connections + // within the candidate set), then the previous condition wil + // be reached sooner. + + // there's some other stuff about using the number of disconnects + // as a counter, but i'm jot really sure i followed it. + + // TODO: If we min-sized cliques to visit, then theoretically, we + // should be able to stop recursing if the clique falls below that + // size - maybe? + + // otherwise, iterate over candidates and and test + // for maxmimal cliquiness. + typename Container::iterator i, j; + for (i = cands.begin(); i != cands.end();) + { + Vertex candidate = *i; + + // add the candidate to the clique (keeping the iterator!) + // typename Clique::iterator ci = clique.insert(clique.end(), + // candidate); + clique.push_back(candidate); + + // remove it from the candidate set + i = cands.erase(i); + + // build new candidate and not sets by removing all vertices + // that are not connected to the current candidate vertex. + // these actually invert the operation, adding them to the new + // sets if the vertices are connected. its semantically the same. + Container new_cands, new_nots; + filter_unconnected_vertices(g, candidate, cands, new_cands); + filter_unconnected_vertices(g, candidate, nots, new_nots); + + if (new_cands.empty() && new_nots.empty()) + { + // our current clique is maximal since there's nothing + // that's connected that we haven't already visited. If + // the clique is below our radar, then we won't visit it. + if (clique.size() >= min) + { + vis.clique(clique, g); + } + } + else + { + // recurse to explore the new candidates + extend_clique(g, clique, new_cands, new_nots, vis, min); + } + + // we're done with this vertex, so we need to move it + // to the nots, and remove the candidate from the clique. + nots.push_back(candidate); + clique.pop_back(); + } + } +} /* namespace detail */ + +template < typename Graph, typename Visitor > +inline void bron_kerbosch_all_cliques( + const Graph& g, Visitor vis, std::size_t min) +{ + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT( + (AdjacencyMatrixConcept< Graph >)); // Structural requirement only + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + typedef std::vector< Vertex > VertexSet; + typedef std::deque< Vertex > Clique; + BOOST_CONCEPT_ASSERT((CliqueVisitorConcept< Visitor, Clique, Graph >)); + + // NOTE: We're using a deque to implement the clique, because it provides + // constant inserts and removals at the end and also a constant size. + + VertexIterator i, end; + boost::tie(i, end) = vertices(g); + VertexSet cands(i, end); // start with all vertices as candidates + VertexSet nots; // start with no vertices visited + + Clique clique; // the first clique is an empty vertex set + detail::extend_clique(g, clique, cands, nots, vis, min); +} + +// NOTE: By default the minimum number of vertices per clique is set at 2 +// because singleton cliques aren't really very interesting. +template < typename Graph, typename Visitor > +inline void bron_kerbosch_all_cliques(const Graph& g, Visitor vis) +{ + bron_kerbosch_all_cliques(g, vis, 2); +} + +template < typename Graph > +inline std::size_t bron_kerbosch_clique_number(const Graph& g) +{ + std::size_t ret = 0; + bron_kerbosch_all_cliques(g, find_max_clique(ret)); + return ret; +} + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/chrobak_payne_drawing.hpp b/contrib/restricted/boost/graph/include/boost/graph/chrobak_payne_drawing.hpp new file mode 100644 index 0000000000..68106267ce --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/chrobak_payne_drawing.hpp @@ -0,0 +1,251 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __CHROBAK_PAYNE_DRAWING_HPP__ +#define __CHROBAK_PAYNE_DRAWING_HPP__ + +#include <vector> +#include <list> +#include <stack> +#include <boost/config.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +namespace graph +{ + namespace detail + { + + template < typename Graph, typename VertexToVertexMap, + typename VertexTo1DCoordMap > + void accumulate_offsets( + typename graph_traits< Graph >::vertex_descriptor v, + std::size_t offset, const Graph& g, VertexTo1DCoordMap x, + VertexTo1DCoordMap delta_x, VertexToVertexMap left, + VertexToVertexMap right) + { + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + // Suggestion of explicit stack from Aaron Windsor to avoid system + // stack overflows. + typedef std::pair< vertex_descriptor, std::size_t > stack_entry; + std::stack< stack_entry > st; + st.push(stack_entry(v, offset)); + while (!st.empty()) + { + vertex_descriptor v = st.top().first; + std::size_t offset = st.top().second; + st.pop(); + if (v != graph_traits< Graph >::null_vertex()) + { + x[v] += delta_x[v] + offset; + st.push(stack_entry(left[v], x[v])); + st.push(stack_entry(right[v], x[v])); + } + } + } + + } /*namespace detail*/ +} /*namespace graph*/ + +template < typename Graph, typename PlanarEmbedding, typename ForwardIterator, + typename GridPositionMap, typename VertexIndexMap > +void chrobak_payne_straight_line_drawing(const Graph& g, + PlanarEmbedding embedding, ForwardIterator ordering_begin, + ForwardIterator ordering_end, GridPositionMap drawing, VertexIndexMap vm) +{ + + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename PlanarEmbedding::value_type::const_iterator + edge_permutation_iterator_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + typedef std::vector< vertex_t > vertex_vector_t; + typedef std::vector< v_size_t > vsize_vector_t; + typedef std::vector< bool > bool_vector_t; + typedef boost::iterator_property_map< typename vertex_vector_t::iterator, + VertexIndexMap > + vertex_to_vertex_map_t; + typedef boost::iterator_property_map< typename vsize_vector_t::iterator, + VertexIndexMap > + vertex_to_vsize_map_t; + typedef boost::iterator_property_map< typename bool_vector_t::iterator, + VertexIndexMap > + vertex_to_bool_map_t; + + vertex_vector_t left_vector( + num_vertices(g), graph_traits< Graph >::null_vertex()); + vertex_vector_t right_vector( + num_vertices(g), graph_traits< Graph >::null_vertex()); + vsize_vector_t seen_as_right_vector(num_vertices(g), 0); + vsize_vector_t seen_vector(num_vertices(g), 0); + vsize_vector_t delta_x_vector(num_vertices(g), 0); + vsize_vector_t y_vector(num_vertices(g)); + vsize_vector_t x_vector(num_vertices(g), 0); + bool_vector_t installed_vector(num_vertices(g), false); + + vertex_to_vertex_map_t left(left_vector.begin(), vm); + vertex_to_vertex_map_t right(right_vector.begin(), vm); + vertex_to_vsize_map_t seen_as_right(seen_as_right_vector.begin(), vm); + vertex_to_vsize_map_t seen(seen_vector.begin(), vm); + vertex_to_vsize_map_t delta_x(delta_x_vector.begin(), vm); + vertex_to_vsize_map_t y(y_vector.begin(), vm); + vertex_to_vsize_map_t x(x_vector.begin(), vm); + vertex_to_bool_map_t installed(installed_vector.begin(), vm); + + v_size_t timestamp = 1; + vertex_vector_t installed_neighbors; + + ForwardIterator itr = ordering_begin; + vertex_t v1 = *itr; + ++itr; + vertex_t v2 = *itr; + ++itr; + vertex_t v3 = *itr; + ++itr; + + delta_x[v2] = 1; + delta_x[v3] = 1; + + y[v1] = 0; + y[v2] = 0; + y[v3] = 1; + + right[v1] = v3; + right[v3] = v2; + + installed[v1] = installed[v2] = installed[v3] = true; + + for (ForwardIterator itr_end = ordering_end; itr != itr_end; ++itr) + { + vertex_t v = *itr; + + // First, find the leftmost and rightmost neighbor of v on the outer + // cycle of the embedding. + // Note: since we're moving clockwise through the edges adjacent to v, + // we're actually moving from right to left among v's neighbors on the + // outer face (since v will be installed above them all) looking for + // the leftmost and rightmost installed neigbhors + + vertex_t leftmost = graph_traits< Graph >::null_vertex(); + vertex_t rightmost = graph_traits< Graph >::null_vertex(); + + installed_neighbors.clear(); + + vertex_t prev_vertex = graph_traits< Graph >::null_vertex(); + edge_permutation_iterator_t pi, pi_end; + pi_end = embedding[v].end(); + for (pi = embedding[v].begin(); pi != pi_end; ++pi) + { + vertex_t curr_vertex + = source(*pi, g) == v ? target(*pi, g) : source(*pi, g); + + // Skip any self-loops or parallel edges + if (curr_vertex == v || curr_vertex == prev_vertex) + continue; + + if (installed[curr_vertex]) + { + seen[curr_vertex] = timestamp; + + if (right[curr_vertex] != graph_traits< Graph >::null_vertex()) + { + seen_as_right[right[curr_vertex]] = timestamp; + } + installed_neighbors.push_back(curr_vertex); + } + + prev_vertex = curr_vertex; + } + + typename vertex_vector_t::iterator vi, vi_end; + vi_end = installed_neighbors.end(); + for (vi = installed_neighbors.begin(); vi != vi_end; ++vi) + { + if (right[*vi] == graph_traits< Graph >::null_vertex() + || seen[right[*vi]] != timestamp) + rightmost = *vi; + if (seen_as_right[*vi] != timestamp) + leftmost = *vi; + } + + ++timestamp; + + // stretch gaps + ++delta_x[right[leftmost]]; + ++delta_x[rightmost]; + + // adjust offsets + std::size_t delta_p_q = 0; + vertex_t stopping_vertex = right[rightmost]; + for (vertex_t temp = right[leftmost]; temp != stopping_vertex; + temp = right[temp]) + { + delta_p_q += delta_x[temp]; + } + + delta_x[v] = ((y[rightmost] + delta_p_q) - y[leftmost]) / 2; + y[v] = y[leftmost] + delta_x[v]; + delta_x[rightmost] = delta_p_q - delta_x[v]; + + bool leftmost_and_rightmost_adjacent = right[leftmost] == rightmost; + if (!leftmost_and_rightmost_adjacent) + delta_x[right[leftmost]] -= delta_x[v]; + + // install v + if (!leftmost_and_rightmost_adjacent) + { + left[v] = right[leftmost]; + vertex_t next_to_rightmost; + for (vertex_t temp = leftmost; temp != rightmost; + temp = right[temp]) + { + next_to_rightmost = temp; + } + + right[next_to_rightmost] = graph_traits< Graph >::null_vertex(); + } + else + { + left[v] = graph_traits< Graph >::null_vertex(); + } + + right[leftmost] = v; + right[v] = rightmost; + installed[v] = true; + } + + graph::detail::accumulate_offsets( + *ordering_begin, 0, g, x, delta_x, left, right); + + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + drawing[v].x = x[v]; + drawing[v].y = y[v]; + } +} + +template < typename Graph, typename PlanarEmbedding, typename ForwardIterator, + typename GridPositionMap > +inline void chrobak_payne_straight_line_drawing(const Graph& g, + PlanarEmbedding embedding, ForwardIterator ord_begin, + ForwardIterator ord_end, GridPositionMap drawing) +{ + chrobak_payne_straight_line_drawing( + g, embedding, ord_begin, ord_end, drawing, get(vertex_index, g)); +} + +} // namespace boost + +#endif //__CHROBAK_PAYNE_DRAWING_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/circle_layout.hpp b/contrib/restricted/boost/graph/include/boost/graph/circle_layout.hpp new file mode 100644 index 0000000000..f295bd20b5 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/circle_layout.hpp @@ -0,0 +1,61 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_CIRCLE_LAYOUT_HPP +#define BOOST_GRAPH_CIRCLE_LAYOUT_HPP +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/math/constants/constants.hpp> +#include <utility> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/topology.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/static_assert.hpp> + +namespace boost +{ +/** + * \brief Layout the graph with the vertices at the points of a regular + * n-polygon. + * + * The distance from the center of the polygon to each point is + * determined by the @p radius parameter. The @p position parameter + * must be an Lvalue Property Map whose value type is a class type + * containing @c x and @c y members that will be set to the @c x and + * @c y coordinates. + */ +template < typename VertexListGraph, typename PositionMap, typename Radius > +void circle_graph_layout( + const VertexListGraph& g, PositionMap position, Radius radius) +{ + BOOST_STATIC_ASSERT( + property_traits< PositionMap >::value_type::dimensions >= 2); + const double pi = boost::math::constants::pi< double >(); + +#ifndef BOOST_NO_STDC_NAMESPACE + using std::cos; + using std::sin; +#endif // BOOST_NO_STDC_NAMESPACE + + typedef typename graph_traits< VertexListGraph >::vertices_size_type + vertices_size_type; + + vertices_size_type n = num_vertices(g); + + vertices_size_type i = 0; + double two_pi_over_n = 2. * pi / n; + BGL_FORALL_VERTICES_T(v, g, VertexListGraph) + { + position[v][0] = radius * cos(i * two_pi_over_n); + position[v][1] = radius * sin(i * two_pi_over_n); + ++i; + } +} +} // end namespace boost + +#endif // BOOST_GRAPH_CIRCLE_LAYOUT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/closeness_centrality.hpp b/contrib/restricted/boost/graph/include/boost/graph/closeness_centrality.hpp new file mode 100644 index 0000000000..d28123cad5 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/closeness_centrality.hpp @@ -0,0 +1,151 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_CLOSENESS_CENTRALITY_HPP +#define BOOST_GRAPH_CLOSENESS_CENTRALITY_HPP + +#include <boost/graph/detail/geodesic.hpp> +#include <boost/graph/exterior_property.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ +template < typename Graph, typename DistanceType, typename ResultType, + typename Reciprocal = detail::reciprocal< ResultType > > +struct closeness_measure +: public geodesic_measure< Graph, DistanceType, ResultType > +{ + typedef geodesic_measure< Graph, DistanceType, ResultType > base_type; + typedef typename base_type::distance_type distance_type; + typedef typename base_type::result_type result_type; + + result_type operator()(distance_type d, const Graph&) + { + BOOST_CONCEPT_ASSERT((NumericValueConcept< DistanceType >)); + BOOST_CONCEPT_ASSERT((NumericValueConcept< ResultType >)); + BOOST_CONCEPT_ASSERT((AdaptableUnaryFunctionConcept< Reciprocal, + ResultType, ResultType >)); + return (d == base_type::infinite_distance()) ? base_type::zero_result() + : rec(result_type(d)); + } + Reciprocal rec; +}; + +template < typename Graph, typename DistanceMap > +inline closeness_measure< Graph, + typename property_traits< DistanceMap >::value_type, double, + detail::reciprocal< double > > +measure_closeness(const Graph&, DistanceMap) +{ + typedef typename property_traits< DistanceMap >::value_type Distance; + return closeness_measure< Graph, Distance, double, + detail::reciprocal< double > >(); +} + +template < typename T, typename Graph, typename DistanceMap > +inline closeness_measure< Graph, + typename property_traits< DistanceMap >::value_type, T, + detail::reciprocal< T > > +measure_closeness(const Graph&, DistanceMap) +{ + typedef typename property_traits< DistanceMap >::value_type Distance; + return closeness_measure< Graph, Distance, T, detail::reciprocal< T > >(); +} + +template < typename T, typename Graph, typename DistanceMap, + typename Reciprocal > +inline closeness_measure< Graph, + typename property_traits< DistanceMap >::value_type, T, Reciprocal > +measure_closeness(const Graph&, DistanceMap) +{ + typedef typename property_traits< DistanceMap >::value_type Distance; + return closeness_measure< Graph, Distance, T, Reciprocal >(); +} + +template < typename Graph, typename DistanceMap, typename Measure, + typename Combinator > +inline typename Measure::result_type closeness_centrality( + const Graph& g, DistanceMap dist, Measure measure, Combinator combine) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< DistanceMap, Vertex >)); + typedef typename property_traits< DistanceMap >::value_type Distance; + BOOST_CONCEPT_ASSERT((NumericValueConcept< Distance >)); + BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >)); + + Distance n = detail::combine_distances(g, dist, combine, Distance(0)); + return measure(n, g); +} + +template < typename Graph, typename DistanceMap, typename Measure > +inline typename Measure::result_type closeness_centrality( + const Graph& g, DistanceMap dist, Measure measure) +{ + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< DistanceMap, Vertex >)); + typedef typename property_traits< DistanceMap >::value_type Distance; + + return closeness_centrality(g, dist, measure, std::plus< Distance >()); +} + +template < typename Graph, typename DistanceMap > +inline double closeness_centrality(const Graph& g, DistanceMap dist) +{ + return closeness_centrality(g, dist, measure_closeness(g, dist)); +} + +template < typename T, typename Graph, typename DistanceMap > +inline T closeness_centrality(const Graph& g, DistanceMap dist) +{ + return closeness_centrality(g, dist, measure_closeness< T >(g, dist)); +} + +template < typename Graph, typename DistanceMatrixMap, typename CentralityMap, + typename Measure > +inline void all_closeness_centralities( + const Graph& g, DistanceMatrixMap dist, CentralityMap cent, Measure measure) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< DistanceMatrixMap, Vertex >)); + typedef + typename property_traits< DistanceMatrixMap >::value_type DistanceMap; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< DistanceMap, Vertex >)); + BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< CentralityMap, Vertex >)); + typedef typename property_traits< CentralityMap >::value_type Centrality; + + typename graph_traits< Graph >::vertex_iterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + DistanceMap dm = get(dist, *i); + Centrality c = closeness_centrality(g, dm, measure); + put(cent, *i, c); + } +} + +template < typename Graph, typename DistanceMatrixMap, typename CentralityMap > +inline void all_closeness_centralities( + const Graph& g, DistanceMatrixMap dist, CentralityMap cent) +{ + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< DistanceMatrixMap, Vertex >)); + typedef + typename property_traits< DistanceMatrixMap >::value_type DistanceMap; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< DistanceMap, Vertex >)); + typedef typename property_traits< CentralityMap >::value_type Result; + + all_closeness_centralities( + g, dist, cent, measure_closeness< Result >(g, DistanceMap())); +} + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/clustering_coefficient.hpp b/contrib/restricted/boost/graph/include/boost/graph/clustering_coefficient.hpp new file mode 100644 index 0000000000..e275dd7e32 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/clustering_coefficient.hpp @@ -0,0 +1,160 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP +#define BOOST_GRAPH_CLUSTERING_COEFFICIENT_HPP + +#include <boost/next_prior.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/lookup_edge.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ +namespace detail +{ + template < class Graph > + inline typename graph_traits< Graph >::degree_size_type possible_edges( + const Graph& g, std::size_t k, directed_tag) + { + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + typedef typename graph_traits< Graph >::degree_size_type T; + return T(k) * (T(k) - 1); + } + + template < class Graph > + inline typename graph_traits< Graph >::degree_size_type possible_edges( + const Graph& g, size_t k, undirected_tag) + { + // dirty little trick... + return possible_edges(g, k, directed_tag()) / 2; + } + + // This template matches directedS and bidirectionalS. + template < class Graph > + inline typename graph_traits< Graph >::degree_size_type count_edges( + const Graph& g, typename graph_traits< Graph >::vertex_descriptor u, + typename graph_traits< Graph >::vertex_descriptor v, directed_tag) + + { + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< Graph >)); + return (lookup_edge(u, v, g).second ? 1 : 0) + + (lookup_edge(v, u, g).second ? 1 : 0); + } + + // This template matches undirectedS + template < class Graph > + inline typename graph_traits< Graph >::degree_size_type count_edges( + const Graph& g, typename graph_traits< Graph >::vertex_descriptor u, + typename graph_traits< Graph >::vertex_descriptor v, undirected_tag) + { + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< Graph >)); + return lookup_edge(u, v, g).second ? 1 : 0; + } +} + +template < typename Graph, typename Vertex > +inline typename graph_traits< Graph >::degree_size_type +num_paths_through_vertex(const Graph& g, Vertex v) +{ + BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::directed_category Directed; + typedef + typename graph_traits< Graph >::adjacency_iterator AdjacencyIterator; + + // TODO: There should actually be a set of neighborhood functions + // for things like this (num_neighbors() would be great). + + AdjacencyIterator i, end; + boost::tie(i, end) = adjacent_vertices(v, g); + std::size_t k = std::distance(i, end); + return detail::possible_edges(g, k, Directed()); +} + +template < typename Graph, typename Vertex > +inline typename graph_traits< Graph >::degree_size_type num_triangles_on_vertex( + const Graph& g, Vertex v) +{ + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::degree_size_type Degree; + typedef typename graph_traits< Graph >::directed_category Directed; + typedef + typename graph_traits< Graph >::adjacency_iterator AdjacencyIterator; + + // TODO: I might be able to reduce the requirement from adjacency graph + // to incidence graph by using out edges. + + Degree count(0); + AdjacencyIterator i, j, end; + for (boost::tie(i, end) = adjacent_vertices(v, g); i != end; ++i) + { + for (j = boost::next(i); j != end; ++j) + { + count += detail::count_edges(g, *i, *j, Directed()); + } + } + return count; +} /* namespace detail */ + +template < typename T, typename Graph, typename Vertex > +inline T clustering_coefficient(const Graph& g, Vertex v) +{ + T zero(0); + T routes = T(num_paths_through_vertex(g, v)); + return (routes > zero) ? T(num_triangles_on_vertex(g, v)) / routes : zero; +} + +template < typename Graph, typename Vertex > +inline double clustering_coefficient(const Graph& g, Vertex v) +{ + return clustering_coefficient< double >(g, v); +} + +template < typename Graph, typename ClusteringMap > +inline typename property_traits< ClusteringMap >::value_type +all_clustering_coefficients(const Graph& g, ClusteringMap cm) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< ClusteringMap, Vertex >)); + typedef typename property_traits< ClusteringMap >::value_type Coefficient; + + Coefficient sum(0); + VertexIterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + Coefficient cc = clustering_coefficient< Coefficient >(g, *i); + put(cm, *i, cc); + sum += cc; + } + return sum / Coefficient(num_vertices(g)); +} + +template < typename Graph, typename ClusteringMap > +inline typename property_traits< ClusteringMap >::value_type +mean_clustering_coefficient(const Graph& g, ClusteringMap cm) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< ClusteringMap, Vertex >)); + typedef typename property_traits< ClusteringMap >::value_type Coefficient; + + Coefficient cc(0); + VertexIterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + cc += get(cm, *i); + } + return cc / Coefficient(num_vertices(g)); +} + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/core_numbers.hpp b/contrib/restricted/boost/graph/include/boost/graph/core_numbers.hpp new file mode 100644 index 0000000000..95053caf1f --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/core_numbers.hpp @@ -0,0 +1,375 @@ +// +//======================================================================= +// Copyright 2007 Stanford University +// Authors: David Gleich +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_CORE_NUMBERS_HPP +#define BOOST_GRAPH_CORE_NUMBERS_HPP + +#include <boost/graph/detail/d_ary_heap.hpp> +#include <boost/graph/breadth_first_search.hpp> +#include <boost/iterator/reverse_iterator.hpp> +#include <boost/concept/assert.hpp> + +/* + * core_numbers + * + * Requirement: IncidenceGraph + */ + +// History +// +// 30 July 2007 +// Added visitors to the implementation +// +// 8 February 2008 +// Fixed headers and missing typename + +namespace boost +{ + +// A linear time O(m) algorithm to compute the indegree core number +// of a graph for unweighted graphs. +// +// and a O((n+m) log n) algorithm to compute the in-edge-weight core +// numbers of a weighted graph. +// +// The linear algorithm comes from: +// Vladimir Batagelj and Matjaz Zaversnik, "An O(m) Algorithm for Cores +// Decomposition of Networks." Sept. 1 2002. + +template < typename Visitor, typename Graph > struct CoreNumbersVisitorConcept +{ + void constraints() + { + BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Visitor >)); + vis.examine_vertex(u, g); + vis.finish_vertex(u, g); + vis.examine_edge(e, g); + } + Visitor vis; + Graph g; + typename graph_traits< Graph >::vertex_descriptor u; + typename graph_traits< Graph >::edge_descriptor e; +}; + +template < class Visitors = null_visitor > +class core_numbers_visitor : public bfs_visitor< Visitors > +{ +public: + core_numbers_visitor() {} + core_numbers_visitor(Visitors vis) : bfs_visitor< Visitors >(vis) {} + +private: + template < class Vertex, class Graph > + void initialize_vertex(Vertex, Graph&) + { + } + + template < class Vertex, class Graph > void discover_vertex(Vertex, Graph&) + { + } + + template < class Vertex, class Graph > void gray_target(Vertex, Graph&) {} + + template < class Vertex, class Graph > void black_target(Vertex, Graph&) {} + + template < class Edge, class Graph > void tree_edge(Edge, Graph&) {} + + template < class Edge, class Graph > void non_tree_edge(Edge, Graph&) {} +}; + +template < class Visitors > +core_numbers_visitor< Visitors > make_core_numbers_visitor(Visitors vis) +{ + return core_numbers_visitor< Visitors >(vis); +} + +typedef core_numbers_visitor<> default_core_numbers_visitor; + +namespace detail +{ + + // implement a constant_property_map to simplify compute_in_degree + // for the weighted and unweighted case + // this is based on dummy property map + template < typename ValueType > + class constant_value_property_map + : public boost::put_get_helper< ValueType, + constant_value_property_map< ValueType > > + { + public: + typedef void key_type; + typedef ValueType value_type; + typedef const ValueType& reference; + typedef boost::readable_property_map_tag category; + inline constant_value_property_map(ValueType cc) : c(cc) {} + inline constant_value_property_map( + const constant_value_property_map< ValueType >& x) + : c(x.c) + { + } + template < class Vertex > inline reference operator[](Vertex) const + { + return c; + } + + protected: + ValueType c; + }; + + // the core numbers start as the indegree or inweight. This function + // will initialize these values + template < typename Graph, typename CoreMap, typename EdgeWeightMap > + void compute_in_degree_map(Graph& g, CoreMap d, EdgeWeightMap wm) + { + typename graph_traits< Graph >::vertex_iterator vi, vi_end; + typename graph_traits< Graph >::out_edge_iterator ei, ei_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + put(d, *vi, 0); + } + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + for (boost::tie(ei, ei_end) = out_edges(*vi, g); ei != ei_end; ++ei) + { + put(d, target(*ei, g), get(d, target(*ei, g)) + get(wm, *ei)); + } + } + } + + // the version for weighted graphs is a little different + template < typename Graph, typename CoreMap, typename EdgeWeightMap, + typename MutableQueue, typename Visitor > + typename property_traits< CoreMap >::value_type core_numbers_impl( + Graph& g, CoreMap c, EdgeWeightMap wm, MutableQueue& Q, Visitor vis) + { + typename property_traits< CoreMap >::value_type v_cn = 0; + typedef typename graph_traits< Graph >::vertex_descriptor vertex; + while (!Q.empty()) + { + // remove v from the Q, and then decrease the core numbers + // of its successors + vertex v = Q.top(); + vis.examine_vertex(v, g); + Q.pop(); + v_cn = get(c, v); + typename graph_traits< Graph >::out_edge_iterator oi, oi_end; + for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi) + { + vis.examine_edge(*oi, g); + vertex u = target(*oi, g); + // if c[u] > c[v], then u is still in the graph, + if (get(c, u) > v_cn) + { + // remove the edge + put(c, u, get(c, u) - get(wm, *oi)); + if (Q.contains(u)) + Q.update(u); + } + } + vis.finish_vertex(v, g); + } + return (v_cn); + } + + template < typename Graph, typename CoreMap, typename EdgeWeightMap, + typename IndexMap, typename CoreNumVisitor > + typename property_traits< CoreMap >::value_type core_numbers_dispatch( + Graph& g, CoreMap c, EdgeWeightMap wm, IndexMap im, CoreNumVisitor vis) + { + typedef typename property_traits< CoreMap >::value_type D; + typedef std::less< D > Cmp; + // build the mutable queue + typedef typename graph_traits< Graph >::vertex_descriptor vertex; + std::vector< std::size_t > index_in_heap_data(num_vertices(g)); + typedef iterator_property_map< std::vector< std::size_t >::iterator, + IndexMap > + index_in_heap_map_type; + index_in_heap_map_type index_in_heap_map( + index_in_heap_data.begin(), im); + typedef d_ary_heap_indirect< vertex, 4, index_in_heap_map_type, CoreMap, + Cmp > + MutableQueue; + MutableQueue Q(c, index_in_heap_map, Cmp()); + typename graph_traits< Graph >::vertex_iterator vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + Q.push(*vi); + } + return core_numbers_impl(g, c, wm, Q, vis); + } + + // the version for the unweighted case + // for this functions CoreMap must be initialized + // with the in degree of each vertex + template < typename Graph, typename CoreMap, typename PositionMap, + typename Visitor > + typename property_traits< CoreMap >::value_type core_numbers_impl( + Graph& g, CoreMap c, PositionMap pos, Visitor vis) + { + typedef typename graph_traits< Graph >::vertices_size_type size_type; + typedef typename graph_traits< Graph >::degree_size_type degree_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex; + typename graph_traits< Graph >::vertex_iterator vi, vi_end; + + // store the vertex core numbers + typename property_traits< CoreMap >::value_type v_cn = 0; + + // compute the maximum degree (degrees are in the coremap) + typename graph_traits< Graph >::degree_size_type max_deg = 0; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + max_deg = (std::max< + typename graph_traits< Graph >::degree_size_type >)(max_deg, + get(c, *vi)); + } + + // store the vertices in bins by their degree + // allocate two extra locations to ease boundary cases + std::vector< size_type > bin(max_deg + 2); + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + ++bin[get(c, *vi)]; + } + + // this loop sets bin[d] to the starting position of vertices + // with degree d in the vert array for the bucket sort + size_type cur_pos = 0; + for (degree_type cur_deg = 0; cur_deg < max_deg + 2; ++cur_deg) + { + degree_type tmp = bin[cur_deg]; + bin[cur_deg] = cur_pos; + cur_pos += tmp; + } + + // perform the bucket sort with pos and vert so that + // pos[0] is the vertex of smallest degree + std::vector< vertex > vert(num_vertices(g)); + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex v = *vi; + size_type p = bin[get(c, v)]; + put(pos, v, p); + vert[p] = v; + ++bin[get(c, v)]; + } + // we ``abused'' bin while placing the vertices, now, + // we need to restore it + std::copy(boost::make_reverse_iterator(bin.end() - 2), + boost::make_reverse_iterator(bin.begin()), + boost::make_reverse_iterator(bin.end() - 1)); + // now simulate removing the vertices + for (size_type i = 0; i < num_vertices(g); ++i) + { + vertex v = vert[i]; + vis.examine_vertex(v, g); + v_cn = get(c, v); + typename graph_traits< Graph >::out_edge_iterator oi, oi_end; + for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi) + { + vis.examine_edge(*oi, g); + vertex u = target(*oi, g); + // if c[u] > c[v], then u is still in the graph, + if (get(c, u) > v_cn) + { + degree_type deg_u = get(c, u); + degree_type pos_u = get(pos, u); + // w is the first vertex with the same degree as u + // (this is the resort operation!) + degree_type pos_w = bin[deg_u]; + vertex w = vert[pos_w]; + if (u != v) + { + // swap u and w + put(pos, u, pos_w); + put(pos, w, pos_u); + vert[pos_w] = u; + vert[pos_u] = w; + } + // now, the vertices array is sorted assuming + // we perform the following step + // start the set of vertices with degree of u + // one into the future (this now points at vertex + // w which we swapped with u). + ++bin[deg_u]; + // we are removing v from the graph, so u's degree + // decreases + put(c, u, get(c, u) - 1); + } + } + vis.finish_vertex(v, g); + } + return v_cn; + } + +} // namespace detail + +// non-named parameter version for the unweighted case +template < typename Graph, typename CoreMap, typename CoreNumVisitor > +typename property_traits< CoreMap >::value_type core_numbers( + Graph& g, CoreMap c, CoreNumVisitor vis) +{ + typedef typename graph_traits< Graph >::vertices_size_type size_type; + detail::compute_in_degree_map(g, c, + detail::constant_value_property_map< + typename property_traits< CoreMap >::value_type >(1)); + return detail::core_numbers_impl(g, c, + make_iterator_property_map( + std::vector< size_type >(num_vertices(g)).begin(), + get(vertex_index, g)), + vis); +} + +// non-named paramter version for the unweighted case +template < typename Graph, typename CoreMap > +typename property_traits< CoreMap >::value_type core_numbers( + Graph& g, CoreMap c) +{ + return core_numbers(g, c, make_core_numbers_visitor(null_visitor())); +} + +// non-named parameter version for the weighted case +template < typename Graph, typename CoreMap, typename EdgeWeightMap, + typename VertexIndexMap, typename CoreNumVisitor > +typename property_traits< CoreMap >::value_type core_numbers(Graph& g, + CoreMap c, EdgeWeightMap wm, VertexIndexMap vim, CoreNumVisitor vis) +{ + detail::compute_in_degree_map(g, c, wm); + return detail::core_numbers_dispatch(g, c, wm, vim, vis); +} + +// non-named parameter version for the weighted case +// template <typename Graph, typename CoreMap, typename EdgeWeightMap> +// typename property_traits<CoreMap>::value_type +// core_numbers(Graph& g, CoreMap c, EdgeWeightMap wm) +// { +// typedef typename graph_traits<Graph>::vertices_size_type size_type; +// detail::compute_in_degree_map(g,c,wm); +// return detail::core_numbers_dispatch(g,c,wm,get(vertex_index,g), +// make_core_numbers_visitor(null_visitor())); +// } + +template < typename Graph, typename CoreMap > +typename property_traits< CoreMap >::value_type weighted_core_numbers( + Graph& g, CoreMap c) +{ + return weighted_core_numbers( + g, c, make_core_numbers_visitor(null_visitor())); +} + +template < typename Graph, typename CoreMap, typename CoreNumVisitor > +typename property_traits< CoreMap >::value_type weighted_core_numbers( + Graph& g, CoreMap c, CoreNumVisitor vis) +{ + return core_numbers(g, c, get(edge_weight, g), get(vertex_index, g), vis); +} + +} // namespace boost + +#endif // BOOST_GRAPH_CORE_NUMBERS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/create_condensation_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/create_condensation_graph.hpp new file mode 100644 index 0000000000..1eb6fa2b60 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/create_condensation_graph.hpp @@ -0,0 +1,86 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_CREATE_CONDENSATION_GRAPH_HPP +#define BOOST_CREATE_CONDENSATION_GRAPH_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +template < typename Graph, typename ComponentLists, typename ComponentNumberMap, + typename CondensationGraph, typename EdgeMultiplicityMap > +void create_condensation_graph(const Graph& g, const ComponentLists& components, + ComponentNumberMap component_number, CondensationGraph& cg, + EdgeMultiplicityMap edge_mult_map) +{ + typedef typename graph_traits< Graph >::vertex_descriptor vertex; + typedef typename graph_traits< Graph >::vertices_size_type size_type; + typedef + typename graph_traits< CondensationGraph >::vertex_descriptor cg_vertex; + std::vector< cg_vertex > to_cg_vertex(components.size()); + for (size_type s = 0; s < components.size(); ++s) + to_cg_vertex[s] = add_vertex(cg); + + for (size_type si = 0; si < components.size(); ++si) + { + cg_vertex s = to_cg_vertex[si]; + std::vector< cg_vertex > adj; + for (size_type i = 0; i < components[si].size(); ++i) + { + vertex u = components[s][i]; + typename graph_traits< Graph >::adjacency_iterator v, v_end; + for (boost::tie(v, v_end) = adjacent_vertices(u, g); v != v_end; + ++v) + { + cg_vertex t = to_cg_vertex[component_number[*v]]; + if (s != t) // Avoid loops in the condensation graph + adj.push_back(t); + } + } + std::sort(adj.begin(), adj.end()); + if (!adj.empty()) + { + size_type i = 0; + cg_vertex t = adj[i]; + typename graph_traits< CondensationGraph >::edge_descriptor e; + bool inserted; + boost::tie(e, inserted) = add_edge(s, t, cg); + put(edge_mult_map, e, 1); + ++i; + while (i < adj.size()) + { + if (adj[i] == t) + put(edge_mult_map, e, get(edge_mult_map, e) + 1); + else + { + t = adj[i]; + boost::tie(e, inserted) = add_edge(s, t, cg); + put(edge_mult_map, e, 1); + } + ++i; + } + } + } +} + +template < typename Graph, typename ComponentLists, typename ComponentNumberMap, + typename CondensationGraph > +void create_condensation_graph(const Graph& g, const ComponentLists& components, + ComponentNumberMap component_number, CondensationGraph& cg) +{ + create_condensation_graph( + g, components, component_number, cg, dummy_property_map()); +} + +} // namespace boost + +#endif // BOOST_CREATE_CONDENSATION_GRAPH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/cuthill_mckee_ordering.hpp b/contrib/restricted/boost/graph/include/boost/graph/cuthill_mckee_ordering.hpp new file mode 100644 index 0000000000..75750bdf5b --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/cuthill_mckee_ordering.hpp @@ -0,0 +1,181 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004, 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// Doug Gregor, D. Kevin McGrath +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_CUTHILL_MCKEE_HPP +#define BOOST_GRAPH_CUTHILL_MCKEE_HPP + +#include <boost/config.hpp> +#include <boost/graph/detail/sparse_ordering.hpp> +#include <boost/graph/graph_utility.hpp> +#include <algorithm> + +/* + (Reverse) Cuthill-McKee Algorithm for matrix reordering +*/ + +namespace boost +{ + +namespace detail +{ + + template < typename OutputIterator, typename Buffer, typename DegreeMap > + class bfs_rcm_visitor : public default_bfs_visitor + { + public: + bfs_rcm_visitor(OutputIterator* iter, Buffer* b, DegreeMap deg) + : permutation(iter), Qptr(b), degree(deg) + { + } + template < class Vertex, class Graph > + void examine_vertex(Vertex u, Graph&) + { + *(*permutation)++ = u; + index_begin = Qptr->size(); + } + template < class Vertex, class Graph > + void finish_vertex(Vertex, Graph&) + { + using std::sort; + + typedef typename property_traits< DegreeMap >::value_type ds_type; + + typedef indirect_cmp< DegreeMap, std::less< ds_type > > Compare; + Compare comp(degree); + + sort(Qptr->begin() + index_begin, Qptr->end(), comp); + } + + protected: + OutputIterator* permutation; + int index_begin; + Buffer* Qptr; + DegreeMap degree; + }; + +} // namespace detail + +// Reverse Cuthill-McKee algorithm with a given starting Vertex. +// +// If user provides a reverse iterator, this will be a reverse-cuthill-mckee +// algorithm, otherwise it will be a standard CM algorithm + +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap > +OutputIterator cuthill_mckee_ordering(const Graph& g, + std::deque< typename graph_traits< Graph >::vertex_descriptor > + vertex_queue, + OutputIterator permutation, ColorMap color, DegreeMap degree) +{ + + // create queue, visitor...don't forget namespaces! + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename boost::sparse::sparse_ordering_queue< Vertex > queue; + typedef typename detail::bfs_rcm_visitor< OutputIterator, queue, DegreeMap > + Visitor; + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + + queue Q; + + // create a bfs_rcm_visitor as defined above + Visitor vis(&permutation, &Q, degree); + + typename graph_traits< Graph >::vertex_iterator ui, ui_end; + + // Copy degree to pseudo_degree + // initialize the color map + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + put(color, *ui, Color::white()); + } + + while (!vertex_queue.empty()) + { + Vertex s = vertex_queue.front(); + vertex_queue.pop_front(); + + // call BFS with visitor + breadth_first_visit(g, s, Q, vis, color); + } + return permutation; +} + +// This is the case where only a single starting vertex is supplied. +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap > +OutputIterator cuthill_mckee_ordering(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + OutputIterator permutation, ColorMap color, DegreeMap degree) +{ + + std::deque< typename graph_traits< Graph >::vertex_descriptor > + vertex_queue; + vertex_queue.push_front(s); + + return cuthill_mckee_ordering(g, vertex_queue, permutation, color, degree); +} + +// This is the version of CM which selects its own starting vertex +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap > +OutputIterator cuthill_mckee_ordering(const Graph& G, + OutputIterator permutation, ColorMap color, DegreeMap degree) +{ + if (boost::graph::has_no_vertices(G)) + return permutation; + + typedef typename boost::graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + + std::deque< Vertex > vertex_queue; + + // Mark everything white + BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white()); + + // Find one vertex from each connected component + BGL_FORALL_VERTICES_T(v, G, Graph) + { + if (get(color, v) == Color::white()) + { + depth_first_visit(G, v, dfs_visitor<>(), color); + vertex_queue.push_back(v); + } + } + + // Find starting nodes for all vertices + // TBD: How to do this with a directed graph? + for (typename std::deque< Vertex >::iterator i = vertex_queue.begin(); + i != vertex_queue.end(); ++i) + *i = find_starting_node(G, *i, color, degree); + + return cuthill_mckee_ordering(G, vertex_queue, permutation, color, degree); +} + +template < typename Graph, typename OutputIterator, typename VertexIndexMap > +OutputIterator cuthill_mckee_ordering( + const Graph& G, OutputIterator permutation, VertexIndexMap index_map) +{ + if (boost::graph::has_no_vertices(G)) + return permutation; + + std::vector< default_color_type > colors(num_vertices(G)); + return cuthill_mckee_ordering(G, permutation, + make_iterator_property_map(&colors[0], index_map, colors[0]), + make_out_degree_map(G)); +} + +template < typename Graph, typename OutputIterator > +inline OutputIterator cuthill_mckee_ordering( + const Graph& G, OutputIterator permutation) +{ + return cuthill_mckee_ordering(G, permutation, get(vertex_index, G)); +} +} // namespace boost + +#endif // BOOST_GRAPH_CUTHILL_MCKEE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/cycle_canceling.hpp b/contrib/restricted/boost/graph/include/boost/graph/cycle_canceling.hpp new file mode 100644 index 0000000000..5aaa25e752 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/cycle_canceling.hpp @@ -0,0 +1,191 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +// +// This algorithm is described in "Network Flows: Theory, Algorithms, and +// Applications" +// by Ahuja, Magnanti, Orlin. + +#ifndef BOOST_GRAPH_CYCLE_CANCELING_HPP +#define BOOST_GRAPH_CYCLE_CANCELING_HPP + +#include <numeric> + +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/pending/indirect_cmp.hpp> +#include <boost/graph/bellman_ford_shortest_paths.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/detail/augment.hpp> +#include <boost/graph/find_flow_cost.hpp> + +namespace boost +{ + +namespace detail +{ + + template < typename PredEdgeMap, typename Vertex > + class RecordEdgeMapAndCycleVertex + : public bellman_visitor< + edge_predecessor_recorder< PredEdgeMap, on_edge_relaxed > > + { + typedef edge_predecessor_recorder< PredEdgeMap, on_edge_relaxed > + PredRec; + + public: + RecordEdgeMapAndCycleVertex(PredEdgeMap pred, Vertex& v) + : bellman_visitor< PredRec >(PredRec(pred)), m_v(v), m_pred(pred) + { + } + + template < typename Graph, typename Edge > + void edge_not_minimized(Edge e, const Graph& g) const + { + typename graph_traits< Graph >::vertices_size_type n + = num_vertices(g) + 1; + + // edge e is not minimized but does not have to be on the negative + // weight cycle to find vertex on negative wieight cycle we move n+1 + // times backword in the PredEdgeMap graph. + while (n > 0) + { + e = get(m_pred, source(e, g)); + --n; + } + m_v = source(e, g); + } + + private: + Vertex& m_v; + PredEdgeMap m_pred; + }; + +} // detail + +template < class Graph, class Pred, class Distance, class Reversed, + class ResidualCapacity, class Weight > +void cycle_canceling(const Graph& g, Weight weight, Reversed rev, + ResidualCapacity residual_capacity, Pred pred, Distance distance) +{ + typedef filtered_graph< const Graph, is_residual_edge< ResidualCapacity > > + ResGraph; + ResGraph gres = detail::residual_graph(g, residual_capacity); + + typedef graph_traits< ResGraph > ResGTraits; + typedef graph_traits< Graph > GTraits; + typedef typename ResGTraits::edge_descriptor edge_descriptor; + typedef typename ResGTraits::vertex_descriptor vertex_descriptor; + + typename GTraits::vertices_size_type N = num_vertices(g); + + BGL_FORALL_VERTICES_T(v, g, Graph) + { + put(pred, v, edge_descriptor()); + put(distance, v, 0); + } + + vertex_descriptor cycleStart; + while (!bellman_ford_shortest_paths(gres, N, + weight_map(weight).distance_map(distance).visitor( + detail::RecordEdgeMapAndCycleVertex< Pred, vertex_descriptor >( + pred, cycleStart)))) + { + + detail::augment( + g, cycleStart, cycleStart, pred, residual_capacity, rev); + + BGL_FORALL_VERTICES_T(v, g, Graph) + { + put(pred, v, edge_descriptor()); + put(distance, v, 0); + } + } +} + +// in this namespace argument dispatching takes place +namespace detail +{ + + template < class Graph, class P, class T, class R, class ResidualCapacity, + class Weight, class Reversed, class Pred, class Distance > + void cycle_canceling_dispatch2(const Graph& g, Weight weight, Reversed rev, + ResidualCapacity residual_capacity, Pred pred, Distance dist, + const bgl_named_params< P, T, R >& params) + { + cycle_canceling(g, weight, rev, residual_capacity, pred, dist); + } + + // setting default distance map + template < class Graph, class P, class T, class R, class Pred, + class ResidualCapacity, class Weight, class Reversed > + void cycle_canceling_dispatch2(Graph& g, Weight weight, Reversed rev, + ResidualCapacity residual_capacity, Pred pred, param_not_found, + const bgl_named_params< P, T, R >& params) + { + typedef typename property_traits< Weight >::value_type D; + + std::vector< D > d_map(num_vertices(g)); + + cycle_canceling(g, weight, rev, residual_capacity, pred, + make_iterator_property_map(d_map.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index))); + } + + template < class Graph, class P, class T, class R, class ResidualCapacity, + class Weight, class Reversed, class Pred > + void cycle_canceling_dispatch1(Graph& g, Weight weight, Reversed rev, + ResidualCapacity residual_capacity, Pred pred, + const bgl_named_params< P, T, R >& params) + { + cycle_canceling_dispatch2(g, weight, rev, residual_capacity, pred, + get_param(params, vertex_distance), params); + } + + // setting default predecessors map + template < class Graph, class P, class T, class R, class ResidualCapacity, + class Weight, class Reversed > + void cycle_canceling_dispatch1(Graph& g, Weight weight, Reversed rev, + ResidualCapacity residual_capacity, param_not_found, + const bgl_named_params< P, T, R >& params) + { + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor; + std::vector< edge_descriptor > p_map(num_vertices(g)); + + cycle_canceling_dispatch2(g, weight, rev, residual_capacity, + make_iterator_property_map(p_map.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index)), + get_param(params, vertex_distance), params); + } + +} // detail + +template < class Graph, class P, class T, class R > +void cycle_canceling(Graph& g, const bgl_named_params< P, T, R >& params) +{ + cycle_canceling_dispatch1(g, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_pmap(get_param(params, edge_residual_capacity), g, + edge_residual_capacity), + get_param(params, vertex_predecessor), params); +} + +template < class Graph > void cycle_canceling(Graph& g) +{ + bgl_named_params< int, buffer_param_t > params(0); + cycle_canceling(g, params); +} + +} + +#endif /* BOOST_GRAPH_CYCLE_CANCELING_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/graph/degree_centrality.hpp b/contrib/restricted/boost/graph/include/boost/graph/degree_centrality.hpp new file mode 100644 index 0000000000..6db11b95eb --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/degree_centrality.hpp @@ -0,0 +1,135 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_DEGREE_CENTRALITY_HPP +#define BOOST_GRAPH_DEGREE_CENTRALITY_HPP + +#include <boost/graph/graph_concepts.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +template < typename Graph > struct degree_centrality_measure +{ + typedef typename graph_traits< Graph >::degree_size_type degree_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_type; +}; + +template < typename Graph > +struct influence_measure : public degree_centrality_measure< Graph > +{ + typedef degree_centrality_measure< Graph > base_type; + typedef typename base_type::degree_type degree_type; + typedef typename base_type::vertex_type vertex_type; + + inline degree_type operator()(vertex_type v, const Graph& g) + { + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >)); + return out_degree(v, g); + } +}; + +template < typename Graph > +inline influence_measure< Graph > measure_influence(const Graph&) +{ + return influence_measure< Graph >(); +} + +template < typename Graph > +struct prestige_measure : public degree_centrality_measure< Graph > +{ + typedef degree_centrality_measure< Graph > base_type; + typedef typename base_type::degree_type degree_type; + typedef typename base_type::vertex_type vertex_type; + + inline degree_type operator()(vertex_type v, const Graph& g) + { + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< Graph >)); + return in_degree(v, g); + } +}; + +template < typename Graph > +inline prestige_measure< Graph > measure_prestige(const Graph&) +{ + return prestige_measure< Graph >(); +} + +template < typename Graph, typename Vertex, typename Measure > +inline typename Measure::degree_type degree_centrality( + const Graph& g, Vertex v, Measure measure) +{ + BOOST_CONCEPT_ASSERT((DegreeMeasureConcept< Measure, Graph >)); + return measure(v, g); +} + +template < typename Graph, typename Vertex > +inline typename graph_traits< Graph >::degree_size_type degree_centrality( + const Graph& g, Vertex v) +{ + return degree_centrality(g, v, measure_influence(g)); +} + +// These are alias functions, intended to provide a more expressive interface. + +template < typename Graph, typename Vertex > +inline typename graph_traits< Graph >::degree_size_type influence( + const Graph& g, Vertex v) +{ + return degree_centrality(g, v, measure_influence(g)); +} + +template < typename Graph, typename Vertex > +inline typename graph_traits< Graph >::degree_size_type prestige( + const Graph& g, Vertex v) +{ + return degree_centrality(g, v, measure_prestige(g)); +} + +template < typename Graph, typename CentralityMap, typename Measure > +inline void all_degree_centralities( + const Graph& g, CentralityMap cent, Measure measure) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< CentralityMap, Vertex >)); + typedef typename property_traits< CentralityMap >::value_type Centrality; + + VertexIterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + Centrality c = degree_centrality(g, *i, measure); + put(cent, *i, c); + } +} + +template < typename Graph, typename CentralityMap > +inline void all_degree_centralities(const Graph& g, CentralityMap cent) +{ + all_degree_centralities(g, cent, measure_influence(g)); +} + +// More helper functions for computing influence and prestige. +// I hate the names of these functions, but influence and prestige +// don't pluralize too well. + +template < typename Graph, typename CentralityMap > +inline void all_influence_values(const Graph& g, CentralityMap cent) +{ + all_degree_centralities(g, cent, measure_influence(g)); +} + +template < typename Graph, typename CentralityMap > +inline void all_prestige_values(const Graph& g, CentralityMap cent) +{ + all_degree_centralities(g, cent, measure_prestige(g)); +} + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/augment.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/augment.hpp new file mode 100644 index 0000000000..956f274cb4 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/augment.hpp @@ -0,0 +1,66 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_AUGMENT_HPP +#define BOOST_GRAPH_AUGMENT_HPP + +#include <boost/graph/filtered_graph.hpp> + +namespace boost +{ +namespace detail +{ + + template < class Graph, class ResCapMap > + filtered_graph< const Graph, is_residual_edge< ResCapMap > > residual_graph( + const Graph& g, ResCapMap residual_capacity) + { + return filtered_graph< const Graph, is_residual_edge< ResCapMap > >( + g, is_residual_edge< ResCapMap >(residual_capacity)); + } + + template < class Graph, class PredEdgeMap, class ResCapMap, + class RevEdgeMap > + inline void augment(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, PredEdgeMap p, + ResCapMap residual_capacity, RevEdgeMap reverse_edge) + { + typename graph_traits< Graph >::edge_descriptor e; + typename graph_traits< Graph >::vertex_descriptor u; + typedef typename property_traits< ResCapMap >::value_type FlowValue; + + // find minimum residual capacity along the augmenting path + FlowValue delta = (std::numeric_limits< FlowValue >::max)(); + e = get(p, sink); + do + { + BOOST_USING_STD_MIN(); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION( + delta, get(residual_capacity, e)); + u = source(e, g); + e = get(p, u); + } while (u != src); + + // push delta units of flow along the augmenting path + e = get(p, sink); + do + { + put(residual_capacity, e, get(residual_capacity, e) - delta); + put(residual_capacity, get(reverse_edge, e), + get(residual_capacity, get(reverse_edge, e)) + delta); + u = source(e, g); + e = get(p, u); + } while (u != src); + } + +} // namespace detail +} // namespace boost + +#endif /* BOOST_GRAPH_AUGMENT_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/connected_components.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/connected_components.hpp new file mode 100644 index 0000000000..a97159118d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/connected_components.hpp @@ -0,0 +1,206 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP +#define BOOST_GRAPH_DETAIL_CONNECTED_COMPONENTS_HPP + +#if defined(__sgi) && !defined(__GNUC__) +#pragma set woff 1234 +#endif + +#include <boost/operators.hpp> + +namespace boost +{ + +namespace detail +{ + + //========================================================================= + // Implementation details of connected_components + + // This is used both in the connected_components algorithm and in + // the kosaraju strong components algorithm during the second DFS + // traversal. + template < class ComponentsPA, class DFSVisitor > + class components_recorder : public DFSVisitor + { + typedef typename property_traits< ComponentsPA >::value_type comp_type; + + public: + components_recorder(ComponentsPA c, comp_type& c_count, DFSVisitor v) + : DFSVisitor(v), m_component(c), m_count(c_count) + { + } + + template < class Vertex, class Graph > + void start_vertex(Vertex u, Graph& g) + { + ++m_count; + DFSVisitor::start_vertex(u, g); + } + template < class Vertex, class Graph > + void discover_vertex(Vertex u, Graph& g) + { + put(m_component, u, m_count); + DFSVisitor::discover_vertex(u, g); + } + + protected: + ComponentsPA m_component; + comp_type& m_count; + }; + + template < class DiscoverTimeMap, class FinishTimeMap, class TimeT, + class DFSVisitor > + class time_recorder : public DFSVisitor + { + public: + time_recorder( + DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor v) + : DFSVisitor(v), m_discover_time(d), m_finish_time(f), m_t(t) + { + } + + template < class Vertex, class Graph > + void discover_vertex(Vertex u, Graph& g) + { + put(m_discover_time, u, ++m_t); + DFSVisitor::discover_vertex(u, g); + } + template < class Vertex, class Graph > + void finish_vertex(Vertex u, Graph& g) + { + put(m_finish_time, u, ++m_t); + DFSVisitor::discover_vertex(u, g); + } + + protected: + DiscoverTimeMap m_discover_time; + FinishTimeMap m_finish_time; + TimeT m_t; + }; + template < class DiscoverTimeMap, class FinishTimeMap, class TimeT, + class DFSVisitor > + time_recorder< DiscoverTimeMap, FinishTimeMap, TimeT, DFSVisitor > + record_times(DiscoverTimeMap d, FinishTimeMap f, TimeT& t, DFSVisitor vis) + { + return time_recorder< DiscoverTimeMap, FinishTimeMap, TimeT, + DFSVisitor >(d, f, t, vis); + } + + //========================================================================= + // Implementation detail of dynamic_components + + //------------------------------------------------------------------------- + // Helper functions for the component_index class + + // Record the representative vertices in the header array. + // Representative vertices now point to the component number. + + template < class Parent, class OutputIterator, class Integer > + inline void build_components_header( + Parent p, OutputIterator header, Integer num_nodes) + { + Parent component = p; + Integer component_num = 0; + for (Integer v = 0; v != num_nodes; ++v) + if (p[v] == v) + { + *header++ = v; + component[v] = component_num++; + } + } + + // Pushes x onto the front of the list. The list is represented in + // an array. + template < class Next, class T, class V > + inline void push_front(Next next, T& head, V x) + { + T tmp = head; + head = x; + next[x] = tmp; + } + + // Create a linked list of the vertices in each component + // by reusing the representative array. + template < class Parent1, class Parent2, class Integer > + void link_components(Parent1 component, Parent2 header, Integer num_nodes, + Integer num_components) + { + // Make the non-representative vertices point to their component + Parent1 representative = component; + for (Integer v = 0; v != num_nodes; ++v) + if (component[v] >= num_components || header[component[v]] != v) + component[v] = component[representative[v]]; + + // initialize the "head" of the lists to "NULL" + std::fill_n(header, num_components, num_nodes); + + // Add each vertex to the linked list for its component + Parent1 next = component; + for (Integer k = 0; k != num_nodes; ++k) + push_front(next, header[component[k]], k); + } + + template < class IndexContainer, class HeaderContainer > + void construct_component_index( + IndexContainer& index, HeaderContainer& header) + { + build_components_header(index.begin(), std::back_inserter(header), + index.end() - index.begin()); + + link_components(index.begin(), header.begin(), + index.end() - index.begin(), header.end() - header.begin()); + } + + template < class IndexIterator, class Integer, class Distance > + class component_iterator + : boost::forward_iterator_helper< + component_iterator< IndexIterator, Integer, Distance >, Integer, + Distance, Integer*, Integer& > + { + public: + typedef component_iterator self; + + IndexIterator next; + Integer node; + + typedef std::forward_iterator_tag iterator_category; + typedef Integer value_type; + typedef Integer& reference; + typedef Integer* pointer; + typedef Distance difference_type; + + component_iterator() {} + component_iterator(IndexIterator x, Integer i) : next(x), node(i) {} + Integer operator*() const { return node; } + self& operator++() + { + node = next[node]; + return *this; + } + }; + + template < class IndexIterator, class Integer, class Distance > + inline bool operator==( + const component_iterator< IndexIterator, Integer, Distance >& x, + const component_iterator< IndexIterator, Integer, Distance >& y) + { + return x.node == y.node; + } + +} // namespace detail + +} // namespace detail + +#if defined(__sgi) && !defined(__GNUC__) +#pragma reset woff 1234 +#endif + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/empty_header.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/empty_header.hpp new file mode 100644 index 0000000000..fde3672551 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/empty_header.hpp @@ -0,0 +1,10 @@ +#ifndef BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED +#define BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED + +// Copyright 2018 Peter Dimov +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#endif // #ifndef BOOST_GRAPH_DETAIL_EMPTY_HEADER_HPP_INCLUDED diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/geodesic.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/geodesic.hpp new file mode 100644 index 0000000000..84805fb647 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/geodesic.hpp @@ -0,0 +1,138 @@ +// (C) Copyright 2007 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_DETAIL_GEODESIC_HPP +#define BOOST_GRAPH_DETAIL_GEODESIC_HPP + +#include <functional> +#include <boost/config.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/numeric_values.hpp> +#include <boost/concept/assert.hpp> + +// TODO: Should this really be in detail? + +namespace boost +{ +// This is a very good discussion on centrality measures. While I can't +// say that this has been the motivating factor for the design and +// implementation of ths centrality framework, it does provide a single +// point of reference for defining things like degree and closeness +// centrality. Plus, the bibliography seems fairly complete. +// +// @article{citeulike:1144245, +// author = {Borgatti, Stephen P. and Everett, Martin G.}, +// citeulike-article-id = {1144245}, +// doi = {10.1016/j.socnet.2005.11.005}, +// journal = {Social Networks}, +// month = {October}, +// number = {4}, +// pages = {466--484}, +// priority = {0}, +// title = {A Graph-theoretic perspective on centrality}, +// url = {https://doi.org/10.1016/j.socnet.2005.11.005}, +// volume = {28}, +// year = {2006} +// } +// } + +namespace detail +{ + // Note that this assumes T == property_traits<DistanceMap>::value_type + // and that the args and return of combine are also T. + template < typename Graph, typename DistanceMap, typename Combinator, + typename Distance > + inline Distance combine_distances( + const Graph& g, DistanceMap dist, Combinator combine, Distance init) + { + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< DistanceMap, Vertex >)); + BOOST_CONCEPT_ASSERT((NumericValueConcept< Distance >)); + typedef numeric_values< Distance > DistanceNumbers; +// NOTE: Disabled until this concept assert is fixed in Boost.ConceptCheck. +// BOOST_CONCEPT_ASSERT((AdaptableBinaryFunction< Combinator, Distance, +// Distance, Distance >)); + + // If there's ever an infinite distance, then we simply return + // infinity. Note that this /will/ include the a non-zero + // distance-to-self in the combined values. However, this is usually + // zero, so it shouldn't be too problematic. + Distance ret = init; + VertexIterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + Vertex v = *i; + if (get(dist, v) != DistanceNumbers::infinity()) + { + ret = combine(ret, get(dist, v)); + } + else + { + ret = DistanceNumbers::infinity(); + break; + } + } + return ret; + } + + // Similar to std::plus<T>, but maximizes parameters + // rather than adding them. + template < typename T > struct maximize + { + typedef T result_type; + typedef T first_argument_type; + typedef T second_argument_type; + T operator()(T x, T y) const + { + BOOST_USING_STD_MAX(); + return max BOOST_PREVENT_MACRO_SUBSTITUTION(x, y); + } + }; + + // Another helper, like maximize() to help abstract functional + // concepts. This is trivially instantiated for builtin numeric + // types, but should be specialized for those types that have + // discrete notions of reciprocals. + template < typename T > struct reciprocal + { + typedef T result_type; + typedef T argument_type; + T operator()(T t) { return T(1) / t; } + }; +} /* namespace detail */ + +// This type defines the basic facilities used for computing values +// based on the geodesic distances between vertices. Examples include +// closeness centrality and mean geodesic distance. +template < typename Graph, typename DistanceType, typename ResultType > +struct geodesic_measure +{ + typedef DistanceType distance_type; + typedef ResultType result_type; + typedef typename graph_traits< Graph >::vertices_size_type size_type; + + typedef numeric_values< distance_type > distance_values; + typedef numeric_values< result_type > result_values; + + static inline distance_type infinite_distance() + { + return distance_values::infinity(); + } + + static inline result_type infinite_result() + { + return result_values::infinity(); + } + + static inline result_type zero_result() { return result_values::zero(); } +}; + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/incidence_iterator.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/incidence_iterator.hpp new file mode 100644 index 0000000000..2da4874ac7 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/incidence_iterator.hpp @@ -0,0 +1,98 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_DETAIL_INCIDENCE_ITERATOR_HPP +#define BOOST_GRAPH_DETAIL_INCIDENCE_ITERATOR_HPP + +#include <utility> +#include <iterator> + +// OBSOLETE + +namespace boost +{ + +namespace detail +{ + // EdgeDir tags + struct in_edge_tag + { + }; + struct out_edge_tag + { + }; + + template < class Vertex, class Edge, class Iterator1D, class EdgeDir > + struct bidir_incidence_iterator + { + typedef bidir_incidence_iterator self; + typedef Edge edge_type; + typedef typename Edge::property_type EdgeProperty; + + public: + typedef int difference_type; + typedef std::forward_iterator_tag iterator_category; + typedef edge_type reference; + typedef edge_type value_type; + typedef value_type* pointer; + inline bidir_incidence_iterator() {} + inline bidir_incidence_iterator(Iterator1D ii, Vertex src) + : i(ii), _src(src) + { + } + + inline self& operator++() + { + ++i; + return *this; + } + inline self operator++(int) + { + self tmp = *this; + ++(*this); + return tmp; + } + + inline reference operator*() const { return deref_helper(EdgeDir()); } + inline self* operator->() { return this; } + + Iterator1D& iter() { return i; } + const Iterator1D& iter() const { return i; } + + Iterator1D i; + Vertex _src; + + protected: + inline reference deref_helper(out_edge_tag) const + { + return edge_type(_src, (*i).get_target(), &(*i).get_property()); + } + inline reference deref_helper(in_edge_tag) const + { + return edge_type((*i).get_target(), _src, &(*i).get_property()); + } + }; + + template < class V, class E, class Iter, class Dir > + inline bool operator==(const bidir_incidence_iterator< V, E, Iter, Dir >& x, + const bidir_incidence_iterator< V, E, Iter, Dir >& y) + { + return x.i == y.i; + } + template < class V, class E, class Iter, class Dir > + inline bool operator!=(const bidir_incidence_iterator< V, E, Iter, Dir >& x, + const bidir_incidence_iterator< V, E, Iter, Dir >& y) + { + return x.i != y.i; + } + +} +} +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/incremental_components.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/incremental_components.hpp new file mode 100644 index 0000000000..8941f67283 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/incremental_components.hpp @@ -0,0 +1,92 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Copyright 2009 Trustees of Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP +#define BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP + +#include <boost/operators.hpp> + +namespace boost +{ + +namespace detail +{ + + // Iterator for a component index linked list. The contents of + // each array element represent the next index in the list. A + // special value (the maximum index + 1) is used to terminate a + // list. + template < typename IndexRandomAccessIterator > + class component_index_iterator + : boost::forward_iterator_helper< + component_index_iterator< IndexRandomAccessIterator >, + typename std::iterator_traits< + IndexRandomAccessIterator >::value_type, + typename std::iterator_traits< + IndexRandomAccessIterator >::difference_type, + typename std::iterator_traits< IndexRandomAccessIterator >::pointer, + typename std::iterator_traits< + IndexRandomAccessIterator >::reference > + { + + private: + typedef component_index_iterator< IndexRandomAccessIterator > self; + + public: + typedef std::forward_iterator_tag iterator_category; + typedef typename std::iterator_traits< + IndexRandomAccessIterator >::value_type value_type; + typedef typename std::iterator_traits< + IndexRandomAccessIterator >::difference_type reference; + typedef + typename std::iterator_traits< IndexRandomAccessIterator >::pointer + pointer; + typedef typename std::iterator_traits< + IndexRandomAccessIterator >::reference difference_type; + + // Constructor for "begin" iterator + component_index_iterator( + IndexRandomAccessIterator index_iterator, value_type begin_index) + : m_index_iterator(index_iterator), m_current_index(begin_index) + { + } + + // Constructor for "end" iterator (end_index should be the linked + // list terminator). + component_index_iterator(value_type end_index) + : m_current_index(end_index) + { + } + + inline value_type operator*() const { return (m_current_index); } + + self& operator++() + { + // Move to the next element in the linked list + m_current_index = m_index_iterator[m_current_index]; + return (*this); + } + + bool operator==(const self& other_iterator) const + { + return (m_current_index == *other_iterator); + } + + protected: + IndexRandomAccessIterator m_index_iterator; + value_type m_current_index; + + }; // class component_index_iterator + +} // namespace detail + +} // namespace detail + +#endif // BOOST_GRAPH_DETAIL_INCREMENTAL_COMPONENTS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/index.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/index.hpp new file mode 100644 index 0000000000..7ffc843fc2 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/index.hpp @@ -0,0 +1,78 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_DETAIL_INDEX_HPP +#define BOOST_GRAPH_DETAIL_INDEX_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> + +// The structures in this module are responsible for selecting and defining +// types for accessing a builting index map. Note that the selection of these +// types requires the Graph parameter to model either VertexIndexGraph or +// EdgeIndexGraph. + +namespace boost +{ +namespace detail +{ + template < typename Graph > struct vertex_indexer + { + typedef vertex_index_t index_type; + typedef typename property_map< Graph, vertex_index_t >::type map_type; + typedef typename property_map< Graph, vertex_index_t >::const_type + const_map_type; + typedef typename property_traits< map_type >::value_type value_type; + typedef typename graph_traits< Graph >::vertex_descriptor key_type; + + static const_map_type index_map(const Graph& g) + { + return get(vertex_index, g); + } + + static map_type index_map(Graph& g) { return get(vertex_index, g); } + + static value_type index(key_type k, const Graph& g) + { + return get(vertex_index, g, k); + } + }; + + template < typename Graph > struct edge_indexer + { + typedef edge_index_t index_type; + typedef typename property_map< Graph, edge_index_t >::type map_type; + typedef typename property_map< Graph, edge_index_t >::const_type + const_map_type; + typedef typename property_traits< map_type >::value_type value_type; + typedef typename graph_traits< Graph >::edge_descriptor key_type; + + static const_map_type index_map(const Graph& g) + { + return get(edge_index, g); + } + + static map_type index_map(Graph& g) { return get(edge_index, g); } + + static value_type index(key_type k, const Graph& g) + { + return get(edge_index, g, k); + } + }; + + // NOTE: The Graph parameter MUST be a model of VertexIndexGraph or + // VertexEdgeGraph - whichever type Key is selecting. + template < typename Graph, typename Key > struct choose_indexer + { + typedef typename mpl::if_< + is_same< Key, typename graph_traits< Graph >::vertex_descriptor >, + vertex_indexer< Graph >, edge_indexer< Graph > >::type indexer_type; + typedef typename indexer_type::index_type index_type; + }; +} +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/labeled_graph_traits.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/labeled_graph_traits.hpp new file mode 100644 index 0000000000..b6600dbb02 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/labeled_graph_traits.hpp @@ -0,0 +1,232 @@ +// Copyright (C) 2009 Andrew Sutton + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_LABELED_GRAPH_TRAITS_HPP +#define BOOST_GRAPH_LABELED_GRAPH_TRAITS_HPP + +#include <boost/graph/graph_mutability_traits.hpp> + +namespace boost +{ + +// Extend the graph mutability traits (and metafunctions) to include options +// for labeled graphs. + +// NOTE: the label_vertex tag denotes the fact that you can basically assign +// arbitrary labels to vertices without modifying the actual graph. + +// TODO: We might also overlay the uniqueness/multiplicity of labels in this +// hierarchy also. For now, we just assumed that labels are unique. + +struct label_vertex_tag +{ +}; +struct labeled_add_vertex_tag : virtual label_vertex_tag +{ +}; +struct labeled_add_vertex_property_tag : virtual labeled_add_vertex_tag +{ +}; +struct labeled_remove_vertex_tag +{ +}; +struct labeled_add_edge_tag : virtual label_vertex_tag +{ +}; +struct labeled_add_edge_property_tag : virtual labeled_add_edge_tag +{ +}; +struct labeled_remove_edge_tag +{ +}; + +struct labeled_mutable_vertex_graph_tag : virtual labeled_add_vertex_tag, + virtual labeled_remove_vertex_tag +{ +}; +struct labeled_mutable_vertex_property_graph_tag +: virtual labeled_add_vertex_property_tag, + virtual labeled_remove_vertex_tag +{ +}; +struct labeled_mutable_edge_graph_tag : virtual labeled_add_edge_tag, + virtual labeled_remove_edge_tag +{ +}; +struct labeled_mutable_edge_property_graph_tag +: virtual labeled_add_edge_property_tag, + virtual labeled_remove_edge_tag +{ +}; + +struct labeled_graph_tag : virtual label_vertex_tag +{ +}; +struct labeled_mutable_graph_tag : virtual labeled_mutable_vertex_graph_tag, + virtual labeled_mutable_edge_graph_tag +{ +}; +struct labeled_mutable_property_graph_tag +: virtual labeled_mutable_vertex_property_graph_tag, + virtual labeled_mutable_edge_property_graph_tag +{ +}; +struct labeled_add_only_property_graph_tag +: virtual labeled_add_vertex_property_tag, + virtual labeled_mutable_edge_property_graph_tag +{ +}; + +// Metafunctions + +template < typename Graph > +struct graph_has_add_vertex_by_label +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + labeled_add_vertex_tag >::value > +{ +}; + +template < typename Graph > +struct graph_has_add_vertex_by_label_with_property +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + labeled_add_vertex_property_tag >::value > +{ +}; + +template < typename Graph > +struct graph_has_remove_vertex_by_label +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + labeled_remove_vertex_tag >::value > +{ +}; + +template < typename Graph > +struct graph_has_add_edge_by_label +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + labeled_add_edge_tag >::value > +{ +}; + +template < typename Graph > +struct graph_has_add_edge_by_label_with_property +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + labeled_add_edge_property_tag >::value > +{ +}; + +template < typename Graph > +struct graph_has_remove_edge_by_label +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + labeled_remove_edge_tag >::value > +{ +}; + +template < typename Graph > +struct is_labeled_mutable_vertex_graph +: mpl::and_< graph_has_add_vertex_by_label< Graph >, + graph_has_remove_vertex_by_label< Graph > > +{ +}; + +template < typename Graph > +struct is_labeled_mutable_vertex_property_graph +: mpl::and_< graph_has_add_vertex_by_label< Graph >, + graph_has_remove_vertex_by_label< Graph > > +{ +}; + +template < typename Graph > +struct is_labeled_mutable_edge_graph +: mpl::and_< graph_has_add_edge_by_label< Graph >, + graph_has_remove_edge_by_label< Graph > > +{ +}; + +template < typename Graph > +struct is_labeled_mutable_edge_property_graph +: mpl::and_< graph_has_add_edge_by_label< Graph >, + graph_has_remove_edge_by_label< Graph > > +{ +}; + +template < typename Graph > +struct is_labeled_mutable_graph +: mpl::and_< is_labeled_mutable_vertex_graph< Graph >, + is_labeled_mutable_edge_graph< Graph > > +{ +}; + +template < typename Graph > +struct is_labeled_mutable_property_graph +: mpl::and_< is_labeled_mutable_vertex_property_graph< Graph >, + is_labeled_mutable_edge_property_graph< Graph > > +{ +}; + +template < typename Graph > +struct is_labeled_add_only_property_graph +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + labeled_add_only_property_graph_tag >::value > +{ +}; + +template < typename Graph > +struct is_labeled_graph +: mpl::bool_< + is_convertible< typename graph_mutability_traits< Graph >::category, + label_vertex_tag >::value > +{ +}; + +template < typename > struct graph_mutability_traits; + +namespace graph_detail +{ + // The determine mutability metafunction computes a labeled mutability tag + // based on the mutability of the given graph type. This is used by the + // graph_mutability_traits specialization below. + template < typename Graph > struct determine_mutability + { + typedef typename mpl::if_< is_add_only_property_graph< Graph >, + labeled_add_only_property_graph_tag, + typename mpl::if_< is_mutable_property_graph< Graph >, + labeled_mutable_property_graph_tag, + typename mpl::if_< is_mutable_graph< Graph >, + labeled_mutable_graph_tag, + typename mpl::if_< is_mutable_edge_graph< Graph >, + labeled_graph_tag, + typename graph_mutability_traits< Graph >::category >:: + type >::type >::type >::type type; + }; +} // namespace graph_detail + +#define LABELED_GRAPH_PARAMS typename G, typename L, typename S +#define LABELED_GRAPH labeled_graph< G, L, S > + +// Specialize mutability traits for the labeled graph. +// This specialization depends on the mutability of the underlying graph type. +// If the underlying graph is fully mutable, this is also fully mutable. +// Otherwise, it's different. +template < LABELED_GRAPH_PARAMS > +struct graph_mutability_traits< LABELED_GRAPH > +{ + typedef typename graph_detail::determine_mutability< + typename LABELED_GRAPH::graph_type >::type category; +}; + +#undef LABELED_GRAPH_PARAMS +#undef LABELED_GRAPH + +} // namespace boost + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/list_base.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/list_base.hpp new file mode 100644 index 0000000000..bd1fc17119 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/list_base.hpp @@ -0,0 +1,206 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_LIST_BASE_HPP +#define BOOST_LIST_BASE_HPP + +#include <boost/iterator_adaptors.hpp> + +// Perhaps this should go through formal review, and move to <boost/>. + +/* + An alternate interface idea: + Extend the std::list functionality by creating remove/insert + functions that do not require the container object! + */ + +namespace boost +{ +namespace detail +{ + + //========================================================================= + // Linked-List Generic Implementation Functions + + template < class Node, class Next > + inline Node slist_insert_after(Node pos, Node x, Next next) + { + next(x) = next(pos); + next(pos) = x; + return x; + } + + // return next(pos) or next(next(pos)) ? + template < class Node, class Next > + inline Node slist_remove_after(Node pos, Next next) + { + Node n = next(pos); + next(pos) = next(n); + return n; + } + + template < class Node, class Next > + inline Node slist_remove_range(Node before_first, Node last, Next next) + { + next(before_first) = last; + return last; + } + + template < class Node, class Next > + inline Node slist_previous(Node head, Node x, Node empty, Next next) + { + while (head != empty && next(head) != x) + head = next(head); + return head; + } + + template < class Node, class Next > + inline void slist_splice_after( + Node pos, Node before_first, Node before_last, Next next) + { + if (pos != before_first && pos != before_last) + { + Node first = next(before_first); + Node after = next(pos); + next(before_first) = next(before_last); + next(pos) = first; + next(before_last) = after; + } + } + + template < class Node, class Next > + inline Node slist_reverse(Node node, Node empty, Next next) + { + Node result = node; + node = next(node); + next(result) = empty; + while (node) + { + Node next = next(node); + next(node) = result; + result = node; + node = next; + } + return result; + } + + template < class Node, class Next > + inline std::size_t slist_size(Node head, Node empty, Next next) + { + std::size_t s = 0; + for (; head != empty; head = next(head)) + ++s; + return s; + } + + template < class Next, class Data > class slist_iterator_policies + { + public: + explicit slist_iterator_policies(const Next& n, const Data& d) + : m_next(n), m_data(d) + { + } + + template < class Reference, class Node > + Reference dereference(type< Reference >, const Node& x) const + { + return m_data(x); + } + + template < class Node > void increment(Node& x) const { x = m_next(x); } + + template < class Node > bool equal(Node& x, Node& y) const + { + return x == y; + } + + protected: + Next m_next; + Data m_data; + }; + + //=========================================================================== + // Doubly-Linked List Generic Implementation Functions + + template < class Node, class Next, class Prev > + inline void dlist_insert_before(Node pos, Node x, Next next, Prev prev) + { + next(x) = pos; + prev(x) = prev(pos); + next(prev(pos)) = x; + prev(pos) = x; + } + + template < class Node, class Next, class Prev > + void dlist_remove(Node pos, Next next, Prev prev) + { + Node next_node = next(pos); + Node prev_node = prev(pos); + next(prev_node) = next_node; + prev(next_node) = prev_node; + } + + // This deletes every node in the list except the + // sentinel node. + template < class Node, class Delete > + inline void dlist_clear(Node sentinel, Delete del) + { + Node i, tmp; + i = next(sentinel); + while (i != sentinel) + { + tmp = i; + i = next(i); + del(tmp); + } + } + + template < class Node > inline bool dlist_empty(Node dummy) + { + return next(dummy) == dummy; + } + + template < class Node, class Next, class Prev > + void dlist_transfer(Node pos, Node first, Node last, Next next, Prev prev) + { + if (pos != last) + { + // Remove [first,last) from its old position + next(prev(last)) = pos; + next(prev(first)) = last; + next(prev(pos)) = first; + + // Splice [first,last) into its new position + Node tmp = prev(pos); + prev(pos) = prev(last); + prev(last) = prev(first); + prev(first) = tmp; + } + } + + template < class Next, class Prev, class Data > + class dlist_iterator_policies : public slist_iterator_policies< Next, Data > + { + typedef slist_iterator_policies< Next, Data > Base; + + public: + template < class Node > void decrement(Node& x) const { x = m_prev(x); } + + dlist_iterator_policies(Next n, Prev p, Data d) : Base(n, d), m_prev(p) + { + } + + protected: + Prev m_prev; + }; + +} // namespace detail +} // namespace boost + +#endif // BOOST_LIST_BASE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/permutation.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/permutation.hpp new file mode 100644 index 0000000000..31ced8e79b --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/permutation.hpp @@ -0,0 +1,211 @@ +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PERMUTATION_HPP +#define BOOST_PERMUTATION_HPP + +#include <vector> +#include <memory> +#include <functional> +#include <algorithm> +#include <boost/graph/detail/shadow_iterator.hpp> + +namespace boost +{ + +template < class Iter1, class Iter2 > +void permute_serial(Iter1 permuter, Iter1 last, Iter2 result) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t D : +#else + typedef typename std::iterator_traits< Iter1 >::difference_type D; +#endif + + D n + = 0; + while (permuter != last) + { + std::swap(result[n], result[*permuter]); + ++n; + ++permuter; + } +} + +template < class InIter, class RandIterP, class RandIterR > +void permute_copy(InIter first, InIter last, RandIterP p, RandIterR result) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t i = 0; +#else + typename std::iterator_traits< RandIterP >::difference_type i = 0; +#endif + for (; first != last; ++first, ++i) + result[p[i]] = *first; +} + +namespace detail +{ + + template < class RandIter, class RandIterPerm, class D, class T > + void permute_helper(RandIter first, RandIter last, RandIterPerm p, D, T) + { + D i = 0, pi, n = last - first, cycle_start; + T tmp; + std::vector< int > visited(n, false); + + while (i != n) + { // continue until all elements have been processed + cycle_start = i; + tmp = first[i]; + do + { // walk around a cycle + pi = p[i]; + visited[pi] = true; + std::swap(tmp, first[pi]); + i = pi; + } while (i != cycle_start); + + // find the next cycle + for (i = 0; i < n; ++i) + if (visited[i] == false) + break; + } + } + +} // namespace detail + +template < class RandIter, class RandIterPerm > +void permute(RandIter first, RandIter last, RandIterPerm p) +{ + detail::permute_helper(first, last, p, last - first, *first); +} + +// Knuth 1.3.3, Vol. 1 p 176 +// modified for zero-based arrays +// time complexity? +// +// WARNING: T must be a signed integer! +template < class PermIter > void invert_permutation(PermIter X, PermIter Xend) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t T : +#else + typedef typename std::iterator_traits< PermIter >::value_type T; +#endif + T n + = Xend - X; + T m = n; + T j = -1; + + while (m > 0) + { + T i = X[m - 1] + 1; + if (i > 0) + { + do + { + X[m - 1] = j - 1; + j = -m; + m = i; + i = X[m - 1] + 1; + } while (i > 0); + i = j; + } + X[m - 1] = -i - 1; + --m; + } +} + +// Takes a "normal" permutation array (and its inverse), and turns it +// into a BLAS-style permutation array (which can be thought of as a +// serialized permutation). +template < class Iter1, class Iter2, class Iter3 > +inline void serialize_permutation(Iter1 q, Iter1 q_end, Iter2 q_inv, Iter3 p) +{ +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + typedef std::ptrdiff_t P1; + typedef std::ptrdiff_t P2; + typedef std::ptrdiff_t D; +#else + typedef typename std::iterator_traits< Iter1 >::value_type P1; + typedef typename std::iterator_traits< Iter2 >::value_type P2; + typedef typename std::iterator_traits< Iter1 >::difference_type D; +#endif + D n = q_end - q; + for (D i = 0; i < n; ++i) + { + P1 qi = q[i]; + P2 qii = q_inv[i]; + *p++ = qii; + std::swap(q[i], q[qii]); + std::swap(q_inv[i], q_inv[qi]); + } +} + +// Not used anymore, leaving it here for future reference. +template < typename Iter, typename Compare > +void merge_sort(Iter first, Iter last, Compare cmp) +{ + if (first + 1 < last) + { + Iter mid = first + (last - first) / 2; + merge_sort(first, mid, cmp); + merge_sort(mid, last, cmp); + std::inplace_merge(first, mid, last, cmp); + } +} + +// time: N log N + 3N + ? +// space: 2N +template < class Iter, class IterP, class Cmp, class Alloc > +inline void sortp(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc) +{ + typedef typename std::iterator_traits< IterP >::value_type P; + typedef typename std::iterator_traits< IterP >::difference_type D; + D n = last - first; + std::vector< P, Alloc > q(n); + for (D i = 0; i < n; ++i) + q[i] = i; + std::sort(make_shadow_iter(first, q.begin()), + make_shadow_iter(last, q.end()), shadow_cmp< Cmp >(cmp)); + invert_permutation(q.begin(), q.end()); + std::copy(q.begin(), q.end(), p); +} + +template < class Iter, class IterP, class Cmp > +inline void sortp(Iter first, Iter last, IterP p, Cmp cmp) +{ + typedef typename std::iterator_traits< IterP >::value_type P; + sortp(first, last, p, cmp, std::allocator< P >()); +} + +template < class Iter, class IterP > +inline void sortp(Iter first, Iter last, IterP p) +{ + typedef typename std::iterator_traits< Iter >::value_type T; + typedef typename std::iterator_traits< IterP >::value_type P; + sortp(first, last, p, std::less< T >(), std::allocator< P >()); +} + +template < class Iter, class IterP, class Cmp, class Alloc > +inline void sortv(Iter first, Iter last, IterP p, Cmp cmp, Alloc alloc) +{ + typedef typename std::iterator_traits< IterP >::value_type P; + typedef typename std::iterator_traits< IterP >::difference_type D; + D n = last - first; + std::vector< P, Alloc > q(n), q_inv(n); + for (D i = 0; i < n; ++i) + q_inv[i] = i; + std::sort(make_shadow_iter(first, q_inv.begin()), + make_shadow_iter(last, q_inv.end()), shadow_cmp< Cmp >(cmp)); + std::copy(q_inv, q_inv.end(), q.begin()); + invert_permutation(q.begin(), q.end()); + serialize_permutation(q.begin(), q.end(), q_inv.end(), p); +} + +} // namespace boost + +#endif // BOOST_PERMUTATION_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/self_avoiding_walk.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/self_avoiding_walk.hpp new file mode 100644 index 0000000000..52ad1cbb92 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/self_avoiding_walk.hpp @@ -0,0 +1,483 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_SELF_AVOIDING_WALK_HPP +#define BOOST_SELF_AVOIDING_WALK_HPP + +/* + This file defines necessary components for SAW. + + mesh language: (defined by myself to clearify what is what) + A triangle in mesh is called an triangle. + An edge in mesh is called an line. + A vertex in mesh is called a point. + + A triangular mesh corresponds to a graph in which a vertex is a + triangle and an edge(u, v) stands for triangle u and triangle v + share an line. + + After this point, a vertex always refers to vertex in graph, + therefore it is a traingle in mesh. + + */ + +#include <utility> +#include <boost/config.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/property_map/property_map.hpp> + +#define SAW_SENTINAL -1 + +namespace boost +{ + +template < class T1, class T2, class T3 > struct triple +{ + T1 first; + T2 second; + T3 third; + triple(const T1& a, const T2& b, const T3& c) + : first(a), second(b), third(c) + { + } + triple() : first(SAW_SENTINAL), second(SAW_SENTINAL), third(SAW_SENTINAL) {} +}; + +typedef triple< int, int, int > Triple; + +/* Define a vertex property which has a triangle inside. Triangle is + represented by a triple. */ +struct triangle_tag +{ + enum + { + num = 100 + }; +}; +typedef property< triangle_tag, Triple > triangle_property; + +/* Define an edge property with a line. A line is represented by a + pair. This is not required for SAW though. +*/ +struct line_tag +{ + enum + { + num = 101 + }; +}; +template < class T > +struct line_property : public property< line_tag, std::pair< T, T > > +{ +}; + +/*Precondition: Points in a Triangle are in order */ +template < class Triangle, class Line > +inline void get_sharing(const Triangle& a, const Triangle& b, Line& l) +{ + l.first = SAW_SENTINAL; + l.second = SAW_SENTINAL; + + if (a.first == b.first) + { + l.first = a.first; + if (a.second == b.second || a.second == b.third) + l.second = a.second; + else if (a.third == b.second || a.third == b.third) + l.second = a.third; + } + else if (a.first == b.second) + { + l.first = a.first; + if (a.second == b.third) + l.second = a.second; + else if (a.third == b.third) + l.second = a.third; + } + else if (a.first == b.third) + { + l.first = a.first; + } + else if (a.second == b.first) + { + l.first = a.second; + if (a.third == b.second || a.third == b.third) + l.second = a.third; + } + else if (a.second == b.second) + { + l.first = a.second; + if (a.third == b.third) + l.second = a.third; + } + else if (a.second == b.third) + { + l.first = a.second; + } + else if (a.third == b.first || a.third == b.second || a.third == b.third) + l.first = a.third; + + /*Make it in order*/ + if (l.first > l.second) + { + typename Line::first_type i = l.first; + l.first = l.second; + l.second = i; + } +} + +template < class TriangleDecorator, class Vertex, class Line > +struct get_vertex_sharing +{ + typedef std::pair< Vertex, Line > Pair; + get_vertex_sharing(const TriangleDecorator& _td) : td(_td) {} + inline Line operator()(const Vertex& u, const Vertex& v) const + { + Line l; + get_sharing(td[u], td[v], l); + return l; + } + inline Line operator()(const Pair& u, const Vertex& v) const + { + Line l; + get_sharing(td[u.first], td[v], l); + return l; + } + inline Line operator()(const Pair& u, const Pair& v) const + { + Line l; + get_sharing(td[u.first], td[v.first], l); + return l; + } + TriangleDecorator td; +}; + +/* HList has to be a handle of data holder so that pass-by-value is + * in right logic. + * + * The element of HList is a pair of vertex and line. (remember a + * line is a pair of two ints.). That indicates the walk w from + * current vertex is across line. (If the first of line is -1, it is + * a point though. + */ +template < class TriangleDecorator, class HList, class IteratorD > +class SAW_visitor : public bfs_visitor<>, public dfs_visitor<> +{ + typedef typename boost::property_traits< IteratorD >::value_type iter; + /*use boost shared_ptr*/ + typedef typename HList::element_type::value_type::second_type Line; + +public: + typedef tree_edge_tag category; + + inline SAW_visitor(TriangleDecorator _td, HList _hlist, IteratorD ia) + : td(_td), hlist(_hlist), iter_d(ia) + { + } + + template < class Vertex, class Graph > + inline void start_vertex(Vertex v, Graph&) + { + Line l1; + l1.first = SAW_SENTINAL; + l1.second = SAW_SENTINAL; + hlist->push_front(std::make_pair(v, l1)); + iter_d[v] = hlist->begin(); + } + + /*Several symbols: + w(i): i-th triangle in walk w + w(i) |- w(i+1): w enter w(i+1) from w(i) over a line + w(i) ~> w(i+1): w enter w(i+1) from w(i) over a point + w(i) -> w(i+1): w enter w(i+1) from w(i) + w(i) ^ w(i+1): the line or point w go over from w(i) to w(i+1) + */ + template < class Edge, class Graph > bool tree_edge(Edge e, Graph& G) + { + using std::make_pair; + typedef typename boost::graph_traits< Graph >::vertex_descriptor Vertex; + Vertex tau = target(e, G); + Vertex i = source(e, G); + + get_vertex_sharing< TriangleDecorator, Vertex, Line > get_sharing_line( + td); + + Line tau_i = get_sharing_line(tau, i); + + iter w_end = hlist->end(); + + iter w_i = iter_d[i]; + + iter w_i_m_1 = w_i; + iter w_i_p_1 = w_i; + + /*---------------------------------------------------------- + * true false + *========================================================== + *a w(i-1) |- w(i) w(i-1) ~> w(i) or w(i-1) is null + *---------------------------------------------------------- + *b w(i) |- w(i+1) w(i) ~> w(i+1) or no w(i+1) yet + *---------------------------------------------------------- + */ + + bool a = false, b = false; + + --w_i_m_1; + ++w_i_p_1; + b = (w_i->second.first != SAW_SENTINAL); + + if (w_i_m_1 != w_end) + { + a = (w_i_m_1->second.first != SAW_SENTINAL); + } + + if (a) + { + + if (b) + { + /*Case 1: + + w(i-1) |- w(i) |- w(i+1) + */ + Line l1 = get_sharing_line(*w_i_m_1, tau); + + iter w_i_m_2 = w_i_m_1; + --w_i_m_2; + + bool c = true; + + if (w_i_m_2 != w_end) + { + c = w_i_m_2->second != l1; + } + + if (c) + { /* w(i-1) ^ tau != w(i-2) ^ w(i-1) */ + /*extension: w(i-1) -> tau |- w(i) */ + w_i_m_1->second = l1; + /*insert(pos, const T&) is to insert before pos*/ + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + } + else + { /* w(i-1) ^ tau == w(i-2) ^ w(i-1) */ + /*must be w(i-2) ~> w(i-1) */ + + bool d = true; + // need to handle the case when w_i_p_1 is null + Line l3 = get_sharing_line(*w_i_p_1, tau); + if (w_i_p_1 != w_end) + d = w_i_p_1->second != l3; + if (d) + { /* w(i+1) ^ tau != w(i+1) ^ w(i+2) */ + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + iter_d[tau] + = hlist->insert(w_i_p_1, make_pair(tau, l3)); + } + else + { /* w(i+1) ^ tau == w(i+1) ^ w(i+2) */ + /*must be w(1+1) ~> w(i+2) */ + Line l5 = get_sharing_line(*w_i_m_1, *w_i_p_1); + if (l5 != w_i_p_1->second) + { /* w(i-1) ^ w(i+1) != w(i+1) ^ w(i+2) */ + /*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> + * w(i+1) */ + w_i_m_2->second = get_sharing_line(*w_i_m_2, tau); + iter_d[tau] + = hlist->insert(w_i, make_pair(tau, tau_i)); + w_i->second = w_i_m_1->second; + w_i_m_1->second = l5; + iter_d[w_i_m_1->first] + = hlist->insert(w_i_p_1, *w_i_m_1); + hlist->erase(w_i_m_1); + } + else + { + /*mesh is tetrahedral*/ + // dont know what that means. + ; + } + } + } + } + else + { + /*Case 2: + + w(i-1) |- w(i) ~> w(1+1) + */ + + if (w_i->second.second == tau_i.first + || w_i->second.second == tau_i.second) + { /*w(i) ^ w(i+1) < w(i) ^ tau*/ + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + Line l1 = get_sharing_line(*w_i_p_1, tau); + iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1)); + } + else + { /*w(i) ^ w(i+1) !< w(i) ^ tau*/ + Line l1 = get_sharing_line(*w_i_m_1, tau); + bool c = true; + iter w_i_m_2 = w_i_m_1; + --w_i_m_2; + if (w_i_m_2 != w_end) + c = l1 != w_i_m_2->second; + if (c) + { /*w(i-1) ^ tau != w(i-2) ^ w(i-1)*/ + /*extension: w(i-1) -> tau |- w(i)*/ + w_i_m_1->second = l1; + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + } + else + { /*w(i-1) ^ tau == w(i-2) ^ w(i-1)*/ + /*must be w(i-2)~>w(i-1)*/ + /*extension: w(i-2) -> tau |- w(i) |- w(i-1) -> w(i+1)*/ + w_i_m_2->second = get_sharing_line(*w_i_m_2, tau); + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + w_i->second = w_i_m_1->second; + w_i_m_1->second = get_sharing_line(*w_i_m_1, *w_i_p_1); + iter_d[w_i_m_1->first] + = hlist->insert(w_i_p_1, *w_i_m_1); + hlist->erase(w_i_m_1); + } + } + } + } + else + { + + if (b) + { + /*Case 3: + + w(i-1) ~> w(i) |- w(i+1) + */ + bool c = false; + if (w_i_m_1 != w_end) + c = (w_i_m_1->second.second == tau_i.first) + || (w_i_m_1->second.second == tau_i.second); + + if (c) + { /*w(i-1) ^ w(i) < w(i) ^ tau*/ + /* extension: w(i-1) -> tau |- w(i) */ + if (w_i_m_1 != w_end) + w_i_m_1->second = get_sharing_line(*w_i_m_1, tau); + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + } + else + { + bool d = true; + Line l1; + l1.first = SAW_SENTINAL; + l1.second = SAW_SENTINAL; + if (w_i_p_1 != w_end) + { + l1 = get_sharing_line(*w_i_p_1, tau); + d = l1 != w_i_p_1->second; + } + if (d) + { /*w(i+1) ^ tau != w(i+1) ^ w(i+2)*/ + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + iter_d[tau] + = hlist->insert(w_i_p_1, make_pair(tau, l1)); + } + else + { + /*must be w(i+1) ~> w(i+2)*/ + /*extension: w(i-1) -> w(i+1) |- w(i) |- tau -> w(i+2) + */ + iter w_i_p_2 = w_i_p_1; + ++w_i_p_2; + + w_i_p_1->second = w_i->second; + iter_d[i] = hlist->insert(w_i_p_2, make_pair(i, tau_i)); + hlist->erase(w_i); + Line l2 = get_sharing_line(*w_i_p_2, tau); + iter_d[tau] + = hlist->insert(w_i_p_2, make_pair(tau, l2)); + } + } + } + else + { + /*Case 4: + + w(i-1) ~> w(i) ~> w(i+1) + + */ + bool c = false; + if (w_i_m_1 != w_end) + { + c = (w_i_m_1->second.second == tau_i.first) + || (w_i_m_1->second.second == tau_i.second); + } + if (c) + { /*w(i-1) ^ w(i) < w(i) ^ tau */ + /*extension: w(i-1) -> tau |- w(i) */ + if (w_i_m_1 != w_end) + w_i_m_1->second = get_sharing_line(*w_i_m_1, tau); + iter_d[tau] = hlist->insert(w_i, make_pair(tau, tau_i)); + } + else + { + /*extension: w(i) |- tau -> w(i+1) */ + w_i->second = tau_i; + Line l1; + l1.first = SAW_SENTINAL; + l1.second = SAW_SENTINAL; + if (w_i_p_1 != w_end) + l1 = get_sharing_line(*w_i_p_1, tau); + iter_d[tau] = hlist->insert(w_i_p_1, make_pair(tau, l1)); + } + } + } + + return true; + } + +protected: + TriangleDecorator td; /*a decorator for vertex*/ + HList hlist; + /*This must be a handle of list to record the SAW + The element type of the list is pair<Vertex, Line> + */ + + IteratorD iter_d; + /*Problem statement: Need a fast access to w for triangle i. + *Possible solution: mantain an array to record. + iter_d[i] will return an iterator + which points to w(i), where i is a vertex + representing triangle i. + */ +}; + +template < class Triangle, class HList, class Iterator > +inline SAW_visitor< Triangle, HList, Iterator > visit_SAW( + Triangle t, HList hl, Iterator i) +{ + return SAW_visitor< Triangle, HList, Iterator >(t, hl, i); +} + +template < class Tri, class HList, class Iter > +inline SAW_visitor< random_access_iterator_property_map< Tri*, Tri, Tri& >, + HList, random_access_iterator_property_map< Iter*, Iter, Iter& > > +visit_SAW_ptr(Tri* t, HList hl, Iter* i) +{ + typedef random_access_iterator_property_map< Tri*, Tri, Tri& > TriD; + typedef random_access_iterator_property_map< Iter*, Iter, Iter& > IterD; + return SAW_visitor< TriD, HList, IterD >(t, hl, i); +} + +// should also have combo's of pointers, and also const :( + +} + +#endif /*BOOST_SAW_H*/ diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/shadow_iterator.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/shadow_iterator.hpp new file mode 100644 index 0000000000..060d13fcc9 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/shadow_iterator.hpp @@ -0,0 +1,183 @@ +// (C) Copyright Jeremy Siek 2001. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_SHADOW_ITERATOR_HPP +#define BOOST_SHADOW_ITERATOR_HPP + +#include <boost/iterator_adaptors.hpp> +#include <boost/operators.hpp> + +namespace boost +{ + +namespace detail +{ + + template < class A, class B, class D > + class shadow_proxy : boost::operators< shadow_proxy< A, B, D > > + { + typedef shadow_proxy self; + + public: + inline shadow_proxy(A aa, B bb) : a(aa), b(bb) {} + inline shadow_proxy(const self& x) : a(x.a), b(x.b) {} + template < class Self > inline shadow_proxy(Self x) : a(x.a), b(x.b) {} + inline self& operator=(const self& x) + { + a = x.a; + b = x.b; + return *this; + } + inline self& operator++() + { + ++a; + return *this; + } + inline self& operator--() + { + --a; + return *this; + } + inline self& operator+=(const self& x) + { + a += x.a; + return *this; + } + inline self& operator-=(const self& x) + { + a -= x.a; + return *this; + } + inline self& operator*=(const self& x) + { + a *= x.a; + return *this; + } + inline self& operator/=(const self& x) + { + a /= x.a; + return *this; + } + inline self& operator%=(const self& x) { return *this; } // JGS + inline self& operator&=(const self& x) { return *this; } // JGS + inline self& operator|=(const self& x) { return *this; } // JGS + inline self& operator^=(const self& x) { return *this; } // JGS + inline friend D operator-(const self& x, const self& y) + { + return x.a - y.a; + } + inline bool operator==(const self& x) const { return a == x.a; } + inline bool operator<(const self& x) const { return a < x.a; } + // protected: + A a; + B b; + }; + + struct shadow_iterator_policies + { + template < typename iter_pair > void initialize(const iter_pair&) {} + + template < typename Iter > + typename Iter::reference dereference(const Iter& i) const + { + typedef typename Iter::reference R; + return R(*i.base().first, *i.base().second); + } + template < typename Iter > + bool equal(const Iter& p1, const Iter& p2) const + { + return p1.base().first == p2.base().first; + } + template < typename Iter > void increment(Iter& i) + { + ++i.base().first; + ++i.base().second; + } + + template < typename Iter > void decrement(Iter& i) + { + --i.base().first; + --i.base().second; + } + + template < typename Iter > bool less(const Iter& x, const Iter& y) const + { + return x.base().first < y.base().first; + } + template < typename Iter > + typename Iter::difference_type distance( + const Iter& x, const Iter& y) const + { + return y.base().first - x.base().first; + } + template < typename D, typename Iter > void advance(Iter& p, D n) + { + p.base().first += n; + p.base().second += n; + } + }; + +} // namespace detail + +template < typename IterA, typename IterB > struct shadow_iterator_generator +{ + + // To use the iterator_adaptor we can't derive from + // random_access_iterator because we don't have a real reference. + // However, we want the STL algorithms to treat the shadow + // iterator like a random access iterator. + struct shadow_iterator_tag : public std::input_iterator_tag + { + operator std::random_access_iterator_tag() + { + return std::random_access_iterator_tag(); + }; + }; + typedef typename std::iterator_traits< IterA >::value_type Aval; + typedef typename std::iterator_traits< IterB >::value_type Bval; + typedef typename std::iterator_traits< IterA >::reference Aref; + typedef typename std::iterator_traits< IterB >::reference Bref; + typedef typename std::iterator_traits< IterA >::difference_type D; + typedef detail::shadow_proxy< Aval, Bval, Aval > V; + typedef detail::shadow_proxy< Aref, Bref, Aval > R; + typedef iterator_adaptor< std::pair< IterA, IterB >, + detail::shadow_iterator_policies, V, R, V*, shadow_iterator_tag, D > + type; +}; + +// short cut for creating a shadow iterator +template < class IterA, class IterB > +inline typename shadow_iterator_generator< IterA, IterB >::type +make_shadow_iter(IterA a, IterB b) +{ + typedef typename shadow_iterator_generator< IterA, IterB >::type Iter; + return Iter(std::make_pair(a, b)); +} + +template < class Cmp > struct shadow_cmp +{ + inline shadow_cmp(const Cmp& c) : cmp(c) {} + template < class ShadowProxy1, class ShadowProxy2 > + inline bool operator()(const ShadowProxy1& x, const ShadowProxy2& y) const + { + return cmp(x.a, y.a); + } + Cmp cmp; +}; + +} // namespace boost + +namespace std +{ +template < class A1, class B1, class D1, class A2, class B2, class D2 > +void swap(boost::detail::shadow_proxy< A1&, B1&, D1 > x, + boost::detail::shadow_proxy< A2&, B2&, D2 > y) +{ + std::swap(x.a, y.a); + std::swap(x.b, y.b); +} +} + +#endif // BOOST_SHADOW_ITERATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/detail/sparse_ordering.hpp b/contrib/restricted/boost/graph/include/boost/graph/detail/sparse_ordering.hpp new file mode 100644 index 0000000000..b7bf470db0 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/detail/sparse_ordering.hpp @@ -0,0 +1,210 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004, 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// Doug Gregor, D. Kevin McGrath +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//=======================================================================// +#ifndef BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP +#define BOOST_GRAPH_DETAIL_SPARSE_ORDERING_HPP + +#include <boost/config.hpp> +#include <vector> +#include <queue> +#include <boost/pending/queue.hpp> +#include <boost/pending/mutable_queue.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/breadth_first_search.hpp> +#include <boost/graph/properties.hpp> +#include <boost/pending/indirect_cmp.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/depth_first_search.hpp> + +namespace boost +{ + +namespace sparse +{ + + // rcm_queue + // + // This is a custom queue type used in the + // *_ordering algorithms. + // In addition to the normal queue operations, the + // rcm_queue provides: + // + // int eccentricity() const; + // value_type spouse() const; + // + + // yes, it's a bad name...but it works, so use it + template < class Vertex, class DegreeMap, + class Container = std::deque< Vertex > > + class rcm_queue : public std::queue< Vertex, Container > + { + typedef std::queue< Vertex > base; + + public: + typedef typename base::value_type value_type; + typedef typename base::size_type size_type; + + /* SGI queue has not had a contructor queue(const Container&) */ + inline rcm_queue(DegreeMap deg) + : _size(0), Qsize(1), eccen(-1), degree(deg) + { + } + + inline void pop() + { + if (!_size) + Qsize = base::size(); + + base::pop(); + if (_size == Qsize - 1) + { + _size = 0; + ++eccen; + } + else + ++_size; + } + + inline value_type& front() + { + value_type& u = base::front(); + if (_size == 0) + w = u; + else if (get(degree, u) < get(degree, w)) + w = u; + return u; + } + + inline const value_type& front() const + { + const value_type& u = base::front(); + if (_size == 0) + w = u; + else if (get(degree, u) < get(degree, w)) + w = u; + return u; + } + + inline value_type& top() { return front(); } + inline const value_type& top() const { return front(); } + + inline size_type size() const { return base::size(); } + + inline size_type eccentricity() const { return eccen; } + inline value_type spouse() const { return w; } + + protected: + size_type _size; + size_type Qsize; + int eccen; + mutable value_type w; + DegreeMap degree; + }; + + template < typename Tp, typename Sequence = std::deque< Tp > > + class sparse_ordering_queue : public boost::queue< Tp, Sequence > + { + public: + typedef typename Sequence::iterator iterator; + typedef typename Sequence::reverse_iterator reverse_iterator; + typedef queue< Tp, Sequence > base; + typedef typename Sequence::size_type size_type; + + inline iterator begin() { return this->c.begin(); } + inline reverse_iterator rbegin() { return this->c.rbegin(); } + inline iterator end() { return this->c.end(); } + inline reverse_iterator rend() { return this->c.rend(); } + inline Tp& operator[](int n) { return this->c[n]; } + inline size_type size() { return this->c.size(); } + + protected: + // nothing + }; + +} // namespace sparse + +// Compute Pseudo peripheral +// +// To compute an approximated peripheral for a given vertex. +// Used in <tt>king_ordering</tt> algorithm. +// +template < class Graph, class Vertex, class ColorMap, class DegreeMap > +Vertex pseudo_peripheral_pair( + Graph const& G, const Vertex& u, int& ecc, ColorMap color, DegreeMap degree) +{ + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + + sparse::rcm_queue< Vertex, DegreeMap > Q(degree); + + typename boost::graph_traits< Graph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + if (get(color, *ui) != Color::red()) + put(color, *ui, Color::white()); + breadth_first_visit(G, u, buffer(Q).color_map(color)); + + ecc = Q.eccentricity(); + return Q.spouse(); +} + +// Find a good starting node +// +// This is to find a good starting node for the +// king_ordering algorithm. "good" is in the sense +// of the ordering generated by RCM. +// +template < class Graph, class Vertex, class Color, class Degree > +Vertex find_starting_node(Graph const& G, Vertex r, Color color, Degree degree) +{ + Vertex x, y; + int eccen_r, eccen_x; + + x = pseudo_peripheral_pair(G, r, eccen_r, color, degree); + y = pseudo_peripheral_pair(G, x, eccen_x, color, degree); + + while (eccen_x > eccen_r) + { + r = x; + eccen_r = eccen_x; + x = y; + y = pseudo_peripheral_pair(G, x, eccen_x, color, degree); + } + return x; +} + +template < typename Graph > +class out_degree_property_map +: public put_get_helper< typename graph_traits< Graph >::degree_size_type, + out_degree_property_map< Graph > > +{ +public: + typedef typename graph_traits< Graph >::vertex_descriptor key_type; + typedef typename graph_traits< Graph >::degree_size_type value_type; + typedef value_type reference; + typedef readable_property_map_tag category; + out_degree_property_map(const Graph& g) : m_g(g) {} + value_type operator[](const key_type& v) const + { + return out_degree(v, m_g); + } + +private: + const Graph& m_g; +}; +template < typename Graph > +inline out_degree_property_map< Graph > make_out_degree_map(const Graph& g) +{ + return out_degree_property_map< Graph >(g); +} + +} // namespace boost + +#endif // BOOST_GRAPH_KING_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp b/contrib/restricted/boost/graph/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp new file mode 100644 index 0000000000..09607c49a3 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/dijkstra_shortest_paths_no_color_map.hpp @@ -0,0 +1,235 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2009 Trustees of Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP +#define BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP + +#include <boost/pending/indirect_cmp.hpp> +#include <boost/graph/relax.hpp> +#include <boost/graph/detail/d_ary_heap.hpp> +#include <boost/graph/dijkstra_shortest_paths.hpp> +#include <boost/graph/iteration_macros.hpp> + +namespace boost +{ + +// No init version +template < typename Graph, typename DijkstraVisitor, typename PredecessorMap, + typename DistanceMap, typename WeightMap, typename VertexIndexMap, + typename DistanceCompare, typename DistanceWeightCombine, + typename DistanceInfinity, typename DistanceZero > +void dijkstra_shortest_paths_no_color_map_no_init(const Graph& graph, + typename graph_traits< Graph >::vertex_descriptor start_vertex, + PredecessorMap predecessor_map, DistanceMap distance_map, + WeightMap weight_map, VertexIndexMap index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, DistanceZero distance_zero, + DijkstraVisitor visitor) +{ + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename property_traits< DistanceMap >::value_type Distance; + + typedef indirect_cmp< DistanceMap, DistanceCompare > + DistanceIndirectCompare; + DistanceIndirectCompare distance_indirect_compare( + distance_map, distance_compare); + + // Default - use d-ary heap (d = 4) + typedef detail::vertex_property_map_generator< Graph, VertexIndexMap, + std::size_t > + IndexInHeapMapHelper; + typedef typename IndexInHeapMapHelper::type IndexInHeapMap; + typedef d_ary_heap_indirect< Vertex, 4, IndexInHeapMap, DistanceMap, + DistanceCompare > + VertexQueue; + + boost::scoped_array< std::size_t > index_in_heap_map_holder; + IndexInHeapMap index_in_heap = IndexInHeapMapHelper::build( + graph, index_map, index_in_heap_map_holder); + VertexQueue vertex_queue(distance_map, index_in_heap, distance_compare); + + // Add vertex to the queue + vertex_queue.push(start_vertex); + + // Starting vertex will always be the first discovered vertex + visitor.discover_vertex(start_vertex, graph); + + while (!vertex_queue.empty()) + { + Vertex min_vertex = vertex_queue.top(); + vertex_queue.pop(); + + visitor.examine_vertex(min_vertex, graph); + + // Check if any other vertices can be reached + Distance min_vertex_distance = get(distance_map, min_vertex); + + if (!distance_compare(min_vertex_distance, distance_infinity)) + { + // This is the minimum vertex, so all other vertices are unreachable + return; + } + + // Examine neighbors of min_vertex + BGL_FORALL_OUTEDGES_T(min_vertex, current_edge, graph, Graph) + { + visitor.examine_edge(current_edge, graph); + + // Check if the edge has a negative weight + if (distance_compare(get(weight_map, current_edge), distance_zero)) + { + boost::throw_exception(negative_edge()); + } + + // Extract the neighboring vertex and get its distance + Vertex neighbor_vertex = target(current_edge, graph); + Distance neighbor_vertex_distance + = get(distance_map, neighbor_vertex); + bool is_neighbor_undiscovered = !distance_compare( + neighbor_vertex_distance, distance_infinity); + + // Attempt to relax the edge + bool was_edge_relaxed + = relax_target(current_edge, graph, weight_map, predecessor_map, + distance_map, distance_weight_combine, distance_compare); + + if (was_edge_relaxed) + { + visitor.edge_relaxed(current_edge, graph); + if (is_neighbor_undiscovered) + { + visitor.discover_vertex(neighbor_vertex, graph); + vertex_queue.push(neighbor_vertex); + } + else + { + vertex_queue.update(neighbor_vertex); + } + } + else + { + visitor.edge_not_relaxed(current_edge, graph); + } + + } // end out edge iteration + + visitor.finish_vertex(min_vertex, graph); + } // end while queue not empty +} + +// Full init version +template < typename Graph, typename DijkstraVisitor, typename PredecessorMap, + typename DistanceMap, typename WeightMap, typename VertexIndexMap, + typename DistanceCompare, typename DistanceWeightCombine, + typename DistanceInfinity, typename DistanceZero > +void dijkstra_shortest_paths_no_color_map(const Graph& graph, + typename graph_traits< Graph >::vertex_descriptor start_vertex, + PredecessorMap predecessor_map, DistanceMap distance_map, + WeightMap weight_map, VertexIndexMap index_map, + DistanceCompare distance_compare, + DistanceWeightCombine distance_weight_combine, + DistanceInfinity distance_infinity, DistanceZero distance_zero, + DijkstraVisitor visitor) +{ + // Initialize vertices + BGL_FORALL_VERTICES_T(current_vertex, graph, Graph) + { + visitor.initialize_vertex(current_vertex, graph); + + // Default all distances to infinity + put(distance_map, current_vertex, distance_infinity); + + // Default all vertex predecessors to the vertex itself + put(predecessor_map, current_vertex, current_vertex); + } + + // Set distance for start_vertex to zero + put(distance_map, start_vertex, distance_zero); + + // Pass everything on to the no_init version + dijkstra_shortest_paths_no_color_map_no_init(graph, start_vertex, + predecessor_map, distance_map, weight_map, index_map, distance_compare, + distance_weight_combine, distance_infinity, distance_zero, visitor); +} + +namespace detail +{ + + // Handle defaults for PredecessorMap, DistanceCompare, + // DistanceWeightCombine, DistanceInfinity and DistanceZero + template < typename Graph, typename DistanceMap, typename WeightMap, + typename VertexIndexMap, typename Params > + inline void dijkstra_no_color_map_dispatch2(const Graph& graph, + typename graph_traits< Graph >::vertex_descriptor start_vertex, + DistanceMap distance_map, WeightMap weight_map, + VertexIndexMap index_map, const Params& params) + { + // Default for predecessor map + dummy_property_map predecessor_map; + + typedef + typename property_traits< DistanceMap >::value_type DistanceType; + DistanceType inf = choose_param(get_param(params, distance_inf_t()), + (std::numeric_limits< DistanceType >::max)()); + dijkstra_shortest_paths_no_color_map(graph, start_vertex, + choose_param( + get_param(params, vertex_predecessor), predecessor_map), + distance_map, weight_map, index_map, + choose_param(get_param(params, distance_compare_t()), + std::less< DistanceType >()), + choose_param(get_param(params, distance_combine_t()), + std::plus< DistanceType >()), + inf, + choose_param(get_param(params, distance_zero_t()), DistanceType()), + choose_param(get_param(params, graph_visitor), + make_dijkstra_visitor(null_visitor()))); + } + + template < typename Graph, typename DistanceMap, typename WeightMap, + typename IndexMap, typename Params > + inline void dijkstra_no_color_map_dispatch1(const Graph& graph, + typename graph_traits< Graph >::vertex_descriptor start_vertex, + DistanceMap distance_map, WeightMap weight_map, IndexMap index_map, + const Params& params) + { + // Default for distance map + typedef typename property_traits< WeightMap >::value_type DistanceType; + typename std::vector< DistanceType >::size_type vertex_count + = is_default_param(distance_map) ? num_vertices(graph) : 1; + + std::vector< DistanceType > default_distance_map(vertex_count); + + detail::dijkstra_no_color_map_dispatch2(graph, start_vertex, + choose_param(distance_map, + make_iterator_property_map(default_distance_map.begin(), + index_map, default_distance_map[0])), + weight_map, index_map, params); + } +} // namespace detail + +// Named parameter version +template < typename Graph, typename Param, typename Tag, typename Rest > +inline void dijkstra_shortest_paths_no_color_map(const Graph& graph, + typename graph_traits< Graph >::vertex_descriptor start_vertex, + const bgl_named_params< Param, Tag, Rest >& params) +{ + // Default for edge weight and vertex index map is to ask for them + // from the graph. Default for the visitor is null_visitor. + detail::dijkstra_no_color_map_dispatch1(graph, start_vertex, + get_param(params, vertex_distance), + choose_const_pmap(get_param(params, edge_weight), graph, edge_weight), + choose_const_pmap(get_param(params, vertex_index), graph, vertex_index), + params); +} + +} // namespace boost + +#endif // BOOST_GRAPH_DIJKSTRA_NO_COLOR_MAP_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/dimacs.hpp b/contrib/restricted/boost/graph/include/boost/graph/dimacs.hpp new file mode 100644 index 0000000000..d6171d2438 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/dimacs.hpp @@ -0,0 +1,375 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Alex Breuer +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_DIMACS_HPP +#define BOOST_GRAPH_DIMACS_HPP + +#include <string> +#include <sstream> +#include <iostream> +#include <fstream> +#include <iterator> +#include <exception> +#include <vector> +#include <queue> +#include <boost/assert.hpp> +#include <boost/throw_exception.hpp> + +namespace boost +{ +namespace graph +{ + + class BOOST_SYMBOL_VISIBLE dimacs_exception : public std::exception + { + }; + + class dimacs_basic_reader + { + public: + typedef std::size_t vertices_size_type; + typedef std::size_t edges_size_type; + typedef double vertex_weight_type; + typedef double edge_weight_type; + typedef std::pair< vertices_size_type, vertices_size_type > edge_type; + enum incr_mode + { + edge, + edge_weight + }; + + dimacs_basic_reader(std::istream& in, bool want_weights = true) + : inpt(in), seen_edges(0), want_weights(want_weights) + { + while (getline(inpt, buf) && !buf.empty() && buf[0] == 'c') + ; + + if (buf[0] != 'p') + { + boost::throw_exception(dimacs_exception()); + } + + std::stringstream instr(buf); + std::string junk; + + instr >> junk >> junk >> num_vertices >> num_edges; + read_edge_weights.push(-1); + incr(edge_weight); + } + + // for a past the end iterator + dimacs_basic_reader() + : inpt(std::cin) + , num_vertices(0) + , num_edges(0) + , seen_edges(0) + , want_weights(false) + { + } + + edge_type edge_deref() + { + BOOST_ASSERT(!read_edges.empty()); + return read_edges.front(); + } + + inline edge_type* edge_ref() + { + BOOST_ASSERT(!read_edges.empty()); + return &read_edges.front(); + } + + inline edge_weight_type edge_weight_deref() + { + BOOST_ASSERT(!read_edge_weights.empty()); + return read_edge_weights.front(); + } + + inline dimacs_basic_reader incr(incr_mode mode) + { + if (mode == edge) + { + BOOST_ASSERT(!read_edges.empty()); + read_edges.pop(); + } + else if (mode == edge_weight) + { + BOOST_ASSERT(!read_edge_weights.empty()); + read_edge_weights.pop(); + } + + if ((mode == edge && read_edges.empty()) + || (mode == edge_weight && read_edge_weights.empty())) + { + + if (seen_edges > num_edges) + { + boost::throw_exception(dimacs_exception()); + } + + while (getline(inpt, buf) && !buf.empty() && buf[0] == 'c') + ; + + if (!inpt.eof()) + { + int source, dest, weight; + read_edge_line((char*)buf.c_str(), source, dest, weight); + + seen_edges++; + source--; + dest--; + + read_edges.push(edge_type(source, dest)); + if (want_weights) + { + read_edge_weights.push(weight); + } + } + BOOST_ASSERT(read_edges.size() < 100); + BOOST_ASSERT(read_edge_weights.size() < 100); + } + + // the 1000000 just happens to be about how many edges can be read + // in 10s + // if( !(seen_edges % 1000000) && !process_id( pg ) && mode == + // edge ) { + // std::cout << "read " << seen_edges << " edges" << + // std::endl; + // } + return *this; + } + + inline bool done_edges() + { + return inpt.eof() && read_edges.size() == 0; + } + + inline bool done_edge_weights() + { + return inpt.eof() && read_edge_weights.size() == 0; + } + + inline vertices_size_type n_vertices() { return num_vertices; } + + inline vertices_size_type processed_edges() + { + return seen_edges - read_edges.size(); + } + + inline vertices_size_type processed_edge_weights() + { + return seen_edges - read_edge_weights.size(); + } + + inline vertices_size_type n_edges() { return num_edges; } + + protected: + bool read_edge_line(char* linebuf, int& from, int& to, int& weight) + { + char *fs = NULL, *ts = NULL, *ws = NULL; + char* tmp = linebuf + 2; + + fs = tmp; + if ('e' == linebuf[0]) + { + while (*tmp != '\n' && *tmp != '\0') + { + if (*tmp == ' ') + { + *tmp = '\0'; + ts = ++tmp; + break; + } + tmp++; + } + *tmp = '\0'; + if (NULL == fs || NULL == ts) + return false; + from = atoi(fs); + to = atoi(ts); + weight = 0; + } + else if ('a' == linebuf[0]) + { + while (*tmp != '\n' && *tmp != '\0') + { + if (*tmp == ' ') + { + *tmp = '\0'; + ts = ++tmp; + break; + } + tmp++; + } + while (*tmp != '\n' && *tmp != '\0') + { + if (*tmp == ' ') + { + *tmp = '\0'; + ws = ++tmp; + break; + } + tmp++; + } + while (*tmp != '\n' && *tmp != '\0') + tmp++; + *tmp = '\0'; + if (fs == NULL || ts == NULL || ws == NULL) + return false; + from = atoi(fs); + to = atoi(ts); + if (want_weights) + weight = atoi(ws); + else + weight = 0; + } + else + { + return false; + } + + return true; + } + + std::queue< edge_type > read_edges; + std::queue< edge_weight_type > read_edge_weights; + + std::istream& inpt; + std::string buf; + vertices_size_type num_vertices, num_edges, seen_edges; + bool want_weights; + }; + + template < typename T > class dimacs_edge_iterator + { + public: + typedef dimacs_basic_reader::edge_type edge_type; + typedef dimacs_basic_reader::incr_mode incr_mode; + + typedef std::input_iterator_tag iterator_category; + typedef edge_type value_type; + typedef value_type reference; + typedef edge_type* pointer; + typedef std::ptrdiff_t difference_type; + + dimacs_edge_iterator(T& reader) : reader(reader) {} + + inline dimacs_edge_iterator& operator++() + { + reader.incr(dimacs_basic_reader::edge); + return *this; + } + + inline edge_type operator*() { return reader.edge_deref(); } + + inline edge_type* operator->() { return reader.edge_ref(); } + + // don't expect this to do the right thing if you're not comparing + // against a general past-the-end-iterator made with the default + // constructor for dimacs_basic_reader + inline bool operator==(dimacs_edge_iterator arg) + { + if (reader.n_vertices() == 0) + { + return arg.reader.done_edges(); + } + else if (arg.reader.n_vertices() == 0) + { + return reader.done_edges(); + } + else + { + return false; + } + return false; + } + + inline bool operator!=(dimacs_edge_iterator arg) + { + if (reader.n_vertices() == 0) + { + return !arg.reader.done_edges(); + } + else if (arg.reader.n_vertices() == 0) + { + return !reader.done_edges(); + } + else + { + return true; + } + return true; + } + + private: + T& reader; + }; + + template < typename T > class dimacs_edge_weight_iterator + { + public: + typedef dimacs_basic_reader::edge_weight_type edge_weight_type; + typedef dimacs_basic_reader::incr_mode incr_mode; + + dimacs_edge_weight_iterator(T& reader) : reader(reader) {} + + inline dimacs_edge_weight_iterator& operator++() + { + reader.incr(dimacs_basic_reader::edge_weight); + return *this; + } + + inline edge_weight_type operator*() + { + return reader.edge_weight_deref(); + } + + // don't expect this to do the right thing if you're not comparing + // against a general past-the-end-iterator made with the default + // constructor for dimacs_basic_reader + inline bool operator==(dimacs_edge_weight_iterator arg) + { + if (reader.n_vertices() == 0) + { + return arg.reader.done_edge_weights(); + } + else if (arg.reader.n_vertices() == 0) + { + return reader.done_edge_weights(); + } + else + { + return false; + } + return false; + } + + inline bool operator!=(dimacs_edge_weight_iterator arg) + { + if (reader.n_vertices() == 0) + { + return !arg.reader.done_edge_weights(); + } + else if (arg.reader.n_vertices() == 0) + { + return !reader.done_edge_weights(); + } + else + { + return true; + } + return true; + } + + private: + T& reader; + }; + +} +} // end namespace boost::graph +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/directed_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/directed_graph.hpp new file mode 100644 index 0000000000..f40c1beb1b --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/directed_graph.hpp @@ -0,0 +1,795 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_DIRECTED_GRAPH_HPP +#define BOOST_GRAPH_DIRECTED_GRAPH_HPP + +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/properties.hpp> +#include <boost/pending/property.hpp> +#include <boost/property_map/transform_value_property_map.hpp> +#include <boost/type_traits.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ +struct directed_graph_tag +{ +}; + +/** + * The directed_graph class template is a simplified version of the BGL + * adjacency list. This class is provided for ease of use, but may not + * perform as well as custom-defined adjacency list classes. Instances of + * this template model the BidirectionalGraph, VertexIndexGraph, and + * EdgeIndexGraph concepts. The graph is also fully mutable, supporting + * both insertions and removals of vertices and edges. + * + * @note Special care must be taken when removing vertices or edges since + * those operations can invalidate the numbering of vertices. + */ +template < typename VertexProp = no_property, typename EdgeProp = no_property, + typename GraphProp = no_property > +class directed_graph +{ +public: + typedef GraphProp graph_property_type; + typedef VertexProp vertex_property_type; + typedef EdgeProp edge_property_type; + typedef typename lookup_one_property< GraphProp, graph_bundle_t >::type + graph_bundled; + typedef typename lookup_one_property< VertexProp, vertex_bundle_t >::type + vertex_bundled; + typedef typename lookup_one_property< EdgeProp, edge_bundle_t >::type + edge_bundled; + +public: + // Embed indices into the vertex type. + typedef property< vertex_index_t, unsigned, vertex_property_type > + internal_vertex_property; + typedef property< edge_index_t, unsigned, edge_property_type > + internal_edge_property; + +public: + typedef adjacency_list< listS, listS, bidirectionalS, + internal_vertex_property, internal_edge_property, GraphProp, listS > + graph_type; + +private: + // storage selectors + typedef typename graph_type::vertex_list_selector vertex_list_selector; + typedef typename graph_type::edge_list_selector edge_list_selector; + typedef typename graph_type::out_edge_list_selector out_edge_list_selector; + typedef typename graph_type::directed_selector directed_selector; + +public: + // more commonly used graph types + typedef typename graph_type::stored_vertex stored_vertex; + typedef typename graph_type::vertices_size_type vertices_size_type; + typedef typename graph_type::edges_size_type edges_size_type; + typedef typename graph_type::degree_size_type degree_size_type; + typedef typename graph_type::vertex_descriptor vertex_descriptor; + typedef typename graph_type::edge_descriptor edge_descriptor; + + // iterator types + typedef typename graph_type::vertex_iterator vertex_iterator; + typedef typename graph_type::edge_iterator edge_iterator; + typedef typename graph_type::out_edge_iterator out_edge_iterator; + typedef typename graph_type::in_edge_iterator in_edge_iterator; + typedef typename graph_type::adjacency_iterator adjacency_iterator; + + // miscellaneous types + typedef directed_graph_tag graph_tag; + typedef typename graph_type::directed_category directed_category; + typedef typename graph_type::edge_parallel_category edge_parallel_category; + typedef typename graph_type::traversal_category traversal_category; + + typedef std::size_t vertex_index_type; + typedef std::size_t edge_index_type; + + directed_graph(GraphProp const& p = GraphProp()) + : m_graph(p) + , m_num_vertices(0) + , m_num_edges(0) + , m_max_vertex_index(0) + , m_max_edge_index(0) + { + } + + directed_graph(directed_graph const& x) + : m_graph(x.m_graph) + , m_num_vertices(x.m_num_vertices) + , m_num_edges(x.m_num_edges) + , m_max_vertex_index(x.m_max_vertex_index) + , m_max_edge_index(x.m_max_edge_index) + { + } + + directed_graph(vertices_size_type n, GraphProp const& p = GraphProp()) + : m_graph(n, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { + renumber_vertex_indices(); + } + + template < typename EdgeIterator > + directed_graph(EdgeIterator f, EdgeIterator l, vertices_size_type n, + edges_size_type m = 0, GraphProp const& p = GraphProp()) + : m_graph(f, l, n, m, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { + // Unfortunately, we have to renumber the entire graph. + renumber_indices(); + + // Can't always guarantee that the number of edges is actually + // m if distance(f, l) != m (or is undefined). + m_num_edges = m_max_edge_index = boost::num_edges(m_graph); + } + + directed_graph& operator=(directed_graph const& g) + { + if (&g != this) + { + m_graph = g.m_graph; + m_num_vertices = g.m_num_vertices; + m_num_edges = g.m_num_edges; + m_max_vertex_index = g.m_max_vertex_index; + m_max_edge_index = g.m_max_edge_index; + } + return *this; + } + + // The impl_() methods are not part of the public interface. + graph_type& impl() { return m_graph; } + + graph_type const& impl() const { return m_graph; } + + // The following methods are not part of the public interface + vertices_size_type num_vertices() const { return m_num_vertices; } + +private: + // This helper function manages the attribution of vertex indices. + vertex_descriptor make_index(vertex_descriptor v) + { + boost::put(vertex_index, m_graph, v, m_max_vertex_index); + m_num_vertices++; + m_max_vertex_index++; + return v; + } + +public: + vertex_descriptor add_vertex() + { + return make_index(boost::add_vertex(m_graph)); + } + + vertex_descriptor add_vertex(vertex_property_type const& p) + { + return make_index( + boost::add_vertex(internal_vertex_property(0u, p), m_graph)); + } + + void clear_vertex(vertex_descriptor v) + { + m_num_edges -= boost::degree(v, m_graph); + boost::clear_vertex(v, m_graph); + } + + void remove_vertex(vertex_descriptor v) + { + boost::remove_vertex(v, m_graph); + --m_num_vertices; + } + + edges_size_type num_edges() const { return m_num_edges; } + +private: + // A helper function for managing edge index attributes. + std::pair< edge_descriptor, bool > const& make_index( + std::pair< edge_descriptor, bool > const& x) + { + if (x.second) + { + boost::put(edge_index, m_graph, x.first, m_max_edge_index); + ++m_num_edges; + ++m_max_edge_index; + } + return x; + } + +public: + std::pair< edge_descriptor, bool > add_edge( + vertex_descriptor u, vertex_descriptor v) + { + return make_index(boost::add_edge(u, v, m_graph)); + } + + std::pair< edge_descriptor, bool > add_edge( + vertex_descriptor u, vertex_descriptor v, edge_property_type const& p) + { + return make_index( + boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); + } + + void remove_edge(vertex_descriptor u, vertex_descriptor v) + { + // find all edges, (u, v) + std::vector< edge_descriptor > edges; + out_edge_iterator i, i_end; + for (boost::tie(i, i_end) = boost::out_edges(u, m_graph); i != i_end; + ++i) + { + if (boost::target(*i, m_graph) == v) + { + edges.push_back(*i); + } + } + // remove all edges, (u, v) + typename std::vector< edge_descriptor >::iterator j = edges.begin(), + j_end = edges.end(); + for (; j != j_end; ++j) + { + remove_edge(*j); + } + } + + void remove_edge(edge_iterator i) { remove_edge(*i); } + + void remove_edge(edge_descriptor e) + { + boost::remove_edge(e, m_graph); + --m_num_edges; + } + + vertex_index_type max_vertex_index() const { return m_max_vertex_index; } + + void renumber_vertex_indices() + { + vertex_iterator i, end; + boost::tie(i, end) = vertices(m_graph); + m_max_vertex_index = renumber_vertex_indices(i, end, 0); + } + + void remove_vertex_and_renumber_indices(vertex_iterator i) + { + vertex_iterator j = next(i), end = vertices(m_graph).second; + vertex_index_type n = get(vertex_index, m_graph, *i); + + // remove the offending vertex and renumber everything after + remove_vertex(*i); + m_max_vertex_index = renumber_vertex_indices(j, end, n); + } + + edge_index_type max_edge_index() const { return m_max_edge_index; } + + void renumber_edge_indices() + { + edge_iterator i, end; + boost::tie(i, end) = edges(m_graph); + m_max_edge_index = renumber_edge_indices(i, end, 0); + } + + void remove_edge_and_renumber_indices(edge_iterator i) + { + edge_iterator j = next(i), end = edges(m_graph).second; + edge_index_type n = get(edge_index, m_graph, *i); + + // remove the offending edge and renumber everything after + remove_edge(*i); + m_max_edge_index = renumber_edge_indices(j, end, n); + } + + void renumber_indices() + { + renumber_vertex_indices(); + renumber_edge_indices(); + } + + // bundled property support +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + vertex_bundled& operator[](vertex_descriptor v) { return m_graph[v]; } + + vertex_bundled const& operator[](vertex_descriptor v) const + { + return m_graph[v]; + } + + edge_bundled& operator[](edge_descriptor e) { return m_graph[e]; } + + edge_bundled const& operator[](edge_descriptor e) const + { + return m_graph[e]; + } + + graph_bundled& operator[](graph_bundle_t) { return get_property(*this); } + + graph_bundled const& operator[](graph_bundle_t) const + { + return get_property(*this); + } +#endif + + // Graph concepts + static vertex_descriptor null_vertex() { return graph_type::null_vertex(); } + + void clear() + { + m_graph.clear(); + m_num_vertices = m_max_vertex_index = 0; + m_num_edges = m_max_edge_index = 0; + } + + void swap(directed_graph& g) + { + m_graph.swap(g.m_graph); + std::swap(m_num_vertices, g.m_num_vertices); + std::swap(m_max_vertex_index, g.m_max_vertex_index); + std::swap(m_num_edges, g.m_num_edges); + std::swap(m_max_edge_index, g.m_max_edge_index); + } + +private: + vertices_size_type renumber_vertex_indices( + vertex_iterator i, vertex_iterator end, vertices_size_type n) + { + typedef + typename property_map< graph_type, vertex_index_t >::type IndexMap; + IndexMap indices = get(vertex_index, m_graph); + for (; i != end; ++i) + { + indices[*i] = n++; + } + return n; + } + + vertices_size_type renumber_edge_indices( + edge_iterator i, edge_iterator end, vertices_size_type n) + { + typedef + typename property_map< graph_type, edge_index_t >::type IndexMap; + IndexMap indices = get(edge_index, m_graph); + for (; i != end; ++i) + { + indices[*i] = n++; + } + return n; + } + + graph_type m_graph; + vertices_size_type m_num_vertices; + edges_size_type m_num_edges; + vertex_index_type m_max_vertex_index; + edge_index_type m_max_edge_index; +}; + +#define DIRECTED_GRAPH_PARAMS typename VP, typename EP, typename GP +#define DIRECTED_GRAPH directed_graph< VP, EP, GP > + +// IncidenceGraph concepts +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::vertex_descriptor source( + typename DIRECTED_GRAPH::edge_descriptor e, DIRECTED_GRAPH const& g) +{ + return source(e, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::vertex_descriptor target( + typename DIRECTED_GRAPH::edge_descriptor e, DIRECTED_GRAPH const& g) +{ + return target(e, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::degree_size_type out_degree( + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return out_degree(v, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +inline std::pair< typename DIRECTED_GRAPH::out_edge_iterator, + typename DIRECTED_GRAPH::out_edge_iterator > +out_edges(typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return out_edges(v, g.impl()); +} + +// BidirectionalGraph concepts +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::degree_size_type in_degree( + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return in_degree(v, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +inline std::pair< typename DIRECTED_GRAPH::in_edge_iterator, + typename DIRECTED_GRAPH::in_edge_iterator > +in_edges(typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return in_edges(v, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::degree_size_type degree( + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return degree(v, g.impl()); +} + +// AdjacencyGraph concepts +template < DIRECTED_GRAPH_PARAMS > +inline std::pair< typename DIRECTED_GRAPH::adjacency_iterator, + typename DIRECTED_GRAPH::adjacency_iterator > +adjacent_vertices( + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return adjacent_vertices(v, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +typename DIRECTED_GRAPH::vertex_descriptor vertex( + typename DIRECTED_GRAPH::vertices_size_type n, DIRECTED_GRAPH const& g) +{ + return vertex(n, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +std::pair< typename DIRECTED_GRAPH::edge_descriptor, bool > edge( + typename DIRECTED_GRAPH::vertex_descriptor u, + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return edge(u, v, g.impl()); +} + +// VertexListGraph concepts +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::vertices_size_type num_vertices( + DIRECTED_GRAPH const& g) +{ + return g.num_vertices(); +} + +template < DIRECTED_GRAPH_PARAMS > +inline std::pair< typename DIRECTED_GRAPH::vertex_iterator, + typename DIRECTED_GRAPH::vertex_iterator > +vertices(DIRECTED_GRAPH const& g) +{ + return vertices(g.impl()); +} + +// EdgeListGraph concepts +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::edges_size_type num_edges( + DIRECTED_GRAPH const& g) +{ + return g.num_edges(); +} + +template < DIRECTED_GRAPH_PARAMS > +inline std::pair< typename DIRECTED_GRAPH::edge_iterator, + typename DIRECTED_GRAPH::edge_iterator > +edges(DIRECTED_GRAPH const& g) +{ + return edges(g.impl()); +} + +// MutableGraph concepts +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::vertex_descriptor add_vertex(DIRECTED_GRAPH& g) +{ + return g.add_vertex(); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::vertex_descriptor add_vertex( + typename DIRECTED_GRAPH::vertex_property_type const& p, DIRECTED_GRAPH& g) +{ + return g.add_vertex(p); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void clear_vertex( + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH& g) +{ + return g.clear_vertex(v); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void remove_vertex( + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH& g) +{ + return g.remove_vertex(v); +} + +template < DIRECTED_GRAPH_PARAMS > +inline std::pair< typename DIRECTED_GRAPH::edge_descriptor, bool > add_edge( + typename DIRECTED_GRAPH::vertex_descriptor u, + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH& g) +{ + return g.add_edge(u, v); +} + +template < DIRECTED_GRAPH_PARAMS > +inline std::pair< typename DIRECTED_GRAPH::edge_descriptor, bool > add_edge( + typename DIRECTED_GRAPH::vertex_descriptor u, + typename DIRECTED_GRAPH::vertex_descriptor v, + typename DIRECTED_GRAPH::edge_property_type const& p, DIRECTED_GRAPH& g) +{ + return g.add_edge(u, v, p); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void remove_edge(typename DIRECTED_GRAPH::vertex_descriptor u, + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH& g) +{ + return g.remove_edge(u, v); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void remove_edge( + typename DIRECTED_GRAPH::edge_descriptor e, DIRECTED_GRAPH& g) +{ + return g.remove_edge(e); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void remove_edge( + typename DIRECTED_GRAPH::edge_iterator i, DIRECTED_GRAPH& g) +{ + return g.remove_edge(i); +} + +template < DIRECTED_GRAPH_PARAMS, class Predicate > +inline void remove_edge_if(Predicate pred, DIRECTED_GRAPH& g) +{ + return remove_edge_if(pred, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS, class Predicate > +inline void remove_out_edge_if(typename DIRECTED_GRAPH::vertex_descriptor v, + Predicate pred, DIRECTED_GRAPH& g) +{ + return remove_out_edge_if(v, pred, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS, class Predicate > +inline void remove_in_edge_if(typename DIRECTED_GRAPH::vertex_descriptor v, + Predicate pred, DIRECTED_GRAPH& g) +{ + return remove_in_edge_if(v, pred, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS, typename Property > +struct property_map< DIRECTED_GRAPH, Property > +: property_map< typename DIRECTED_GRAPH::graph_type, Property > +{ +}; + +template < DIRECTED_GRAPH_PARAMS > +struct property_map< DIRECTED_GRAPH, vertex_all_t > +{ + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename DIRECTED_GRAPH::graph_type, + vertex_all_t >::const_type > + const_type; + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename DIRECTED_GRAPH::graph_type, + vertex_all_t >::type > + type; +}; + +template < DIRECTED_GRAPH_PARAMS > +struct property_map< DIRECTED_GRAPH, edge_all_t > +{ + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename DIRECTED_GRAPH::graph_type, + edge_all_t >::const_type > + const_type; + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename DIRECTED_GRAPH::graph_type, + edge_all_t >::type > + type; +}; + +// PropertyGraph concepts +template < DIRECTED_GRAPH_PARAMS, typename Property > +inline typename property_map< DIRECTED_GRAPH, Property >::type get( + Property p, DIRECTED_GRAPH& g) +{ + return get(p, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS, typename Property > +inline typename property_map< DIRECTED_GRAPH, Property >::const_type get( + Property p, DIRECTED_GRAPH const& g) +{ + return get(p, g.impl()); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename property_map< DIRECTED_GRAPH, vertex_all_t >::type get( + vertex_all_t, DIRECTED_GRAPH& g) +{ + return typename property_map< DIRECTED_GRAPH, vertex_all_t >::type( + detail::remove_first_property(), get(vertex_all, g.impl())); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename property_map< DIRECTED_GRAPH, vertex_all_t >::const_type get( + vertex_all_t, DIRECTED_GRAPH const& g) +{ + return typename property_map< DIRECTED_GRAPH, vertex_all_t >::const_type( + detail::remove_first_property(), get(vertex_all, g.impl())); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename property_map< DIRECTED_GRAPH, edge_all_t >::type get( + edge_all_t, DIRECTED_GRAPH& g) +{ + return typename property_map< DIRECTED_GRAPH, edge_all_t >::type( + detail::remove_first_property(), get(edge_all, g.impl())); +} + +template < DIRECTED_GRAPH_PARAMS > +inline typename property_map< DIRECTED_GRAPH, edge_all_t >::const_type get( + edge_all_t, DIRECTED_GRAPH const& g) +{ + return typename property_map< DIRECTED_GRAPH, edge_all_t >::const_type( + detail::remove_first_property(), get(edge_all, g.impl())); +} + +template < DIRECTED_GRAPH_PARAMS, typename Property, typename Key > +inline typename property_traits< typename property_map< + typename DIRECTED_GRAPH::graph_type, Property >::const_type >::value_type +get(Property p, DIRECTED_GRAPH const& g, Key const& k) +{ + return get(p, g.impl(), k); +} + +template < DIRECTED_GRAPH_PARAMS, typename Key > +inline typename property_traits< + typename property_map< typename DIRECTED_GRAPH::graph_type, + vertex_all_t >::const_type >::value_type +get(vertex_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ + return get(vertex_all, g.impl(), k).m_base; +} + +template < DIRECTED_GRAPH_PARAMS, typename Key > +inline typename property_traits< typename property_map< + typename DIRECTED_GRAPH::graph_type, edge_all_t >::const_type >::value_type +get(edge_all_t, DIRECTED_GRAPH const& g, Key const& k) +{ + return get(edge_all, g.impl(), k).m_base; +} + +template < DIRECTED_GRAPH_PARAMS, typename Property, typename Key, + typename Value > +inline void put(Property p, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ + put(p, g.impl(), k, v); +} + +template < DIRECTED_GRAPH_PARAMS, typename Key, typename Value > +inline void put(vertex_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ + put(vertex_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property( + get(vertex_index, g.impl(), k), v)); +} + +template < DIRECTED_GRAPH_PARAMS, typename Key, typename Value > +inline void put(edge_all_t, DIRECTED_GRAPH& g, Key const& k, Value const& v) +{ + put(edge_all, g.impl(), k, + typename DIRECTED_GRAPH::internal_vertex_property( + get(edge_index, g.impl(), k), v)); +} + +template < DIRECTED_GRAPH_PARAMS, class Property > +typename graph_property< DIRECTED_GRAPH, Property >::type& get_property( + DIRECTED_GRAPH& g, Property p) +{ + return get_property(g.impl(), p); +} + +template < DIRECTED_GRAPH_PARAMS, class Property > +typename graph_property< DIRECTED_GRAPH, Property >::type const& get_property( + DIRECTED_GRAPH const& g, Property p) +{ + return get_property(g.impl(), p); +} + +template < DIRECTED_GRAPH_PARAMS, class Property, class Value > +void set_property(DIRECTED_GRAPH& g, Property p, Value v) +{ + return set_property(g.impl(), p, v); +} + +// Vertex index management + +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::vertex_index_type get_vertex_index( + typename DIRECTED_GRAPH::vertex_descriptor v, DIRECTED_GRAPH const& g) +{ + return get(vertex_index, g, v); +} + +template < DIRECTED_GRAPH_PARAMS > +typename DIRECTED_GRAPH::vertex_index_type max_vertex_index( + DIRECTED_GRAPH const& g) +{ + return g.max_vertex_index(); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void renumber_vertex_indices(DIRECTED_GRAPH& g) +{ + g.renumber_vertex_indices(); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void remove_vertex_and_renumber_indices( + typename DIRECTED_GRAPH::vertex_iterator i, DIRECTED_GRAPH& g) +{ + g.remove_vertex_and_renumber_indices(i); +} + +// Edge index management +template < DIRECTED_GRAPH_PARAMS > +inline typename DIRECTED_GRAPH::edge_index_type get_edge_index( + typename DIRECTED_GRAPH::edge_descriptor v, DIRECTED_GRAPH const& g) +{ + return get(edge_index, g, v); +} + +template < DIRECTED_GRAPH_PARAMS > +typename DIRECTED_GRAPH::edge_index_type max_edge_index(DIRECTED_GRAPH const& g) +{ + return g.max_edge_index(); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void renumber_edge_indices(DIRECTED_GRAPH& g) +{ + g.renumber_edge_indices(); +} + +template < DIRECTED_GRAPH_PARAMS > +inline void remove_edge_and_renumber_indices( + typename DIRECTED_GRAPH::edge_iterator i, DIRECTED_GRAPH& g) +{ + g.remove_edge_and_renumber_indices(i); +} + +// Index management +template < DIRECTED_GRAPH_PARAMS > +inline void renumber_indices(DIRECTED_GRAPH& g) +{ + g.renumber_indices(); +} + +// Mutability Traits +template < DIRECTED_GRAPH_PARAMS > +struct graph_mutability_traits< DIRECTED_GRAPH > +{ + typedef mutable_property_graph_tag category; +}; + +#undef DIRECTED_GRAPH_PARAMS +#undef DIRECTED_GRAPH + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/dominator_tree.hpp b/contrib/restricted/boost/graph/include/boost/graph/dominator_tree.hpp new file mode 100644 index 0000000000..df9783b0b3 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/dominator_tree.hpp @@ -0,0 +1,483 @@ +//======================================================================= +// Copyright (C) 2005-2009 Jongsoo Park <jongsoo.park -at- gmail.com> +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_DOMINATOR_HPP +#define BOOST_GRAPH_DOMINATOR_HPP + +#include <boost/config.hpp> +#include <deque> +#include <set> +#include <boost/graph/depth_first_search.hpp> +#include <boost/concept/assert.hpp> + +// Dominator tree computation + +namespace boost +{ +namespace detail +{ + /** + * An extended time_stamper which also records vertices for each dfs number + */ + template < class TimeMap, class VertexVector, class TimeT, class Tag > + class time_stamper_with_vertex_vector + : public base_visitor< + time_stamper_with_vertex_vector< TimeMap, VertexVector, TimeT, Tag > > + { + public: + typedef Tag event_filter; + time_stamper_with_vertex_vector( + TimeMap timeMap, VertexVector& v, TimeT& t) + : timeStamper_(timeMap, t), v_(v) + { + } + + template < class Graph > + void operator()(const typename property_traits< TimeMap >::key_type& v, + const Graph& g) + { + timeStamper_(v, g); + v_[timeStamper_.m_time] = v; + } + + private: + time_stamper< TimeMap, TimeT, Tag > timeStamper_; + VertexVector& v_; + }; + + /** + * A convenient way to create a time_stamper_with_vertex_vector + */ + template < class TimeMap, class VertexVector, class TimeT, class Tag > + time_stamper_with_vertex_vector< TimeMap, VertexVector, TimeT, Tag > + stamp_times_with_vertex_vector( + TimeMap timeMap, VertexVector& v, TimeT& t, Tag) + { + return time_stamper_with_vertex_vector< TimeMap, VertexVector, TimeT, + Tag >(timeMap, v, t); + } + + template < class Graph, class IndexMap, class TimeMap, class PredMap, + class DomTreePredMap > + class dominator_visitor + { + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef + typename graph_traits< Graph >::vertices_size_type VerticesSizeType; + + public: + /** + * @param g [in] the target graph of the dominator tree + * @param entry [in] the entry node of g + * @param indexMap [in] the vertex index map for g + * @param domTreePredMap [out] the immediate dominator map + * (parent map in dominator tree) + */ + dominator_visitor(const Graph& g, const Vertex& entry, + const IndexMap& indexMap, DomTreePredMap domTreePredMap) + : semi_(num_vertices(g)) + , ancestor_(num_vertices(g), graph_traits< Graph >::null_vertex()) + , samedom_(ancestor_) + , best_(semi_) + , semiMap_(make_iterator_property_map(semi_.begin(), indexMap)) + , ancestorMap_(make_iterator_property_map(ancestor_.begin(), indexMap)) + , bestMap_(make_iterator_property_map(best_.begin(), indexMap)) + , buckets_(num_vertices(g)) + , bucketMap_(make_iterator_property_map(buckets_.begin(), indexMap)) + , entry_(entry) + , domTreePredMap_(domTreePredMap) + , numOfVertices_(num_vertices(g)) + , samedomMap(make_iterator_property_map(samedom_.begin(), indexMap)) + { + } + + void operator()(const Vertex& n, const TimeMap& dfnumMap, + const PredMap& parentMap, const Graph& g) + { + if (n == entry_) + return; + + const Vertex p(get(parentMap, n)); + Vertex s(p); + + // 1. Calculate the semidominator of n, + // based on the semidominator thm. + // * Semidominator thm. : To find the semidominator of a node n, + // consider all predecessors v of n in the CFG (Control Flow + // Graph). + // - If v is a proper ancestor of n in the spanning tree + // (so dfnum(v) < dfnum(n)), then v is a candidate for semi(n) + // - If v is a non-ancestor of n (so dfnum(v) > dfnum(n)) + // then for each u that is an ancestor of v (or u = v), + // Let semi(u) be a candidate for semi(n) + // of all these candidates, the one with lowest dfnum is + // the semidominator of n. + + // For each predecessor of n + typename graph_traits< Graph >::in_edge_iterator inItr, inEnd; + for (boost::tie(inItr, inEnd) = in_edges(n, g); inItr != inEnd; + ++inItr) + { + const Vertex v = source(*inItr, g); + // To deal with unreachable nodes + if (get(dfnumMap, v) < 0 || get(dfnumMap, v) >= numOfVertices_) + continue; + + Vertex s2; + if (get(dfnumMap, v) <= get(dfnumMap, n)) + s2 = v; + else + s2 = get(semiMap_, ancestor_with_lowest_semi_(v, dfnumMap)); + + if (get(dfnumMap, s2) < get(dfnumMap, s)) + s = s2; + } + put(semiMap_, n, s); + + // 2. Calculation of n's dominator is deferred until + // the path from s to n has been linked into the forest + get(bucketMap_, s).push_back(n); + get(ancestorMap_, n) = p; + get(bestMap_, n) = n; + + // 3. Now that the path from p to v has been linked into + // the spanning forest, these lines calculate the dominator of v, + // based on the dominator thm., or else defer the calculation + // until y's dominator is known + // * Dominator thm. : On the spanning-tree path below semi(n) and + // above or including n, let y be the node + // with the smallest-numbered semidominator. Then, + // + // idom(n) = semi(n) if semi(y)=semi(n) or + // idom(y) if semi(y) != semi(n) + typename std::deque< Vertex >::iterator buckItr; + for (buckItr = get(bucketMap_, p).begin(); + buckItr != get(bucketMap_, p).end(); ++buckItr) + { + const Vertex v(*buckItr); + const Vertex y(ancestor_with_lowest_semi_(v, dfnumMap)); + if (get(semiMap_, y) == get(semiMap_, v)) + put(domTreePredMap_, v, p); + else + put(samedomMap, v, y); + } + + get(bucketMap_, p).clear(); + } + + protected: + /** + * Evaluate function in Tarjan's path compression + */ + const Vertex ancestor_with_lowest_semi_( + const Vertex& v, const TimeMap& dfnumMap) + { + const Vertex a(get(ancestorMap_, v)); + + if (get(ancestorMap_, a) != graph_traits< Graph >::null_vertex()) + { + const Vertex b(ancestor_with_lowest_semi_(a, dfnumMap)); + + put(ancestorMap_, v, get(ancestorMap_, a)); + + if (get(dfnumMap, get(semiMap_, b)) + < get(dfnumMap, get(semiMap_, get(bestMap_, v)))) + put(bestMap_, v, b); + } + + return get(bestMap_, v); + } + + std::vector< Vertex > semi_, ancestor_, samedom_, best_; + PredMap semiMap_, ancestorMap_, bestMap_; + std::vector< std::deque< Vertex > > buckets_; + + iterator_property_map< + typename std::vector< std::deque< Vertex > >::iterator, IndexMap > + bucketMap_; + + const Vertex& entry_; + DomTreePredMap domTreePredMap_; + const VerticesSizeType numOfVertices_; + + public: + PredMap samedomMap; + }; + +} // namespace detail + +/** + * @brief Build dominator tree using Lengauer-Tarjan algorithm. + * It takes O((V+E)log(V+E)) time. + * + * @pre dfnumMap, parentMap and verticesByDFNum have dfs results corresponding + * indexMap. + * If dfs has already run before, + * this function would be good for saving computations. + * @pre Unreachable nodes must be masked as + * graph_traits<Graph>::null_vertex in parentMap. + * @pre Unreachable nodes must be masked as + * (std::numeric_limits<VerticesSizeType>::max)() in dfnumMap. + * + * @param domTreePredMap [out] : immediate dominator map (parent map + * in dom. tree) + * + * @note reference Appel. p. 452~453. algorithm 19.9, 19.10. + * + * @todo : Optimization in Finding Dominators in Practice, Loukas Georgiadis + */ +template < class Graph, class IndexMap, class TimeMap, class PredMap, + class VertexVector, class DomTreePredMap > +void lengauer_tarjan_dominator_tree_without_dfs(const Graph& g, + const typename graph_traits< Graph >::vertex_descriptor& entry, + const IndexMap& indexMap, TimeMap dfnumMap, PredMap parentMap, + VertexVector& verticesByDFNum, DomTreePredMap domTreePredMap) +{ + // Typedefs and concept check + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertices_size_type VerticesSizeType; + + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< Graph >)); + + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) + return; + + // 1. Visit each vertex in reverse post order and calculate sdom. + detail::dominator_visitor< Graph, IndexMap, TimeMap, PredMap, + DomTreePredMap > + visitor(g, entry, indexMap, domTreePredMap); + + VerticesSizeType i; + for (i = 0; i < numOfVertices; ++i) + { + const Vertex u(verticesByDFNum[numOfVertices - 1 - i]); + if (u != graph_traits< Graph >::null_vertex()) + visitor(u, dfnumMap, parentMap, g); + } + + // 2. Now all the deferred dominator calculations, + // based on the second clause of the dominator thm., are performed + for (i = 0; i < numOfVertices; ++i) + { + const Vertex n(verticesByDFNum[i]); + + if (n == entry || n == graph_traits< Graph >::null_vertex()) + continue; + + Vertex u = get(visitor.samedomMap, n); + if (u != graph_traits< Graph >::null_vertex()) + { + put(domTreePredMap, n, get(domTreePredMap, u)); + } + } +} + +/** + * Unlike lengauer_tarjan_dominator_tree_without_dfs, + * dfs is run in this function and + * the result is written to dfnumMap, parentMap, vertices. + * + * If the result of dfs required after this algorithm, + * this function can eliminate the need of rerunning dfs. + */ +template < class Graph, class IndexMap, class TimeMap, class PredMap, + class VertexVector, class DomTreePredMap > +void lengauer_tarjan_dominator_tree(const Graph& g, + const typename graph_traits< Graph >::vertex_descriptor& entry, + const IndexMap& indexMap, TimeMap dfnumMap, PredMap parentMap, + VertexVector& verticesByDFNum, DomTreePredMap domTreePredMap) +{ + // Typedefs and concept check + typedef typename graph_traits< Graph >::vertices_size_type VerticesSizeType; + + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< Graph >)); + + // 1. Depth first visit + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) + return; + + VerticesSizeType time = (std::numeric_limits< VerticesSizeType >::max)(); + std::vector< default_color_type > colors( + numOfVertices, color_traits< default_color_type >::white()); + depth_first_visit(g, entry, + make_dfs_visitor( + make_pair(record_predecessors(parentMap, on_tree_edge()), + detail::stamp_times_with_vertex_vector( + dfnumMap, verticesByDFNum, time, on_discover_vertex()))), + make_iterator_property_map(colors.begin(), indexMap)); + + // 2. Run main algorithm. + lengauer_tarjan_dominator_tree_without_dfs(g, entry, indexMap, dfnumMap, + parentMap, verticesByDFNum, domTreePredMap); +} + +/** + * Use vertex_index as IndexMap and make dfnumMap, parentMap, verticesByDFNum + * internally. + * If we don't need the result of dfs (dfnumMap, parentMap, verticesByDFNum), + * this function would be more convenient one. + */ +template < class Graph, class DomTreePredMap > +void lengauer_tarjan_dominator_tree(const Graph& g, + const typename graph_traits< Graph >::vertex_descriptor& entry, + DomTreePredMap domTreePredMap) +{ + // typedefs + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertices_size_type VerticesSizeType; + typedef typename property_map< Graph, vertex_index_t >::const_type IndexMap; + typedef iterator_property_map< + typename std::vector< VerticesSizeType >::iterator, IndexMap > + TimeMap; + typedef iterator_property_map< typename std::vector< Vertex >::iterator, + IndexMap > + PredMap; + + // Make property maps + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) + return; + + const IndexMap indexMap = get(vertex_index, g); + + std::vector< VerticesSizeType > dfnum(numOfVertices, 0); + TimeMap dfnumMap(make_iterator_property_map(dfnum.begin(), indexMap)); + + std::vector< Vertex > parent( + numOfVertices, graph_traits< Graph >::null_vertex()); + PredMap parentMap(make_iterator_property_map(parent.begin(), indexMap)); + + std::vector< Vertex > verticesByDFNum(parent); + + // Run main algorithm + lengauer_tarjan_dominator_tree(g, entry, indexMap, dfnumMap, parentMap, + verticesByDFNum, domTreePredMap); +} + +/** + * Muchnick. p. 182, 184 + * + * using iterative bit vector analysis + */ +template < class Graph, class IndexMap, class DomTreePredMap > +void iterative_bit_vector_dominator_tree(const Graph& g, + const typename graph_traits< Graph >::vertex_descriptor& entry, + const IndexMap& indexMap, DomTreePredMap domTreePredMap) +{ + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator vertexItr; + typedef typename graph_traits< Graph >::vertices_size_type VerticesSizeType; + typedef iterator_property_map< + typename std::vector< std::set< Vertex > >::iterator, IndexMap > + vertexSetMap; + + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< Graph >)); + + // 1. Finding dominator + // 1.1. Initialize + const VerticesSizeType numOfVertices = num_vertices(g); + if (numOfVertices == 0) + return; + + vertexItr vi, viend; + boost::tie(vi, viend) = vertices(g); + const std::set< Vertex > N(vi, viend); + + bool change = true; + + std::vector< std::set< Vertex > > dom(numOfVertices, N); + vertexSetMap domMap(make_iterator_property_map(dom.begin(), indexMap)); + get(domMap, entry).clear(); + get(domMap, entry).insert(entry); + + while (change) + { + change = false; + for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi) + { + if (*vi == entry) + continue; + + std::set< Vertex > T(N); + + typename graph_traits< Graph >::in_edge_iterator inItr, inEnd; + for (boost::tie(inItr, inEnd) = in_edges(*vi, g); inItr != inEnd; + ++inItr) + { + const Vertex p = source(*inItr, g); + + std::set< Vertex > tempSet; + std::set_intersection(T.begin(), T.end(), + get(domMap, p).begin(), get(domMap, p).end(), + std::inserter(tempSet, tempSet.begin())); + T.swap(tempSet); + } + + T.insert(*vi); + if (T != get(domMap, *vi)) + { + change = true; + get(domMap, *vi).swap(T); + } + } // end of for (boost::tie(vi, viend) = vertices(g) + } // end of while(change) + + // 2. Build dominator tree + for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi) + get(domMap, *vi).erase(*vi); + + Graph domTree(numOfVertices); + + for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi) + { + if (*vi == entry) + continue; + + // We have to iterate through copied dominator set + const std::set< Vertex > tempSet(get(domMap, *vi)); + typename std::set< Vertex >::const_iterator s; + for (s = tempSet.begin(); s != tempSet.end(); ++s) + { + typename std::set< Vertex >::iterator t; + for (t = get(domMap, *vi).begin(); t != get(domMap, *vi).end();) + { + typename std::set< Vertex >::iterator old_t = t; + ++t; // Done early because t may become invalid + if (*old_t == *s) + continue; + if (get(domMap, *s).find(*old_t) != get(domMap, *s).end()) + get(domMap, *vi).erase(old_t); + } + } + } + + for (boost::tie(vi, viend) = vertices(g); vi != viend; ++vi) + { + if (*vi != entry && get(domMap, *vi).size() == 1) + { + Vertex temp = *get(domMap, *vi).begin(); + put(domTreePredMap, *vi, temp); + } + } +} + +template < class Graph, class DomTreePredMap > +void iterative_bit_vector_dominator_tree(const Graph& g, + const typename graph_traits< Graph >::vertex_descriptor& entry, + DomTreePredMap domTreePredMap) +{ + typename property_map< Graph, vertex_index_t >::const_type indexMap + = get(vertex_index, g); + + iterative_bit_vector_dominator_tree(g, entry, indexMap, domTreePredMap); +} +} // namespace boost + +#endif // BOOST_GRAPH_DOMINATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/eccentricity.hpp b/contrib/restricted/boost/graph/include/boost/graph/eccentricity.hpp new file mode 100644 index 0000000000..26480ced0e --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/eccentricity.hpp @@ -0,0 +1,121 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_ECCENTRICITY_HPP +#define BOOST_GRAPH_ECCENTRICITY_HPP + +#include <boost/next_prior.hpp> +#include <boost/config.hpp> +#include <boost/graph/detail/geodesic.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ +template < typename Graph, typename DistanceMap, typename Combinator > +inline typename property_traits< DistanceMap >::value_type eccentricity( + const Graph& g, DistanceMap dist, Combinator combine) +{ + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< DistanceMap, Vertex >)); + typedef typename property_traits< DistanceMap >::value_type Distance; + + return detail::combine_distances(g, dist, combine, Distance(0)); +} + +template < typename Graph, typename DistanceMap > +inline typename property_traits< DistanceMap >::value_type eccentricity( + const Graph& g, DistanceMap dist) +{ + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< DistanceMap, Vertex >)); + typedef typename property_traits< DistanceMap >::value_type Distance; + + return eccentricity(g, dist, detail::maximize< Distance >()); +} + +template < typename Graph, typename DistanceMatrix, typename EccentricityMap > +inline std::pair< typename property_traits< EccentricityMap >::value_type, + typename property_traits< EccentricityMap >::value_type > +all_eccentricities( + const Graph& g, const DistanceMatrix& dist, EccentricityMap ecc) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< DistanceMatrix, Vertex >)); + typedef typename property_traits< DistanceMatrix >::value_type DistanceMap; + BOOST_CONCEPT_ASSERT( + (WritablePropertyMapConcept< EccentricityMap, Vertex >)); + typedef + typename property_traits< EccentricityMap >::value_type Eccentricity; + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + + Eccentricity r = numeric_values< Eccentricity >::infinity(), + d = numeric_values< Eccentricity >::zero(); + VertexIterator i, end; + boost::tie(i, end) = vertices(g); + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + DistanceMap dm = get(dist, *i); + Eccentricity e = eccentricity(g, dm); + put(ecc, *i, e); + + // track the radius and diameter at the same time + r = min BOOST_PREVENT_MACRO_SUBSTITUTION(r, e); + d = max BOOST_PREVENT_MACRO_SUBSTITUTION(d, e); + } + return std::make_pair(r, d); +} + +template < typename Graph, typename EccentricityMap > +inline std::pair< typename property_traits< EccentricityMap >::value_type, + typename property_traits< EccentricityMap >::value_type > +radius_and_diameter(const Graph& g, EccentricityMap ecc) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< EccentricityMap, Vertex >)); + typedef + typename property_traits< EccentricityMap >::value_type Eccentricity; + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + + VertexIterator i, end; + boost::tie(i, end) = vertices(g); + Eccentricity radius = get(ecc, *i); + Eccentricity diameter = get(ecc, *i); + for (i = boost::next(i); i != end; ++i) + { + Eccentricity cur = get(ecc, *i); + radius = min BOOST_PREVENT_MACRO_SUBSTITUTION(radius, cur); + diameter = max BOOST_PREVENT_MACRO_SUBSTITUTION(diameter, cur); + } + return std::make_pair(radius, diameter); +} + +template < typename Graph, typename EccentricityMap > +inline typename property_traits< EccentricityMap >::value_type radius( + const Graph& g, EccentricityMap ecc) +{ + return radius_and_diameter(g, ecc).first; +} + +template < typename Graph, typename EccentricityMap > +inline typename property_traits< EccentricityMap >::value_type diameter( + const Graph& g, EccentricityMap ecc) +{ + return radius_and_diameter(g, ecc).second; +} + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/edge_coloring.hpp b/contrib/restricted/boost/graph/include/boost/graph/edge_coloring.hpp new file mode 100644 index 0000000000..9de277658e --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/edge_coloring.hpp @@ -0,0 +1,201 @@ +//======================================================================= +// Copyright 2013 Maciej Piechotka +// Authors: Maciej Piechotka +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_EDGE_COLORING_HPP +#define BOOST_GRAPH_EDGE_COLORING_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/properties.hpp> +#include <algorithm> +#include <limits> +#include <vector> + +/* This algorithm is to find coloring of an edges + + Reference: + + Misra, J., & Gries, D. (1992). A constructive proof of Vizing's + theorem. In Information Processing Letters. +*/ + +namespace boost +{ +namespace detail +{ + template < typename Graph, typename ColorMap > + bool is_free(const Graph& g, ColorMap color, + typename boost::graph_traits< Graph >::vertex_descriptor u, + typename boost::property_traits< ColorMap >::value_type free_color) + { + typedef typename boost::property_traits< ColorMap >::value_type color_t; + if (free_color == (std::numeric_limits< color_t >::max)()) + return false; + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) + { + if (get(color, e) == free_color) + { + return false; + } + } + return true; + } + + template < typename Graph, typename ColorMap > + std::vector< typename boost::graph_traits< Graph >::vertex_descriptor > + maximal_fan(const Graph& g, ColorMap color, + typename boost::graph_traits< Graph >::vertex_descriptor x, + typename boost::graph_traits< Graph >::vertex_descriptor y) + { + typedef + typename boost::graph_traits< Graph >::vertex_descriptor vertex_t; + std::vector< vertex_t > fan; + fan.push_back(y); + bool extended; + do + { + extended = false; + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) + { + vertex_t v = target(e, g); + if (is_free(g, color, fan.back(), get(color, e)) + && std::find(fan.begin(), fan.end(), v) == fan.end()) + { + fan.push_back(v); + extended = true; + } + } + } while (extended); + return fan; + } + template < typename Graph, typename ColorMap > + typename boost::property_traits< ColorMap >::value_type find_free_color( + const Graph& g, ColorMap color, + typename boost::graph_traits< Graph >::vertex_descriptor u) + { + typename boost::property_traits< ColorMap >::value_type c = 0; + while (!is_free(g, color, u, c)) + c++; + return c; + } + + template < typename Graph, typename ColorMap > + void invert_cd_path(const Graph& g, ColorMap color, + typename boost::graph_traits< Graph >::vertex_descriptor x, + typename boost::graph_traits< Graph >::edge_descriptor eold, + typename boost::property_traits< ColorMap >::value_type c, + typename boost::property_traits< ColorMap >::value_type d) + { + put(color, eold, d); + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) + { + if (get(color, e) == d && e != eold) + { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template < typename Graph, typename ColorMap > + void invert_cd_path(const Graph& g, ColorMap color, + typename boost::graph_traits< Graph >::vertex_descriptor x, + typename boost::property_traits< ColorMap >::value_type c, + typename boost::property_traits< ColorMap >::value_type d) + { + BGL_FORALL_OUTEDGES_T(x, e, g, Graph) + { + if (get(color, e) == d) + { + invert_cd_path(g, color, target(e, g), e, d, c); + return; + } + } + } + + template < typename Graph, typename ColorMap, typename ForwardIterator > + void rotate_fan(const Graph& g, ColorMap color, + typename boost::graph_traits< Graph >::vertex_descriptor x, + ForwardIterator begin, ForwardIterator end) + { + typedef typename boost::graph_traits< Graph >::edge_descriptor edge_t; + if (begin == end) + { + return; + } + edge_t previous = edge(x, *begin, g).first; + for (begin++; begin != end; begin++) + { + edge_t current = edge(x, *begin, g).first; + put(color, previous, get(color, current)); + previous = current; + } + } + + template < typename Graph, typename ColorMap > class find_free_in_fan + { + public: + find_free_in_fan(const Graph& graph, const ColorMap color, + typename boost::property_traits< ColorMap >::value_type d) + : graph(graph), color(color), d(d) + { + } + bool operator()( + const typename boost::graph_traits< Graph >::vertex_descriptor u) + const + { + return is_free(graph, color, u, d); + } + + private: + const Graph& graph; + const ColorMap color; + const typename boost::property_traits< ColorMap >::value_type d; + }; +} + +template < typename Graph, typename ColorMap > +typename boost::property_traits< ColorMap >::value_type color_edge( + const Graph& g, ColorMap color, + typename boost::graph_traits< Graph >::edge_descriptor e) +{ + typedef typename boost::graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename boost::property_traits< ColorMap >::value_type color_t; + typedef typename std::vector< vertex_t >::iterator fan_iterator; + using namespace detail; + vertex_t x = source(e, g), y = target(e, g); + std::vector< vertex_t > fan = maximal_fan(g, color, x, y); + color_t c = find_free_color(g, color, x); + color_t d = find_free_color(g, color, fan.back()); + invert_cd_path(g, color, x, c, d); + fan_iterator w = std::find_if(fan.begin(), fan.end(), + find_free_in_fan< Graph, ColorMap >(g, color, d)); + rotate_fan(g, color, x, fan.begin(), w + 1); + put(color, edge(x, *w, g).first, d); + return (std::max)(c, d); +} + +template < typename Graph, typename ColorMap > +typename boost::property_traits< ColorMap >::value_type edge_coloring( + const Graph& g, ColorMap color) +{ + typedef typename boost::property_traits< ColorMap >::value_type color_t; + BGL_FORALL_EDGES_T(e, g, Graph) + { + put(color, e, (std::numeric_limits< color_t >::max)()); + } + color_t colors = 0; + BGL_FORALL_EDGES_T(e, g, Graph) + { + colors = (std::max)(colors, color_edge(g, color, e) + 1); + } + return colors; +} +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/edge_connectivity.hpp b/contrib/restricted/boost/graph/include/boost/graph/edge_connectivity.hpp new file mode 100644 index 0000000000..25e7d85a52 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/edge_connectivity.hpp @@ -0,0 +1,188 @@ +//======================================================================= +// Copyright 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_EDGE_CONNECTIVITY +#define BOOST_EDGE_CONNECTIVITY + +// WARNING: not-yet fully tested! + +#include <boost/config.hpp> +#include <vector> +#include <set> +#include <algorithm> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/edmonds_karp_max_flow.hpp> + +namespace boost +{ + +namespace detail +{ + + template < class Graph > + inline std::pair< typename graph_traits< Graph >::vertex_descriptor, + typename graph_traits< Graph >::degree_size_type > + min_degree_vertex(Graph& g) + { + typedef graph_traits< Graph > Traits; + typename Traits::vertex_descriptor p; + typedef typename Traits::degree_size_type size_type; + size_type delta = (std::numeric_limits< size_type >::max)(); + + typename Traits::vertex_iterator i, iend; + for (boost::tie(i, iend) = vertices(g); i != iend; ++i) + if (degree(*i, g) < delta) + { + delta = degree(*i, g); + p = *i; + } + return std::make_pair(p, delta); + } + + template < class Graph, class OutputIterator > + void neighbors(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor u, + OutputIterator result) + { + typename graph_traits< Graph >::adjacency_iterator ai, aend; + for (boost::tie(ai, aend) = adjacent_vertices(u, g); ai != aend; ++ai) + *result++ = *ai; + } + + template < class Graph, class VertexIterator, class OutputIterator > + void neighbors(const Graph& g, VertexIterator first, VertexIterator last, + OutputIterator result) + { + for (; first != last; ++first) + neighbors(g, *first, result); + } + +} // namespace detail + +// O(m n) +template < class VertexListGraph, class OutputIterator > +typename graph_traits< VertexListGraph >::degree_size_type edge_connectivity( + VertexListGraph& g, OutputIterator disconnecting_set) +{ + //------------------------------------------------------------------------- + // Type Definitions + typedef graph_traits< VertexListGraph > Traits; + typedef typename Traits::vertex_iterator vertex_iterator; + typedef typename Traits::edge_iterator edge_iterator; + typedef typename Traits::out_edge_iterator out_edge_iterator; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::degree_size_type degree_size_type; + typedef color_traits< default_color_type > Color; + + typedef adjacency_list_traits< vecS, vecS, directedS > Tr; + typedef typename Tr::edge_descriptor Tr_edge_desc; + typedef adjacency_list< vecS, vecS, directedS, no_property, + property< edge_capacity_t, degree_size_type, + property< edge_residual_capacity_t, degree_size_type, + property< edge_reverse_t, Tr_edge_desc > > > > + FlowGraph; + typedef typename graph_traits< FlowGraph >::edge_descriptor edge_descriptor; + + //------------------------------------------------------------------------- + // Variable Declarations + vertex_descriptor u, v, p, k; + edge_descriptor e1, e2; + bool inserted; + vertex_iterator vi, vi_end; + edge_iterator ei, ei_end; + degree_size_type delta, alpha_star, alpha_S_k; + std::set< vertex_descriptor > S, neighbor_S; + std::vector< vertex_descriptor > S_star, non_neighbor_S; + std::vector< default_color_type > color(num_vertices(g)); + std::vector< edge_descriptor > pred(num_vertices(g)); + + //------------------------------------------------------------------------- + // Create a network flow graph out of the undirected graph + FlowGraph flow_g(num_vertices(g)); + + typename property_map< FlowGraph, edge_capacity_t >::type cap + = get(edge_capacity, flow_g); + typename property_map< FlowGraph, edge_residual_capacity_t >::type res_cap + = get(edge_residual_capacity, flow_g); + typename property_map< FlowGraph, edge_reverse_t >::type rev_edge + = get(edge_reverse, flow_g); + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + u = source(*ei, g), v = target(*ei, g); + boost::tie(e1, inserted) = add_edge(u, v, flow_g); + cap[e1] = 1; + boost::tie(e2, inserted) = add_edge(v, u, flow_g); + cap[e2] = 1; // not sure about this + rev_edge[e1] = e2; + rev_edge[e2] = e1; + } + + //------------------------------------------------------------------------- + // The Algorithm + + boost::tie(p, delta) = detail::min_degree_vertex(g); + S_star.push_back(p); + alpha_star = delta; + S.insert(p); + neighbor_S.insert(p); + detail::neighbors( + g, S.begin(), S.end(), std::inserter(neighbor_S, neighbor_S.begin())); + + boost::tie(vi, vi_end) = vertices(g); + std::set_difference(vi, vi_end, neighbor_S.begin(), neighbor_S.end(), + std::back_inserter(non_neighbor_S)); + + while (!non_neighbor_S.empty()) + { // at most n - 1 times + k = non_neighbor_S.front(); + + alpha_S_k = edmonds_karp_max_flow( + flow_g, p, k, cap, res_cap, rev_edge, &color[0], &pred[0]); + + if (alpha_S_k < alpha_star) + { + alpha_star = alpha_S_k; + S_star.clear(); + for (boost::tie(vi, vi_end) = vertices(flow_g); vi != vi_end; ++vi) + if (color[*vi] != Color::white()) + S_star.push_back(*vi); + } + S.insert(k); + neighbor_S.insert(k); + detail::neighbors(g, k, std::inserter(neighbor_S, neighbor_S.begin())); + non_neighbor_S.clear(); + boost::tie(vi, vi_end) = vertices(g); + std::set_difference(vi, vi_end, neighbor_S.begin(), neighbor_S.end(), + std::back_inserter(non_neighbor_S)); + } + //------------------------------------------------------------------------- + // Compute edges of the cut [S*, ~S*] + std::vector< bool > in_S_star(num_vertices(g), false); + typename std::vector< vertex_descriptor >::iterator si; + for (si = S_star.begin(); si != S_star.end(); ++si) + in_S_star[*si] = true; + + degree_size_type c = 0; + for (si = S_star.begin(); si != S_star.end(); ++si) + { + out_edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(*si, g); ei != ei_end; ++ei) + if (!in_S_star[target(*ei, g)]) + { + *disconnecting_set++ = *ei; + ++c; + } + } + return c; +} + +} // namespace boost + +#endif // BOOST_EDGE_CONNECTIVITY diff --git a/contrib/restricted/boost/graph/include/boost/graph/edge_list.hpp b/contrib/restricted/boost/graph/include/boost/graph/edge_list.hpp new file mode 100644 index 0000000000..77c0c01ea4 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/edge_list.hpp @@ -0,0 +1,330 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_EDGE_LIST_HPP +#define BOOST_GRAPH_EDGE_LIST_HPP + +#include <iterator> +#include <boost/config.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/range/irange.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> + +namespace boost +{ + +// +// The edge_list class is an EdgeListGraph module that is constructed +// from a pair of iterators whose value type is a pair of vertex +// descriptors. +// +// For example: +// +// typedef std::pair<int,int> E; +// list<E> elist; +// ... +// typedef edge_list<list<E>::iterator> Graph; +// Graph g(elist.begin(), elist.end()); +// +// If the iterators are random access, then Graph::edge_descriptor +// is of Integral type, otherwise it is a struct, though it is +// convertible to an Integral type. +// + +struct edge_list_tag +{ +}; + +// The implementation class for edge_list. +template < class G, class EdgeIter, class T, class D > class edge_list_impl +{ +public: + typedef D edge_id; + typedef T Vpair; + typedef typename Vpair::first_type V; + typedef V vertex_descriptor; + typedef edge_list_tag graph_tag; + typedef void edge_property_type; + + struct edge_descriptor + { + edge_descriptor() {} + edge_descriptor(EdgeIter p, edge_id id) : _ptr(p), _id(id) {} + operator edge_id() { return _id; } + EdgeIter _ptr; + edge_id _id; + }; + typedef edge_descriptor E; + + struct edge_iterator + { + typedef edge_iterator self; + typedef E value_type; + typedef E& reference; + typedef E* pointer; + typedef std::ptrdiff_t difference_type; + typedef std::input_iterator_tag iterator_category; + edge_iterator() {} + edge_iterator(EdgeIter iter) : _iter(iter), _i(0) {} + E operator*() { return E(_iter, _i); } + self& operator++() + { + ++_iter; + ++_i; + return *this; + } + self operator++(int) + { + self t = *this; + ++(*this); + return t; + } + bool operator==(const self& x) { return _iter == x._iter; } + bool operator!=(const self& x) { return _iter != x._iter; } + EdgeIter _iter; + edge_id _i; + }; + typedef void out_edge_iterator; + typedef void in_edge_iterator; + typedef void adjacency_iterator; + typedef void vertex_iterator; +}; + +template < class G, class EI, class T, class D > +std::pair< typename edge_list_impl< G, EI, T, D >::edge_iterator, + typename edge_list_impl< G, EI, T, D >::edge_iterator > +edges(const edge_list_impl< G, EI, T, D >& g_) +{ + const G& g = static_cast< const G& >(g_); + typedef typename edge_list_impl< G, EI, T, D >::edge_iterator edge_iterator; + return std::make_pair(edge_iterator(g._first), edge_iterator(g._last)); +} +template < class G, class EI, class T, class D > +typename edge_list_impl< G, EI, T, D >::vertex_descriptor source( + typename edge_list_impl< G, EI, T, D >::edge_descriptor e, + const edge_list_impl< G, EI, T, D >&) +{ + return (*e._ptr).first; +} +template < class G, class EI, class T, class D > +typename edge_list_impl< G, EI, T, D >::vertex_descriptor target( + typename edge_list_impl< G, EI, T, D >::edge_descriptor e, + const edge_list_impl< G, EI, T, D >&) +{ + return (*e._ptr).second; +} + +template < class D, class E > +class el_edge_property_map +: public put_get_helper< D, el_edge_property_map< D, E > > +{ +public: + typedef E key_type; + typedef D value_type; + typedef D reference; + typedef readable_property_map_tag category; + + value_type operator[](key_type e) const { return e._i; } +}; +struct edge_list_edge_property_selector +{ + template < class Graph, class Property, class Tag > struct bind_ + { + typedef el_edge_property_map< typename Graph::edge_id, + typename Graph::edge_descriptor > + type; + typedef type const_type; + }; +}; +template <> struct edge_property_selector< edge_list_tag > +{ + typedef edge_list_edge_property_selector type; +}; + +template < class G, class EI, class T, class D > +typename property_map< edge_list_impl< G, EI, T, D >, edge_index_t >::type get( + edge_index_t, const edge_list_impl< G, EI, T, D >&) +{ + typedef typename property_map< edge_list_impl< G, EI, T, D >, + edge_index_t >::type EdgeIndexMap; + return EdgeIndexMap(); +} + +template < class G, class EI, class T, class D > +inline D get(edge_index_t, const edge_list_impl< G, EI, T, D >&, + typename edge_list_impl< G, EI, T, D >::edge_descriptor e) +{ + return e._i; +} + +// A specialized implementation for when the iterators are random access. + +struct edge_list_ra_tag +{ +}; + +template < class G, class EdgeIter, class T, class D > class edge_list_impl_ra +{ +public: + typedef D edge_id; + typedef T Vpair; + typedef typename Vpair::first_type V; + typedef edge_list_ra_tag graph_tag; + typedef void edge_property_type; + + typedef edge_id edge_descriptor; + typedef V vertex_descriptor; + typedef typename boost::integer_range< edge_id >::iterator edge_iterator; + typedef void out_edge_iterator; + typedef void in_edge_iterator; + typedef void adjacency_iterator; + typedef void vertex_iterator; +}; + +template < class G, class EI, class T, class D > +std::pair< typename edge_list_impl_ra< G, EI, T, D >::edge_iterator, + typename edge_list_impl_ra< G, EI, T, D >::edge_iterator > +edges(const edge_list_impl_ra< G, EI, T, D >& g_) +{ + const G& g = static_cast< const G& >(g_); + typedef + typename edge_list_impl_ra< G, EI, T, D >::edge_iterator edge_iterator; + return std::make_pair(edge_iterator(0), edge_iterator(g._last - g._first)); +} +template < class G, class EI, class T, class D > +typename edge_list_impl_ra< G, EI, T, D >::vertex_descriptor source( + typename edge_list_impl_ra< G, EI, T, D >::edge_descriptor e, + const edge_list_impl_ra< G, EI, T, D >& g_) +{ + const G& g = static_cast< const G& >(g_); + return g._first[e].first; +} +template < class G, class EI, class T, class D > +typename edge_list_impl_ra< G, EI, T, D >::vertex_descriptor target( + typename edge_list_impl_ra< G, EI, T, D >::edge_descriptor e, + const edge_list_impl_ra< G, EI, T, D >& g_) +{ + const G& g = static_cast< const G& >(g_); + return g._first[e].second; +} +template < class E > +class el_ra_edge_property_map +: public put_get_helper< E, el_ra_edge_property_map< E > > +{ +public: + typedef E key_type; + typedef E value_type; + typedef E reference; + typedef readable_property_map_tag category; + + value_type operator[](key_type e) const { return e; } +}; +struct edge_list_ra_edge_property_selector +{ + template < class Graph, class Property, class Tag > struct bind_ + { + typedef el_ra_edge_property_map< typename Graph::edge_descriptor > type; + typedef type const_type; + }; +}; +template <> struct edge_property_selector< edge_list_ra_tag > +{ + typedef edge_list_ra_edge_property_selector type; +}; +template < class G, class EI, class T, class D > +inline typename property_map< edge_list_impl_ra< G, EI, T, D >, + edge_index_t >::type +get(edge_index_t, const edge_list_impl_ra< G, EI, T, D >&) +{ + typedef typename property_map< edge_list_impl_ra< G, EI, T, D >, + edge_index_t >::type EdgeIndexMap; + return EdgeIndexMap(); +} + +template < class G, class EI, class T, class D > +inline D get(edge_index_t, const edge_list_impl_ra< G, EI, T, D >&, + typename edge_list_impl_ra< G, EI, T, D >::edge_descriptor e) +{ + return e; +} + +// Some helper classes for determining if the iterators are random access +template < class Cat > struct is_random +{ + enum + { + RET = false + }; + typedef mpl::false_ type; +}; +template <> struct is_random< std::random_access_iterator_tag > +{ + enum + { + RET = true + }; + typedef mpl::true_ type; +}; + +// The edge_list class conditionally inherits from one of the +// above two classes. + +template < class EdgeIter, +#if !defined BOOST_NO_STD_ITERATOR_TRAITS + class T = typename std::iterator_traits< EdgeIter >::value_type, + class D = typename std::iterator_traits< EdgeIter >::difference_type, + class Cat = typename std::iterator_traits< EdgeIter >::iterator_category > +#else + class T, class D, class Cat > +#endif +class edge_list +: public mpl::if_< typename is_random< Cat >::type, + edge_list_impl_ra< edge_list< EdgeIter, T, D, Cat >, EdgeIter, T, D >, + edge_list_impl< edge_list< EdgeIter, T, D, Cat >, EdgeIter, T, D > >::type +{ +public: + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; + typedef edge_list_graph_tag traversal_category; + typedef std::size_t edges_size_type; + typedef std::size_t vertices_size_type; + typedef std::size_t degree_size_type; + edge_list(EdgeIter first, EdgeIter last) : _first(first), _last(last) + { + m_num_edges = std::distance(first, last); + } + edge_list(EdgeIter first, EdgeIter last, edges_size_type E) + : _first(first), _last(last), m_num_edges(E) + { + } + + EdgeIter _first, _last; + edges_size_type m_num_edges; +}; + +template < class EdgeIter, class T, class D, class Cat > +std::size_t num_edges(const edge_list< EdgeIter, T, D, Cat >& el) +{ + return el.m_num_edges; +} + +#ifndef BOOST_NO_STD_ITERATOR_TRAITS +template < class EdgeIter > +inline edge_list< EdgeIter > make_edge_list(EdgeIter first, EdgeIter last) +{ + return edge_list< EdgeIter >(first, last); +} +#endif + +} /* namespace boost */ + +#endif /* BOOST_GRAPH_EDGE_LIST_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/graph/edmonds_karp_max_flow.hpp b/contrib/restricted/boost/graph/include/boost/graph/edmonds_karp_max_flow.hpp new file mode 100644 index 0000000000..cd8aa99f63 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/edmonds_karp_max_flow.hpp @@ -0,0 +1,245 @@ +//======================================================================= +// Copyright 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_EDMONDS_KARP_MAX_FLOW_HPP +#define BOOST_GRAPH_EDMONDS_KARP_MAX_FLOW_HPP + +#include <boost/config.hpp> +#include <vector> +#include <algorithm> // for std::min and std::max +#include <boost/config.hpp> +#include <boost/pending/queue.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/filtered_graph.hpp> +#include <boost/graph/breadth_first_search.hpp> + +namespace boost +{ + +// The "labeling" algorithm from "Network Flows" by Ahuja, Magnanti, +// Orlin. I think this is the same as or very similar to the original +// Edmonds-Karp algorithm. This solves the maximum flow problem. + +namespace detail +{ + + template < class Graph, class ResCapMap > + filtered_graph< Graph, is_residual_edge< ResCapMap > > residual_graph( + Graph& g, ResCapMap residual_capacity) + { + return filtered_graph< Graph, is_residual_edge< ResCapMap > >( + g, is_residual_edge< ResCapMap >(residual_capacity)); + } + + template < class Graph, class PredEdgeMap, class ResCapMap, + class RevEdgeMap > + inline void augment(Graph& g, + typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, PredEdgeMap p, + ResCapMap residual_capacity, RevEdgeMap reverse_edge) + { + typename graph_traits< Graph >::edge_descriptor e; + typename graph_traits< Graph >::vertex_descriptor u; + typedef typename property_traits< ResCapMap >::value_type FlowValue; + + // find minimum residual capacity along the augmenting path + FlowValue delta = (std::numeric_limits< FlowValue >::max)(); + e = get(p, sink); + do + { + BOOST_USING_STD_MIN(); + delta = min BOOST_PREVENT_MACRO_SUBSTITUTION( + delta, get(residual_capacity, e)); + u = source(e, g); + e = get(p, u); + } while (u != src); + + // push delta units of flow along the augmenting path + e = get(p, sink); + do + { + put(residual_capacity, e, get(residual_capacity, e) - delta); + put(residual_capacity, get(reverse_edge, e), + get(residual_capacity, get(reverse_edge, e)) + delta); + u = source(e, g); + e = get(p, u); + } while (u != src); + } + +} // namespace detail + +template < class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, + class ReverseEdgeMap, class ColorMap, class PredEdgeMap > +typename property_traits< CapacityEdgeMap >::value_type edmonds_karp_max_flow( + Graph& g, typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, CapacityEdgeMap cap, + ResidualCapacityEdgeMap res, ReverseEdgeMap rev, ColorMap color, + PredEdgeMap pred) +{ + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + + typename graph_traits< Graph >::vertex_iterator u_iter, u_end; + typename graph_traits< Graph >::out_edge_iterator ei, e_end; + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter) + for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; ++ei) + put(res, *ei, get(cap, *ei)); + + put(color, sink, Color::gray()); + while (get(color, sink) != Color::white()) + { + boost::queue< vertex_t > Q; + breadth_first_search(detail::residual_graph(g, res), src, Q, + make_bfs_visitor(record_edge_predecessors(pred, on_tree_edge())), + color); + if (get(color, sink) != Color::white()) + detail::augment(g, src, sink, pred, res, rev); + } // while + + typename property_traits< CapacityEdgeMap >::value_type flow = 0; + for (boost::tie(ei, e_end) = out_edges(src, g); ei != e_end; ++ei) + flow += (get(cap, *ei) - get(res, *ei)); + return flow; +} // edmonds_karp_max_flow() + +namespace detail +{ + //------------------------------------------------------------------------- + // Handle default for color property map + + // use of class here is a VC++ workaround + template < class ColorMap > struct edmonds_karp_dispatch2 + { + template < class Graph, class PredMap, class P, class T, class R > + static typename edge_capacity_value< Graph, P, T, R >::type apply( + Graph& g, typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, + PredMap pred, const bgl_named_params< P, T, R >& params, + ColorMap color) + { + return edmonds_karp_max_flow(g, src, sink, + choose_const_pmap( + get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), g, + edge_residual_capacity), + choose_const_pmap( + get_param(params, edge_reverse), g, edge_reverse), + color, pred); + } + }; + template <> struct edmonds_karp_dispatch2< param_not_found > + { + template < class Graph, class PredMap, class P, class T, class R > + static typename edge_capacity_value< Graph, P, T, R >::type apply( + Graph& g, typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, + PredMap pred, const bgl_named_params< P, T, R >& params, + param_not_found) + { + typedef + typename graph_traits< Graph >::vertices_size_type size_type; + size_type n = is_default_param(get_param(params, vertex_color)) + ? num_vertices(g) + : 1; + std::vector< default_color_type > color_vec(n); + return edmonds_karp_max_flow(g, src, sink, + choose_const_pmap( + get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), g, + edge_residual_capacity), + choose_const_pmap( + get_param(params, edge_reverse), g, edge_reverse), + make_iterator_property_map(color_vec.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index), + color_vec[0]), + pred); + } + }; + + //------------------------------------------------------------------------- + // Handle default for predecessor property map + + // use of class here is a VC++ workaround + template < class PredMap > struct edmonds_karp_dispatch1 + { + template < class Graph, class P, class T, class R > + static typename edge_capacity_value< Graph, P, T, R >::type apply( + Graph& g, typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, + const bgl_named_params< P, T, R >& params, PredMap pred) + { + typedef typename get_param_type< vertex_color_t, + bgl_named_params< P, T, R > >::type C; + return edmonds_karp_dispatch2< C >::apply( + g, src, sink, pred, params, get_param(params, vertex_color)); + } + }; + template <> struct edmonds_karp_dispatch1< param_not_found > + { + + template < class Graph, class P, class T, class R > + static typename edge_capacity_value< Graph, P, T, R >::type apply( + Graph& g, typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, + const bgl_named_params< P, T, R >& params, param_not_found) + { + typedef + typename graph_traits< Graph >::edge_descriptor edge_descriptor; + typedef + typename graph_traits< Graph >::vertices_size_type size_type; + size_type n + = is_default_param(get_param(params, vertex_predecessor)) + ? num_vertices(g) + : 1; + std::vector< edge_descriptor > pred_vec(n); + + typedef typename get_param_type< vertex_color_t, + bgl_named_params< P, T, R > >::type C; + return edmonds_karp_dispatch2< C >::apply(g, src, sink, + make_iterator_property_map(pred_vec.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index), + pred_vec[0]), + params, get_param(params, vertex_color)); + } + }; + +} // namespace detail + +template < class Graph, class P, class T, class R > +typename detail::edge_capacity_value< Graph, P, T, R >::type +edmonds_karp_max_flow(Graph& g, + typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, + const bgl_named_params< P, T, R >& params) +{ + typedef typename get_param_type< vertex_predecessor_t, + bgl_named_params< P, T, R > >::type Pred; + return detail::edmonds_karp_dispatch1< Pred >::apply( + g, src, sink, params, get_param(params, vertex_predecessor)); +} + +template < class Graph > +typename property_traits< + typename property_map< Graph, edge_capacity_t >::const_type >::value_type +edmonds_karp_max_flow(Graph& g, + typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink) +{ + bgl_named_params< int, buffer_param_t > params(0); + return edmonds_karp_max_flow(g, src, sink, params); +} + +} // namespace boost + +#endif // BOOST_GRAPH_EDMONDS_KARP_MAX_FLOW_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/edmunds_karp_max_flow.hpp b/contrib/restricted/boost/graph/include/boost/graph/edmunds_karp_max_flow.hpp new file mode 100644 index 0000000000..aee587acd9 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/edmunds_karp_max_flow.hpp @@ -0,0 +1,22 @@ +//======================================================================= +// (c) Copyright Juergen Hunold 2008 +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP +#define BOOST_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP + +#if defined(_MSC_VER) || defined(__BORLANDC__) && !defined(__clang__) || defined(__DMC__) +#pragma message( \ + "Warning: This header is deprecated. Please use: boost/graph/edmonds_karp_max_flow.hpp") +#elif defined(__GNUC__) || defined(__HP_aCC) || defined(__SUNPRO_CC) \ + || defined(__IBMCPP__) || defined(__BORLANDC__) +#warning \ + "This header is deprecated. Please use: boost/graph/edmonds_karp_max_flow.hpp" +#endif + +#include <boost/graph/edmonds_karp_max_flow.hpp> + +#endif // BOOST_DEPRECATED_INCLUDE_EDMONDS_KARP_MAX_FLOW_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/erdos_renyi_generator.hpp b/contrib/restricted/boost/graph/include/boost/graph/erdos_renyi_generator.hpp new file mode 100644 index 0000000000..f5e33c9632 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/erdos_renyi_generator.hpp @@ -0,0 +1,221 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP +#define BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP + +#include <boost/assert.hpp> +#include <iterator> +#include <utility> +#include <boost/shared_ptr.hpp> +#include <boost/random/uniform_int.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/random/geometric_distribution.hpp> +#include <boost/type_traits/is_base_of.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/iterator/iterator_facade.hpp> + +namespace boost +{ + +template < typename RandomGenerator, typename Graph > +class erdos_renyi_iterator +: public iterator_facade< erdos_renyi_iterator< RandomGenerator, Graph >, + std::pair< typename graph_traits< Graph >::vertices_size_type, + typename graph_traits< Graph >::vertices_size_type >, + std::input_iterator_tag, + const std::pair< typename graph_traits< Graph >::vertices_size_type, + typename graph_traits< Graph >::vertices_size_type >& > +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + typedef typename graph_traits< Graph >::edges_size_type edges_size_type; + + BOOST_STATIC_CONSTANT(bool, + is_undirected + = (is_base_of< undirected_tag, directed_category >::value)); + +public: + erdos_renyi_iterator() : gen(), n(0), edges(0), allow_self_loops(false) {} + erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n, + double fraction = 0.0, bool allow_self_loops = false) + : gen(&gen) + , n(n) + , edges(edges_size_type(fraction * n * n)) + , allow_self_loops(allow_self_loops) + { + if (is_undirected) + edges = edges / 2; + next(); + } + + erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, bool allow_self_loops = false) + : gen(&gen), n(n), edges(m), allow_self_loops(allow_self_loops) + { + next(); + } + + const std::pair< vertices_size_type, vertices_size_type >& + dereference() const + { + return current; + } + + void increment() + { + --edges; + next(); + } + + bool equal(const erdos_renyi_iterator& other) const + { + return edges == other.edges; + } + +private: + void next() + { + uniform_int< vertices_size_type > rand_vertex(0, n - 1); + current.first = rand_vertex(*gen); + do + { + current.second = rand_vertex(*gen); + } while (current.first == current.second && !allow_self_loops); + } + + RandomGenerator* gen; + vertices_size_type n; + edges_size_type edges; + bool allow_self_loops; + std::pair< vertices_size_type, vertices_size_type > current; +}; + +template < typename RandomGenerator, typename Graph > +class sorted_erdos_renyi_iterator +: public iterator_facade< sorted_erdos_renyi_iterator< RandomGenerator, Graph >, + std::pair< typename graph_traits< Graph >::vertices_size_type, + typename graph_traits< Graph >::vertices_size_type >, + std::input_iterator_tag, + const std::pair< typename graph_traits< Graph >::vertices_size_type, + typename graph_traits< Graph >::vertices_size_type >& > +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + typedef typename graph_traits< Graph >::edges_size_type edges_size_type; + + BOOST_STATIC_CONSTANT(bool, + is_undirected + = (is_base_of< undirected_tag, directed_category >::value)); + +public: + sorted_erdos_renyi_iterator() + : gen() + , rand_vertex(0.5) + , n(0) + , allow_self_loops(false) + , src((std::numeric_limits< vertices_size_type >::max)()) + , tgt_index(vertices_size_type(-1)) + , prob(.5) + { + } + + // NOTE: The default probability has been changed to be the same as that + // used by the geometic distribution. It was previously 0.0, which would + // cause an assertion. + sorted_erdos_renyi_iterator(RandomGenerator& gen, vertices_size_type n, + double prob = 0.5, bool loops = false) + : gen() + , rand_vertex(1. - prob) + , n(n) + , allow_self_loops(loops) + , src(0) + , tgt_index(vertices_size_type(-1)) + , prob(prob) + { + this->gen.reset(new uniform_01< RandomGenerator* >(&gen)); + + if (prob == 0.0) + { + src = (std::numeric_limits< vertices_size_type >::max)(); + return; + } + next(); + } + + const std::pair< vertices_size_type, vertices_size_type >& + dereference() const + { + return current; + } + + bool equal(const sorted_erdos_renyi_iterator& o) const + { + return src == o.src && tgt_index == o.tgt_index; + } + + void increment() { next(); } + +private: + void next() + { + // In order to get the edges from the generator in sorted order, one + // effective (but slow) procedure would be to use a + // bernoulli_distribution for each legal (src, tgt_index) pair. Because + // of the O(|V|^2) cost of that, a geometric distribution is used. The + // geometric distribution tells how many times the + // bernoulli_distribution would need to be run until it returns true. + // Thus, this distribution can be used to step through the edges + // which are actually present. + BOOST_ASSERT(src != (std::numeric_limits< vertices_size_type >::max)() + && src != n); + while (src != n) + { + vertices_size_type increment = rand_vertex(*gen); + size_t tgt_index_limit + = (is_undirected ? src + 1 : n) + (allow_self_loops ? 0 : -1); + if (tgt_index + increment >= tgt_index_limit) + { + // Overflowed this source; go to the next one and try again. + ++src; + // This bias is because the geometric distribution always + // returns values >=1, and we want to allow 0 as a valid target. + tgt_index = vertices_size_type(-1); + continue; + } + else + { + tgt_index += increment; + current.first = src; + current.second = tgt_index + + (!allow_self_loops && !is_undirected && tgt_index >= src + ? 1 + : 0); + break; + } + } + if (src == n) + src = (std::numeric_limits< vertices_size_type >::max)(); + } + + shared_ptr< uniform_01< RandomGenerator* > > gen; + geometric_distribution< vertices_size_type > rand_vertex; + vertices_size_type n; + bool allow_self_loops; + vertices_size_type src, tgt_index; + std::pair< vertices_size_type, vertices_size_type > current; + double prob; +}; + +} // end namespace boost + +#endif // BOOST_GRAPH_ERDOS_RENYI_GENERATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/exterior_property.hpp b/contrib/restricted/boost/graph/include/boost/graph/exterior_property.hpp new file mode 100644 index 0000000000..281b7bb2a9 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/exterior_property.hpp @@ -0,0 +1,114 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_EXTERIOR_PROPERTY_HPP +#define BOOST_GRAPH_EXTERIOR_PROPERTY_HPP + +#include <vector> +#include <boost/graph/property_maps/container_property_map.hpp> +#include <boost/graph/property_maps/matrix_property_map.hpp> + +namespace boost +{ +namespace detail +{ + // The vector matrix provides a little abstraction over vector + // types that makes matrices easier to work with. + template < typename Value > struct vector_matrix + { + typedef std::vector< Value > container_type; + typedef std::vector< container_type > matrix_type; + + typedef container_type value_type; + typedef container_type& reference; + typedef const container_type const_reference; + typedef container_type* pointer; + typedef typename matrix_type::size_type size_type; + + // Instantiate the matrix over n elements (creates an n by n matrix). + // The graph has to be passed in order to ensure the index maps + // are constructed correctly when returning indexible elements. + inline vector_matrix(size_type n) : m_matrix(n, container_type(n)) {} + + inline reference operator[](size_type n) { return m_matrix[n]; } + + inline const_reference operator[](size_type n) const + { + return m_matrix[n]; + } + + matrix_type m_matrix; + }; +} /* namespace detail */ + +/** + * The exterior_property metafunction defines an appropriate set of types for + * creating an exterior property. An exterior property is comprised of a both + * a container and a property map that acts as its abstraction. An extension + * of this metafunction will select an appropriate "matrix" property that + * records values for pairs of vertices. + * + * @todo This does not currently support the ability to define exterior + * properties for graph types that do not model the IndexGraph concepts. A + * solution should not be especially difficult, but will require an extension + * of type traits to affect the type selection. + */ +template < typename Graph, typename Key, typename Value > +struct exterior_property +{ + typedef Key key_type; + typedef Value value_type; + + typedef std::vector< Value > container_type; + typedef container_property_map< Graph, Key, container_type > map_type; + + typedef detail::vector_matrix< Value > matrix_type; + typedef matrix_property_map< Graph, Key, matrix_type > matrix_map_type; + +private: + exterior_property() {} + exterior_property(const exterior_property&) {} +}; + +/** + * Define a the container and property map types requried to create an exterior + * vertex property for the given value type. The Graph parameter is required to + * model the VertexIndexGraph concept. + */ +template < typename Graph, typename Value > struct exterior_vertex_property +{ + typedef exterior_property< Graph, + typename graph_traits< Graph >::vertex_descriptor, Value > + property_type; + typedef typename property_type::key_type key_type; + typedef typename property_type::value_type value_type; + typedef typename property_type::container_type container_type; + typedef typename property_type::map_type map_type; + typedef typename property_type::matrix_type matrix_type; + typedef typename property_type::matrix_map_type matrix_map_type; +}; + +/** + * Define a the container and property map types requried to create an exterior + * edge property for the given value type. The Graph parameter is required to + * model the EdgeIndexGraph concept. + */ +template < typename Graph, typename Value > struct exterior_edge_property +{ + typedef exterior_property< Graph, + typename graph_traits< Graph >::edge_descriptor, Value > + property_type; + typedef typename property_type::key_type key_type; + typedef typename property_type::value_type value_type; + typedef typename property_type::container_type container_type; + typedef typename property_type::map_type map_type; + typedef typename property_type::matrix_type matrix_type; + typedef typename property_type::matrix_map_type matrix_map_type; +}; + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/find_flow_cost.hpp b/contrib/restricted/boost/graph/include/boost/graph/find_flow_cost.hpp new file mode 100644 index 0000000000..78fd955d83 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/find_flow_cost.hpp @@ -0,0 +1,57 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_FIND_FLOW_COST_HPP +#define BOOST_GRAPH_FIND_FLOW_COST_HPP + +#include <boost/graph/iteration_macros.hpp> + +namespace boost +{ + +template < class Graph, class Capacity, class ResidualCapacity, class Weight > +typename property_traits< Weight >::value_type find_flow_cost(const Graph& g, + Capacity capacity, ResidualCapacity residual_capacity, Weight weight) +{ + typedef typename property_traits< Weight >::value_type Cost; + + Cost cost = 0; + BGL_FORALL_EDGES_T(e, g, Graph) + { + if (get(capacity, e) > Cost(0)) + { + cost += (get(capacity, e) - get(residual_capacity, e)) + * get(weight, e); + } + } + return cost; +} + +template < class Graph, class P, class T, class R > +typename detail::edge_weight_value< Graph, P, T, R >::type find_flow_cost( + const Graph& g, const bgl_named_params< P, T, R >& params) +{ + return find_flow_cost(g, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_const_pmap(get_param(params, edge_residual_capacity), g, + edge_residual_capacity), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); +} + +template < class Graph > +typename property_traits< + typename property_map< Graph, edge_capacity_t >::type >::value_type +find_flow_cost(const Graph& g) +{ + bgl_named_params< int, buffer_param_t > params(0); + return find_flow_cost(g, params); +} + +} // boost + +#endif /* BOOST_GRAPH_FIND_FLOW_COST_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/graph/floyd_warshall_shortest.hpp b/contrib/restricted/boost/graph/include/boost/graph/floyd_warshall_shortest.hpp new file mode 100644 index 0000000000..e8eeae5472 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/floyd_warshall_shortest.hpp @@ -0,0 +1,223 @@ +// Copyright 2002 Rensselaer Polytechnic Institute + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Lauren Foutz +// Scott Hill + +/* + This file implements the functions + + template <class VertexListGraph, class DistanceMatrix, + class P, class T, class R> + bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d, + const bgl_named_params<P, T, R>& params) + + AND + + template <class VertexAndEdgeListGraph, class DistanceMatrix, + class P, class T, class R> + bool floyd_warshall_all_pairs_shortest_paths( + const VertexAndEdgeListGraph& g, DistanceMatrix& d, + const bgl_named_params<P, T, R>& params) +*/ + +#ifndef BOOST_GRAPH_FLOYD_WARSHALL_HPP +#define BOOST_GRAPH_FLOYD_WARSHALL_HPP + +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/relax.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ +namespace detail +{ + template < typename T, typename BinaryPredicate > + T min_with_compare(const T& x, const T& y, const BinaryPredicate& compare) + { + if (compare(x, y)) + return x; + else + return y; + } + + template < typename VertexListGraph, typename DistanceMatrix, + typename BinaryPredicate, typename BinaryFunction, typename Infinity, + typename Zero > + bool floyd_warshall_dispatch(const VertexListGraph& g, DistanceMatrix& d, + const BinaryPredicate& compare, const BinaryFunction& combine, + const Infinity& inf, const Zero& zero) + { + typename graph_traits< VertexListGraph >::vertex_iterator i, lasti, j, + lastj, k, lastk; + + for (boost::tie(k, lastk) = vertices(g); k != lastk; k++) + for (boost::tie(i, lasti) = vertices(g); i != lasti; i++) + if (d[*i][*k] != inf) + for (boost::tie(j, lastj) = vertices(g); j != lastj; j++) + if (d[*k][*j] != inf) + d[*i][*j] = detail::min_with_compare(d[*i][*j], + combine(d[*i][*k], d[*k][*j]), compare); + + for (boost::tie(i, lasti) = vertices(g); i != lasti; i++) + if (compare(d[*i][*i], zero)) + return false; + return true; + } +} + +template < typename VertexListGraph, typename DistanceMatrix, + typename BinaryPredicate, typename BinaryFunction, typename Infinity, + typename Zero > +bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d, const BinaryPredicate& compare, + const BinaryFunction& combine, const Infinity& inf, const Zero& zero) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< VertexListGraph >)); + + return detail::floyd_warshall_dispatch(g, d, compare, combine, inf, zero); +} + +template < typename VertexAndEdgeListGraph, typename DistanceMatrix, + typename WeightMap, typename BinaryPredicate, typename BinaryFunction, + typename Infinity, typename Zero > +bool floyd_warshall_all_pairs_shortest_paths(const VertexAndEdgeListGraph& g, + DistanceMatrix& d, const WeightMap& w, const BinaryPredicate& compare, + const BinaryFunction& combine, const Infinity& inf, const Zero& zero) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< VertexAndEdgeListGraph >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< VertexAndEdgeListGraph >)); + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< VertexAndEdgeListGraph >)); + + typename graph_traits< VertexAndEdgeListGraph >::vertex_iterator firstv, + lastv, firstv2, lastv2; + typename graph_traits< VertexAndEdgeListGraph >::edge_iterator first, last; + + for (boost::tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++) + for (boost::tie(firstv2, lastv2) = vertices(g); firstv2 != lastv2; + firstv2++) + d[*firstv][*firstv2] = inf; + + for (boost::tie(firstv, lastv) = vertices(g); firstv != lastv; firstv++) + d[*firstv][*firstv] = zero; + + for (boost::tie(first, last) = edges(g); first != last; first++) + { + if (d[source(*first, g)][target(*first, g)] != inf) + { + d[source(*first, g)][target(*first, g)] + = detail::min_with_compare(get(w, *first), + d[source(*first, g)][target(*first, g)], compare); + } + else + d[source(*first, g)][target(*first, g)] = get(w, *first); + } + + bool is_undirected = is_same< + typename graph_traits< VertexAndEdgeListGraph >::directed_category, + undirected_tag >::value; + if (is_undirected) + { + for (boost::tie(first, last) = edges(g); first != last; first++) + { + if (d[target(*first, g)][source(*first, g)] != inf) + d[target(*first, g)][source(*first, g)] + = detail::min_with_compare(get(w, *first), + d[target(*first, g)][source(*first, g)], compare); + else + d[target(*first, g)][source(*first, g)] = get(w, *first); + } + } + + return detail::floyd_warshall_dispatch(g, d, compare, combine, inf, zero); +} + +namespace detail +{ + template < class VertexListGraph, class DistanceMatrix, class WeightMap, + class P, class T, class R > + bool floyd_warshall_init_dispatch(const VertexListGraph& g, + DistanceMatrix& d, WeightMap /*w*/, + const bgl_named_params< P, T, R >& params) + { + typedef typename property_traits< WeightMap >::value_type WM; + WM inf = choose_param(get_param(params, distance_inf_t()), + std::numeric_limits< WM >::max BOOST_PREVENT_MACRO_SUBSTITUTION()); + + return floyd_warshall_initialized_all_pairs_shortest_paths(g, d, + choose_param( + get_param(params, distance_compare_t()), std::less< WM >()), + choose_param(get_param(params, distance_combine_t()), + closed_plus< WM >(inf)), + inf, choose_param(get_param(params, distance_zero_t()), WM())); + } + + template < class VertexAndEdgeListGraph, class DistanceMatrix, + class WeightMap, class P, class T, class R > + bool floyd_warshall_noninit_dispatch(const VertexAndEdgeListGraph& g, + DistanceMatrix& d, WeightMap w, + const bgl_named_params< P, T, R >& params) + { + typedef typename property_traits< WeightMap >::value_type WM; + + WM inf = choose_param(get_param(params, distance_inf_t()), + std::numeric_limits< WM >::max BOOST_PREVENT_MACRO_SUBSTITUTION()); + return floyd_warshall_all_pairs_shortest_paths(g, d, w, + choose_param( + get_param(params, distance_compare_t()), std::less< WM >()), + choose_param(get_param(params, distance_combine_t()), + closed_plus< WM >(inf)), + inf, choose_param(get_param(params, distance_zero_t()), WM())); + } + +} // namespace detail + +template < class VertexListGraph, class DistanceMatrix, class P, class T, + class R > +bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d, + const bgl_named_params< P, T, R >& params) +{ + return detail::floyd_warshall_init_dispatch(g, d, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + params); +} + +template < class VertexListGraph, class DistanceMatrix > +bool floyd_warshall_initialized_all_pairs_shortest_paths( + const VertexListGraph& g, DistanceMatrix& d) +{ + bgl_named_params< int, int > params(0); + return detail::floyd_warshall_init_dispatch( + g, d, get(edge_weight, g), params); +} + +template < class VertexAndEdgeListGraph, class DistanceMatrix, class P, class T, + class R > +bool floyd_warshall_all_pairs_shortest_paths(const VertexAndEdgeListGraph& g, + DistanceMatrix& d, const bgl_named_params< P, T, R >& params) +{ + return detail::floyd_warshall_noninit_dispatch(g, d, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + params); +} + +template < class VertexAndEdgeListGraph, class DistanceMatrix > +bool floyd_warshall_all_pairs_shortest_paths( + const VertexAndEdgeListGraph& g, DistanceMatrix& d) +{ + bgl_named_params< int, int > params(0); + return detail::floyd_warshall_noninit_dispatch( + g, d, get(edge_weight, g), params); +} + +} // namespace boost + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/fruchterman_reingold.hpp b/contrib/restricted/boost/graph/include/boost/graph/fruchterman_reingold.hpp new file mode 100644 index 0000000000..d2a443427d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/fruchterman_reingold.hpp @@ -0,0 +1,460 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP +#define BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/topology.hpp> // For topology concepts +#include <boost/graph/detail/mpi_include.hpp> +#include <vector> +#include <list> +#include <algorithm> // for std::min and std::max +#include <numeric> // for std::accumulate +#include <cmath> // for std::sqrt and std::fabs +#include <functional> + +namespace boost +{ + +struct square_distance_attractive_force +{ + template < typename Graph, typename T > + T operator()(typename graph_traits< Graph >::edge_descriptor, T k, T d, + const Graph&) const + { + return d * d / k; + } +}; + +struct square_distance_repulsive_force +{ + template < typename Graph, typename T > + T operator()(typename graph_traits< Graph >::vertex_descriptor, + typename graph_traits< Graph >::vertex_descriptor, T k, T d, + const Graph&) const + { + return k * k / d; + } +}; + +template < typename T > struct linear_cooling +{ + typedef T result_type; + + linear_cooling(std::size_t iterations) + : temp(T(iterations) / T(10)), step(0.1) + { + } + + linear_cooling(std::size_t iterations, T temp) + : temp(temp), step(temp / T(iterations)) + { + } + + T operator()() + { + T old_temp = temp; + temp -= step; + if (temp < T(0)) + temp = T(0); + return old_temp; + } + +private: + T temp; + T step; +}; + +struct all_force_pairs +{ + template < typename Graph, typename ApplyForce > + void operator()(const Graph& g, ApplyForce apply_force) + { + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator; + vertex_iterator v, end; + for (boost::tie(v, end) = vertices(g); v != end; ++v) + { + vertex_iterator u = v; + for (++u; u != end; ++u) + { + apply_force(*u, *v); + apply_force(*v, *u); + } + } + } +}; + +template < typename Topology, typename PositionMap > struct grid_force_pairs +{ + typedef typename property_traits< PositionMap >::value_type Point; + BOOST_STATIC_ASSERT(Point::dimensions == 2); + typedef typename Topology::point_difference_type point_difference_type; + + template < typename Graph > + explicit grid_force_pairs( + const Topology& topology, PositionMap position, const Graph& g) + : topology(topology), position(position) + { + two_k = 2. * this->topology.volume(this->topology.extent()) + / std::sqrt((double)num_vertices(g)); + } + + template < typename Graph, typename ApplyForce > + void operator()(const Graph& g, ApplyForce apply_force) + { + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator; + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + typedef std::list< vertex_descriptor > bucket_t; + typedef std::vector< bucket_t > buckets_t; + + std::size_t columns = std::size_t(topology.extent()[0] / two_k + 1.); + std::size_t rows = std::size_t(topology.extent()[1] / two_k + 1.); + buckets_t buckets(rows * columns); + vertex_iterator v, v_end; + for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) + { + std::size_t column = std::size_t( + (get(position, *v)[0] + topology.extent()[0] / 2) / two_k); + std::size_t row = std::size_t( + (get(position, *v)[1] + topology.extent()[1] / 2) / two_k); + + if (column >= columns) + column = columns - 1; + if (row >= rows) + row = rows - 1; + buckets[row * columns + column].push_back(*v); + } + + for (std::size_t row = 0; row < rows; ++row) + for (std::size_t column = 0; column < columns; ++column) + { + bucket_t& bucket = buckets[row * columns + column]; + typedef typename bucket_t::iterator bucket_iterator; + for (bucket_iterator u = bucket.begin(); u != bucket.end(); ++u) + { + // Repulse vertices in this bucket + bucket_iterator v = u; + for (++v; v != bucket.end(); ++v) + { + apply_force(*u, *v); + apply_force(*v, *u); + } + + std::size_t adj_start_row = row == 0 ? 0 : row - 1; + std::size_t adj_end_row = row == rows - 1 ? row : row + 1; + std::size_t adj_start_column = column == 0 ? 0 : column - 1; + std::size_t adj_end_column + = column == columns - 1 ? column : column + 1; + for (std::size_t other_row = adj_start_row; + other_row <= adj_end_row; ++other_row) + for (std::size_t other_column = adj_start_column; + other_column <= adj_end_column; ++other_column) + if (other_row != row || other_column != column) + { + // Repulse vertices in this bucket + bucket_t& other_bucket + = buckets[other_row * columns + + other_column]; + for (v = other_bucket.begin(); + v != other_bucket.end(); ++v) + { + double dist = topology.distance( + get(position, *u), get(position, *v)); + if (dist < two_k) + apply_force(*u, *v); + } + } + } + } + } + +private: + const Topology& topology; + PositionMap position; + double two_k; +}; + +template < typename PositionMap, typename Topology, typename Graph > +inline grid_force_pairs< Topology, PositionMap > make_grid_force_pairs( + const Topology& topology, const PositionMap& position, const Graph& g) +{ + return grid_force_pairs< Topology, PositionMap >(topology, position, g); +} + +template < typename Graph, typename PositionMap, typename Topology > +void scale_graph(const Graph& g, PositionMap position, const Topology& topology, + typename Topology::point_type upper_left, + typename Topology::point_type lower_right) +{ + if (num_vertices(g) == 0) + return; + + typedef typename Topology::point_type Point; + typedef typename Topology::point_difference_type point_difference_type; + + // Find min/max ranges + Point min_point = get(position, *vertices(g).first), max_point = min_point; + BGL_FORALL_VERTICES_T(v, g, Graph) + { + min_point = topology.pointwise_min(min_point, get(position, v)); + max_point = topology.pointwise_max(max_point, get(position, v)); + } + + Point old_origin = topology.move_position_toward(min_point, 0.5, max_point); + Point new_origin + = topology.move_position_toward(upper_left, 0.5, lower_right); + point_difference_type old_size = topology.difference(max_point, min_point); + point_difference_type new_size + = topology.difference(lower_right, upper_left); + + // Scale to bounding box provided + BGL_FORALL_VERTICES_T(v, g, Graph) + { + point_difference_type relative_loc + = topology.difference(get(position, v), old_origin); + relative_loc = (relative_loc / old_size) * new_size; + put(position, v, topology.adjust(new_origin, relative_loc)); + } +} + +namespace detail +{ + template < typename Topology, typename PropMap, typename Vertex > + void maybe_jitter_point(const Topology& topology, const PropMap& pm, + Vertex v, const typename Topology::point_type& p2) + { + double too_close = topology.norm(topology.extent()) / 10000.; + if (topology.distance(get(pm, v), p2) < too_close) + { + put(pm, v, + topology.move_position_toward( + get(pm, v), 1. / 200, topology.random_point())); + } + } + + template < typename Topology, typename PositionMap, + typename DisplacementMap, typename RepulsiveForce, typename Graph > + struct fr_apply_force + { + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + typedef typename Topology::point_type Point; + typedef typename Topology::point_difference_type PointDiff; + + fr_apply_force(const Topology& topology, const PositionMap& position, + const DisplacementMap& displacement, RepulsiveForce repulsive_force, + double k, const Graph& g) + : topology(topology) + , position(position) + , displacement(displacement) + , repulsive_force(repulsive_force) + , k(k) + , g(g) + { + } + + void operator()(vertex_descriptor u, vertex_descriptor v) + { + if (u != v) + { + // When the vertices land on top of each other, move the + // first vertex away from the boundaries. + maybe_jitter_point(topology, position, u, get(position, v)); + + double dist + = topology.distance(get(position, u), get(position, v)); + typename Topology::point_difference_type dispv + = get(displacement, v); + if (dist == 0.) + { + for (std::size_t i = 0; i < Point::dimensions; ++i) + { + dispv[i] += 0.01; + } + } + else + { + double fr = repulsive_force(u, v, k, dist, g); + dispv += (fr / dist) + * topology.difference( + get(position, v), get(position, u)); + } + put(displacement, v, dispv); + } + } + + private: + const Topology& topology; + PositionMap position; + DisplacementMap displacement; + RepulsiveForce repulsive_force; + double k; + const Graph& g; + }; + +} // end namespace detail + +template < typename Topology, typename Graph, typename PositionMap, + typename AttractiveForce, typename RepulsiveForce, typename ForcePairs, + typename Cooling, typename DisplacementMap > +void fruchterman_reingold_force_directed_layout(const Graph& g, + PositionMap position, const Topology& topology, + AttractiveForce attractive_force, RepulsiveForce repulsive_force, + ForcePairs force_pairs, Cooling cool, DisplacementMap displacement) +{ + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator; + + double volume = topology.volume(topology.extent()); + + // assume positions are initialized randomly + double k = pow(volume / num_vertices(g), + 1. / (double)(Topology::point_difference_type::dimensions)); + + detail::fr_apply_force< Topology, PositionMap, DisplacementMap, + RepulsiveForce, Graph > + apply_force(topology, position, displacement, repulsive_force, k, g); + + do + { + // Calculate repulsive forces + vertex_iterator v, v_end; + for (boost::tie(v, v_end) = vertices(g); v != v_end; ++v) + put(displacement, *v, typename Topology::point_difference_type()); + force_pairs(g, apply_force); + + // Calculate attractive forces + edge_iterator e, e_end; + for (boost::tie(e, e_end) = edges(g); e != e_end; ++e) + { + vertex_descriptor v = source(*e, g); + vertex_descriptor u = target(*e, g); + + // When the vertices land on top of each other, move the + // first vertex away from the boundaries. + ::boost::detail::maybe_jitter_point( + topology, position, u, get(position, v)); + + typename Topology::point_difference_type delta + = topology.difference(get(position, v), get(position, u)); + double dist = topology.distance(get(position, u), get(position, v)); + double fa = attractive_force(*e, k, dist, g); + + put(displacement, v, get(displacement, v) - (fa / dist) * delta); + put(displacement, u, get(displacement, u) + (fa / dist) * delta); + } + + if (double temp = cool()) + { + // Update positions + BGL_FORALL_VERTICES_T(v, g, Graph) + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + double disp_size = topology.norm(get(displacement, v)); + put(position, v, + topology.adjust(get(position, v), + get(displacement, v) + * (min BOOST_PREVENT_MACRO_SUBSTITUTION( + disp_size, temp) + / disp_size))); + put(position, v, topology.bound(get(position, v))); + } + } + else + { + break; + } + } while (true); +} + +namespace detail +{ + template < typename DisplacementMap > struct fr_force_directed_layout + { + template < typename Topology, typename Graph, typename PositionMap, + typename AttractiveForce, typename RepulsiveForce, + typename ForcePairs, typename Cooling, typename Param, typename Tag, + typename Rest > + static void run(const Graph& g, PositionMap position, + const Topology& topology, AttractiveForce attractive_force, + RepulsiveForce repulsive_force, ForcePairs force_pairs, + Cooling cool, DisplacementMap displacement, + const bgl_named_params< Param, Tag, Rest >&) + { + fruchterman_reingold_force_directed_layout(g, position, topology, + attractive_force, repulsive_force, force_pairs, cool, + displacement); + } + }; + + template <> struct fr_force_directed_layout< param_not_found > + { + template < typename Topology, typename Graph, typename PositionMap, + typename AttractiveForce, typename RepulsiveForce, + typename ForcePairs, typename Cooling, typename Param, typename Tag, + typename Rest > + static void run(const Graph& g, PositionMap position, + const Topology& topology, AttractiveForce attractive_force, + RepulsiveForce repulsive_force, ForcePairs force_pairs, + Cooling cool, param_not_found, + const bgl_named_params< Param, Tag, Rest >& params) + { + typedef typename Topology::point_difference_type PointDiff; + std::vector< PointDiff > displacements(num_vertices(g)); + fruchterman_reingold_force_directed_layout(g, position, topology, + attractive_force, repulsive_force, force_pairs, cool, + make_iterator_property_map(displacements.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index), + PointDiff())); + } + }; + +} // end namespace detail + +template < typename Topology, typename Graph, typename PositionMap, + typename Param, typename Tag, typename Rest > +void fruchterman_reingold_force_directed_layout(const Graph& g, + PositionMap position, const Topology& topology, + const bgl_named_params< Param, Tag, Rest >& params) +{ + typedef typename get_param_type< vertex_displacement_t, + bgl_named_params< Param, Tag, Rest > >::type D; + + detail::fr_force_directed_layout< D >::run(g, position, topology, + choose_param(get_param(params, attractive_force_t()), + square_distance_attractive_force()), + choose_param(get_param(params, repulsive_force_t()), + square_distance_repulsive_force()), + choose_param(get_param(params, force_pairs_t()), + make_grid_force_pairs(topology, position, g)), + choose_param( + get_param(params, cooling_t()), linear_cooling< double >(100)), + get_param(params, vertex_displacement_t()), params); +} + +template < typename Topology, typename Graph, typename PositionMap > +void fruchterman_reingold_force_directed_layout( + const Graph& g, PositionMap position, const Topology& topology) +{ + fruchterman_reingold_force_directed_layout(g, position, topology, + attractive_force(square_distance_attractive_force())); +} + +} // end namespace boost + + + +#endif // BOOST_GRAPH_FRUCHTERMAN_REINGOLD_FORCE_DIRECTED_LAYOUT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/geodesic_distance.hpp b/contrib/restricted/boost/graph/include/boost/graph/geodesic_distance.hpp new file mode 100644 index 0000000000..5675406a08 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/geodesic_distance.hpp @@ -0,0 +1,217 @@ +// (C) Copyright Andrew Sutton 2007 +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_GEODESIC_DISTANCE_HPP +#define BOOST_GRAPH_GEODESIC_DISTANCE_HPP + +#include <boost/graph/detail/geodesic.hpp> +#include <boost/graph/exterior_property.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ +template < typename Graph, typename DistanceType, typename ResultType, + typename Divides = std::divides< ResultType > > +struct mean_geodesic_measure +: public geodesic_measure< Graph, DistanceType, ResultType > +{ + typedef geodesic_measure< Graph, DistanceType, ResultType > base_type; + typedef typename base_type::distance_type distance_type; + typedef typename base_type::result_type result_type; + + result_type operator()(distance_type d, const Graph& g) + { + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((NumericValueConcept< DistanceType >)); + BOOST_CONCEPT_ASSERT((NumericValueConcept< ResultType >)); +// NOTE: Disabled until this concept assert is fixed in Boost.ConceptCheck. +// BOOST_CONCEPT_ASSERT((AdaptableBinaryFunctionConcept< Divides, +// ResultType, ResultType, ResultType >)); + + return (d == base_type::infinite_distance()) + ? base_type::infinite_result() + : div(result_type(d), result_type(num_vertices(g) - 1)); + } + Divides div; +}; + +template < typename Graph, typename DistanceMap > +inline mean_geodesic_measure< Graph, + typename property_traits< DistanceMap >::value_type, double > +measure_mean_geodesic(const Graph&, DistanceMap) +{ + return mean_geodesic_measure< Graph, + typename property_traits< DistanceMap >::value_type, double >(); +} + +template < typename T, typename Graph, typename DistanceMap > +inline mean_geodesic_measure< Graph, + typename property_traits< DistanceMap >::value_type, T > +measure_mean_geodesic(const Graph&, DistanceMap) +{ + return mean_geodesic_measure< Graph, + typename property_traits< DistanceMap >::value_type, T >(); +} + +// This is a little different because it's expected that the result type +// should (must?) be the same as the distance type. There's a type of +// transitivity in this thinking... If the average of distances has type +// X then the average of x's should also be type X. Is there a case where this +// is not true? +// +// This type is a little under-genericized... It needs generic parameters +// for addition and division. +template < typename Graph, typename DistanceType > +struct mean_graph_distance_measure +: public geodesic_measure< Graph, DistanceType, DistanceType > +{ + typedef geodesic_measure< Graph, DistanceType, DistanceType > base_type; + typedef typename base_type::distance_type distance_type; + typedef typename base_type::result_type result_type; + + inline result_type operator()(distance_type d, const Graph& g) + { + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((NumericValueConcept< DistanceType >)); + + if (d == base_type::infinite_distance()) + { + return base_type::infinite_result(); + } + else + { + return d / result_type(num_vertices(g)); + } + } +}; + +template < typename Graph, typename DistanceMap > +inline mean_graph_distance_measure< Graph, + typename property_traits< DistanceMap >::value_type > +measure_graph_mean_geodesic(const Graph&, DistanceMap) +{ + typedef typename property_traits< DistanceMap >::value_type T; + return mean_graph_distance_measure< Graph, T >(); +} + +template < typename Graph, typename DistanceMap, typename Measure, + typename Combinator > +inline typename Measure::result_type mean_geodesic( + const Graph& g, DistanceMap dist, Measure measure, Combinator combine) +{ + BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >)); + typedef typename Measure::distance_type Distance; + + Distance n = detail::combine_distances(g, dist, combine, Distance(0)); + return measure(n, g); +} + +template < typename Graph, typename DistanceMap, typename Measure > +inline typename Measure::result_type mean_geodesic( + const Graph& g, DistanceMap dist, Measure measure) +{ + BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >)); + typedef typename Measure::distance_type Distance; + + return mean_geodesic(g, dist, measure, std::plus< Distance >()); +} + +template < typename Graph, typename DistanceMap > +inline double mean_geodesic(const Graph& g, DistanceMap dist) +{ + return mean_geodesic(g, dist, measure_mean_geodesic(g, dist)); +} + +template < typename T, typename Graph, typename DistanceMap > +inline T mean_geodesic(const Graph& g, DistanceMap dist) +{ + return mean_geodesic(g, dist, measure_mean_geodesic< T >(g, dist)); +} + +template < typename Graph, typename DistanceMatrixMap, typename GeodesicMap, + typename Measure > +inline typename property_traits< GeodesicMap >::value_type all_mean_geodesics( + const Graph& g, DistanceMatrixMap dist, GeodesicMap geo, Measure measure) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< DistanceMatrixMap, Vertex >)); + typedef + typename property_traits< DistanceMatrixMap >::value_type DistanceMap; + BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >)); + typedef typename Measure::result_type Result; + BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< GeodesicMap, Vertex >)); + BOOST_CONCEPT_ASSERT((NumericValueConcept< Result >)); + + // NOTE: We could compute the mean geodesic here by performing additional + // computations (i.e., adding and dividing). However, I don't really feel + // like fully genericizing the entire operation yet so I'm not going to. + + Result inf = numeric_values< Result >::infinity(); + Result sum = numeric_values< Result >::zero(); + VertexIterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + DistanceMap dm = get(dist, *i); + Result r = mean_geodesic(g, dm, measure); + put(geo, *i, r); + + // compute the sum along with geodesics + if (r == inf) + { + sum = inf; + } + else if (sum != inf) + { + sum += r; + } + } + + // return the average of averages. + return sum / Result(num_vertices(g)); +} + +template < typename Graph, typename DistanceMatrixMap, typename GeodesicMap > +inline typename property_traits< GeodesicMap >::value_type all_mean_geodesics( + const Graph& g, DistanceMatrixMap dist, GeodesicMap geo) +{ + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< DistanceMatrixMap, Vertex >)); + typedef + typename property_traits< DistanceMatrixMap >::value_type DistanceMap; + BOOST_CONCEPT_ASSERT((WritablePropertyMapConcept< GeodesicMap, Vertex >)); + typedef typename property_traits< GeodesicMap >::value_type Result; + + return all_mean_geodesics( + g, dist, geo, measure_mean_geodesic< Result >(g, DistanceMap())); +} + +template < typename Graph, typename GeodesicMap, typename Measure > +inline typename Measure::result_type small_world_distance( + const Graph& g, GeodesicMap geo, Measure measure) +{ + BOOST_CONCEPT_ASSERT((DistanceMeasureConcept< Measure, Graph >)); + typedef typename Measure::result_type Result; + + Result sum + = detail::combine_distances(g, geo, std::plus< Result >(), Result(0)); + return measure(sum, g); +} + +template < typename Graph, typename GeodesicMap > +inline typename property_traits< GeodesicMap >::value_type small_world_distance( + const Graph& g, GeodesicMap geo) +{ + return small_world_distance(g, geo, measure_graph_mean_geodesic(g, geo)); +} + +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/graph_archetypes.hpp b/contrib/restricted/boost/graph/include/boost/graph/graph_archetypes.hpp new file mode 100644 index 0000000000..428c3c5afd --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/graph_archetypes.hpp @@ -0,0 +1,326 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_ARCHETYPES_HPP +#define BOOST_GRAPH_ARCHETYPES_HPP + +#include <boost/property_map/property_map.hpp> +#include <boost/concept_archetype.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> + +namespace boost +{ // should use a different namespace for this + +namespace detail +{ + struct null_graph_archetype : public null_archetype<> + { + struct traversal_category + { + }; + }; +} + +//=========================================================================== +template < typename Vertex, typename Directed, typename ParallelCategory, + typename Base = detail::null_graph_archetype > +struct incidence_graph_archetype : public Base +{ + typedef typename Base::traversal_category base_trav_cat; + struct traversal_category : public incidence_graph_tag, public base_trav_cat + { + }; +#if 0 + typedef immutable_graph_tag mutability_category; +#endif + typedef Vertex vertex_descriptor; + typedef unsigned int degree_size_type; + typedef unsigned int vertices_size_type; + typedef unsigned int edges_size_type; + struct edge_descriptor + { + edge_descriptor() {} + edge_descriptor(const detail::dummy_constructor&) {} + bool operator==(const edge_descriptor&) const { return false; } + bool operator!=(const edge_descriptor&) const { return false; } + }; + typedef input_iterator_archetype< edge_descriptor > out_edge_iterator; + + typedef Directed directed_category; + typedef ParallelCategory edge_parallel_category; + + typedef void adjacency_iterator; + typedef void in_edge_iterator; + typedef void vertex_iterator; + typedef void edge_iterator; + + static vertex_descriptor null_vertex() { return vertex_descriptor(); } +}; +template < typename V, typename D, typename P, typename B > +V source( + const typename incidence_graph_archetype< V, D, P, B >::edge_descriptor&, + const incidence_graph_archetype< V, D, P, B >&) +{ + return V(static_object< detail::dummy_constructor >::get()); +} +template < typename V, typename D, typename P, typename B > +V target( + const typename incidence_graph_archetype< V, D, P, B >::edge_descriptor&, + const incidence_graph_archetype< V, D, P, B >&) +{ + return V(static_object< detail::dummy_constructor >::get()); +} + +template < typename V, typename D, typename P, typename B > +std::pair< typename incidence_graph_archetype< V, D, P, B >::out_edge_iterator, + typename incidence_graph_archetype< V, D, P, B >::out_edge_iterator > +out_edges(const V&, const incidence_graph_archetype< V, D, P, B >&) +{ + typedef typename incidence_graph_archetype< V, D, P, B >::out_edge_iterator + Iter; + return std::make_pair(Iter(), Iter()); +} + +template < typename V, typename D, typename P, typename B > +typename incidence_graph_archetype< V, D, P, B >::degree_size_type out_degree( + const V&, const incidence_graph_archetype< V, D, P, B >&) +{ + return 0; +} + +//=========================================================================== +template < typename Vertex, typename Directed, typename ParallelCategory, + typename Base = detail::null_graph_archetype > +struct adjacency_graph_archetype : public Base +{ + typedef typename Base::traversal_category base_trav_cat; + struct traversal_category : public adjacency_graph_tag, public base_trav_cat + { + }; + typedef Vertex vertex_descriptor; + typedef unsigned int degree_size_type; + typedef unsigned int vertices_size_type; + typedef unsigned int edges_size_type; + typedef void edge_descriptor; + typedef input_iterator_archetype< Vertex > adjacency_iterator; + + typedef Directed directed_category; + typedef ParallelCategory edge_parallel_category; + + typedef void in_edge_iterator; + typedef void out_edge_iterator; + typedef void vertex_iterator; + typedef void edge_iterator; + + static vertex_descriptor null_vertex() { return vertex_descriptor(); } +}; + +template < typename V, typename D, typename P, typename B > +std::pair< typename adjacency_graph_archetype< V, D, P, B >::adjacency_iterator, + typename adjacency_graph_archetype< V, D, P, B >::adjacency_iterator > +adjacent_vertices(const V&, const adjacency_graph_archetype< V, D, P, B >&) +{ + typedef typename adjacency_graph_archetype< V, D, P, B >::adjacency_iterator + Iter; + return std::make_pair(Iter(), Iter()); +} + +template < typename V, typename D, typename P, typename B > +typename adjacency_graph_archetype< V, D, P, B >::degree_size_type out_degree( + const V&, const adjacency_graph_archetype< V, D, P, B >&) +{ + return 0; +} + +//=========================================================================== +template < typename Vertex, typename Directed, typename ParallelCategory, + typename Base = detail::null_graph_archetype > +struct vertex_list_graph_archetype : public Base +{ + typedef incidence_graph_archetype< Vertex, Directed, ParallelCategory > + Incidence; + typedef adjacency_graph_archetype< Vertex, Directed, ParallelCategory > + Adjacency; + + typedef typename Base::traversal_category base_trav_cat; + struct traversal_category : public vertex_list_graph_tag, + public base_trav_cat + { + }; +#if 0 + typedef immutable_graph_tag mutability_category; +#endif + typedef Vertex vertex_descriptor; + typedef unsigned int degree_size_type; + typedef typename Incidence::edge_descriptor edge_descriptor; + typedef typename Incidence::out_edge_iterator out_edge_iterator; + typedef typename Adjacency::adjacency_iterator adjacency_iterator; + + typedef input_iterator_archetype< Vertex > vertex_iterator; + typedef unsigned int vertices_size_type; + typedef unsigned int edges_size_type; + + typedef Directed directed_category; + typedef ParallelCategory edge_parallel_category; + + typedef void in_edge_iterator; + typedef void edge_iterator; + + static vertex_descriptor null_vertex() { return vertex_descriptor(); } +}; + +template < typename V, typename D, typename P, typename B > +std::pair< typename vertex_list_graph_archetype< V, D, P, B >::vertex_iterator, + typename vertex_list_graph_archetype< V, D, P, B >::vertex_iterator > +vertices(const vertex_list_graph_archetype< V, D, P, B >&) +{ + typedef typename vertex_list_graph_archetype< V, D, P, B >::vertex_iterator + Iter; + return std::make_pair(Iter(), Iter()); +} + +template < typename V, typename D, typename P, typename B > +typename vertex_list_graph_archetype< V, D, P, B >::vertices_size_type +num_vertices(const vertex_list_graph_archetype< V, D, P, B >&) +{ + return 0; +} + +// ambiguously inherited from incidence graph and adjacency graph +template < typename V, typename D, typename P, typename B > +typename vertex_list_graph_archetype< V, D, P, B >::degree_size_type out_degree( + const V&, const vertex_list_graph_archetype< V, D, P, B >&) +{ + return 0; +} + +//=========================================================================== + +struct property_graph_archetype_tag +{ +}; + +template < typename GraphArchetype, typename Property, typename ValueArch > +struct property_graph_archetype : public GraphArchetype +{ + typedef property_graph_archetype_tag graph_tag; + typedef ValueArch vertex_property_type; + typedef ValueArch edge_property_type; +}; + +struct choose_edge_property_map_archetype +{ + template < typename Graph, typename Property, typename Tag > struct bind_ + { + typedef mutable_lvalue_property_map_archetype< + typename Graph::edge_descriptor, Property > + type; + typedef lvalue_property_map_archetype< typename Graph::edge_descriptor, + Property > + const_type; + }; +}; +template <> struct edge_property_selector< property_graph_archetype_tag > +{ + typedef choose_edge_property_map_archetype type; +}; + +struct choose_vertex_property_map_archetype +{ + template < typename Graph, typename Property, typename Tag > struct bind_ + { + typedef mutable_lvalue_property_map_archetype< + typename Graph::vertex_descriptor, Property > + type; + typedef lvalue_property_map_archetype< + typename Graph::vertex_descriptor, Property > + const_type; + }; +}; + +template <> struct vertex_property_selector< property_graph_archetype_tag > +{ + typedef choose_vertex_property_map_archetype type; +}; + +template < typename G, typename P, typename V > +typename property_map< property_graph_archetype< G, P, V >, P >::type get( + P, property_graph_archetype< G, P, V >&) +{ + typename property_map< property_graph_archetype< G, P, V >, P >::type pmap; + return pmap; +} + +template < typename G, typename P, typename V > +typename property_map< property_graph_archetype< G, P, V >, P >::const_type get( + P, const property_graph_archetype< G, P, V >&) +{ + typename property_map< property_graph_archetype< G, P, V >, P >::const_type + pmap; + return pmap; +} + +template < typename G, typename P, typename K, typename V > +typename property_traits< typename property_map< + property_graph_archetype< G, P, V >, P >::const_type >::value_type +get(P p, const property_graph_archetype< G, P, V >& g, K k) +{ + return get(get(p, g), k); +} + +template < typename G, typename P, typename V, typename Key > +void put( + P p, property_graph_archetype< G, P, V >& g, const Key& key, const V& value) +{ + typedef typename boost::property_map< property_graph_archetype< G, P, V >, + P >::type Map; + Map pmap = get(p, g); + put(pmap, key, value); +} + +struct color_value_archetype +{ + color_value_archetype() {} + color_value_archetype(detail::dummy_constructor) {} + bool operator==(const color_value_archetype&) const { return true; } + bool operator!=(const color_value_archetype&) const { return true; } +}; +template <> struct color_traits< color_value_archetype > +{ + static color_value_archetype white() + { + return color_value_archetype( + static_object< detail::dummy_constructor >::get()); + } + static color_value_archetype gray() + { + return color_value_archetype( + static_object< detail::dummy_constructor >::get()); + } + static color_value_archetype black() + { + return color_value_archetype( + static_object< detail::dummy_constructor >::get()); + } +}; + +template < typename T > class buffer_archetype +{ +public: + void push(const T&) {} + void pop() {} + T& top() { return static_object< T >::get(); } + const T& top() const { return static_object< T >::get(); } + bool empty() const { return true; } +}; + +} // namespace boost + +#endif // BOOST_GRAPH_ARCHETYPES_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/graph_as_tree.hpp b/contrib/restricted/boost/graph/include/boost/graph/graph_as_tree.hpp new file mode 100644 index 0000000000..ce6057c981 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/graph_as_tree.hpp @@ -0,0 +1,156 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_GRAPH_AS_TREE_HPP +#define BOOST_GRAPH_GRAPH_AS_TREE_HPP + +#include <vector> +#include <boost/config.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/tree_traits.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/breadth_first_search.hpp> +#include <boost/graph/visitors.hpp> + +namespace boost +{ + +template < class Graph, class Node, class ChIt, class Derived > +class graph_as_tree_base +{ + typedef Derived Tree; + +public: + typedef Node node_descriptor; + typedef ChIt children_iterator; + + graph_as_tree_base(Graph& g, Node root) : _g(g), _root(root) {} + + friend Node root(const Tree& t) { return t._root; } + + template < class N > + friend std::pair< ChIt, ChIt > children(N n, const Tree& t) + { + return adjacent_vertices(n, t._g); + } + + template < class N > friend Node parent(N n, const Tree& t) + { + return boost::get(t.parent_pa(), n); + } + + Graph& _g; + Node _root; +}; + +struct graph_as_tree_tag +{ +}; + +template < class Graph, class ParentMap, + class Node = typename graph_traits< Graph >::vertex_descriptor, + class ChIt = typename graph_traits< Graph >::adjacency_iterator > +class graph_as_tree : public graph_as_tree_base< Graph, Node, ChIt, + graph_as_tree< Graph, ParentMap, Node, ChIt > > +{ + typedef graph_as_tree self; + typedef graph_as_tree_base< Graph, Node, ChIt, self > super; + +public: + graph_as_tree(Graph& g, Node root) : super(g, root) {} + + graph_as_tree(Graph& g, Node root, ParentMap p) : super(g, root), _p(p) + { + breadth_first_search(g, root, + visitor(make_bfs_visitor( + record_predecessors(p, boost::on_tree_edge())))); + } + ParentMap parent_pa() const { return _p; } + typedef graph_as_tree_tag graph_tag; // for property_map +protected: + ParentMap _p; +}; + +namespace detail +{ + + struct graph_as_tree_vertex_property_selector + { + template < typename GraphAsTree, typename Property, typename Tag > + struct bind_ + { + typedef typename GraphAsTree::base_type Graph; + typedef property_map< Graph, Tag > PMap; + typedef typename PMap::type type; + typedef typename PMap::const_type const_type; + }; + }; + + struct graph_as_tree_edge_property_selector + { + template < typename GraphAsTree, typename Property, typename Tag > + struct bind_ + { + typedef typename GraphAsTree::base_type Graph; + typedef property_map< Graph, Tag > PMap; + typedef typename PMap::type type; + typedef typename PMap::const_type const_type; + }; + }; + +} // namespace detail + +template <> struct vertex_property_selector< graph_as_tree_tag > +{ + typedef detail::graph_as_tree_vertex_property_selector type; +}; + +template <> struct edge_property_selector< graph_as_tree_tag > +{ + typedef detail::graph_as_tree_edge_property_selector type; +}; + +template < typename Graph, typename P, typename N, typename C, + typename Property > +typename property_map< Graph, Property >::type get( + Property p, graph_as_tree< Graph, P, N, C >& g) +{ + return get(p, g._g); +} + +template < typename Graph, typename P, typename N, typename C, + typename Property > +typename property_map< Graph, Property >::const_type get( + Property p, const graph_as_tree< Graph, P, N, C >& g) +{ + const Graph& gref = g._g; // in case GRef is non-const + return get(p, gref); +} + +template < typename Graph, typename P, typename N, typename C, + typename Property, typename Key > +typename property_traits< + typename property_map< Graph, Property >::const_type >::value_type +get(Property p, const graph_as_tree< Graph, P, N, C >& g, const Key& k) +{ + return get(p, g._g, k); +} + +template < typename Graph, typename P, typename N, typename C, + typename Property, typename Key, typename Value > +void put(Property p, const graph_as_tree< Graph, P, N, C >& g, const Key& k, + const Value& val) +{ + put(p, g._g, k, val); +} + +} // namespace boost + +#endif // BOOST_GRAPH_GRAPH_AS_TREE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/graph_stats.hpp b/contrib/restricted/boost/graph/include/boost/graph/graph_stats.hpp new file mode 100644 index 0000000000..aff1f3550c --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/graph_stats.hpp @@ -0,0 +1,148 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Alex Breuer +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_GRAPH_STATS_HPP +#define BOOST_GRAPH_GRAPH_STATS_HPP + +#include <map> +#include <list> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/properties.hpp> +#include <boost/assert.hpp> + +namespace boost +{ +namespace graph +{ + + template < typename Graph > struct sort_edge_by_origin + { + public: + typedef typename graph_traits< Graph >::edge_descriptor edge_type; + + explicit sort_edge_by_origin(Graph& g) : g(g) {} + + inline bool operator()(edge_type a, edge_type b) + { + return source(a, g) == source(b, g) ? target(a, g) < target(b, g) + : source(a, g) < source(b, g); + } + + private: + Graph& g; + }; + + template < typename Graph > struct equal_edge + { + public: + typedef typename graph_traits< Graph >::edge_descriptor edge_type; + + explicit equal_edge(Graph& g) : g(g) {} + + inline bool operator()(edge_type a, edge_type b) + { + return source(a, g) == source(b, g) && target(a, g) == target(b, g); + } + + private: + Graph& g; + }; + + template < typename Graph > unsigned long num_dup_edges(Graph& g) + { + typedef typename graph_traits< Graph >::edge_iterator e_iterator_type; + typedef typename graph_traits< Graph >::edge_descriptor edge_type; + + std::list< edge_type > all_edges; + + BGL_FORALL_EDGES_T(e, g, Graph) { all_edges.push_back(e); } + + sort_edge_by_origin< Graph > cmp1(g); + all_edges.sort(cmp1); + equal_edge< Graph > cmp2(g); + all_edges.unique(cmp2); + + return num_edges(g) - all_edges.size(); + } + + template < typename Graph > + std::map< unsigned long, unsigned long > dup_edge_dist(Graph& g) + { + std::map< unsigned long, unsigned long > dist; + typedef + typename graph_traits< Graph >::adjacency_iterator a_iterator_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_type; + + BGL_FORALL_VERTICES_T(v, g, Graph) + { + std::list< vertex_type > front_neighbors; + a_iterator_type a_iter, a_end; + for (boost::tie(a_iter, a_end) = adjacent_vertices(v, g); + a_iter != a_end; ++a_iter) + { + front_neighbors.push_back(*a_iter); + } + + front_neighbors.sort(); + front_neighbors.unique(); + dist[out_degree(v, g) - front_neighbors.size()] += 1; + } + return dist; + } + + template < typename Graph > + std::map< unsigned long, unsigned long > degree_dist(Graph& g) + { + std::map< unsigned long, unsigned long > dist; + typedef + typename graph_traits< Graph >::adjacency_iterator a_iterator_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_type; + + BGL_FORALL_VERTICES_T(v, g, Graph) { dist[out_degree(v, g)] += 1; } + + return dist; + } + + template < typename Graph > + std::map< unsigned long, double > weight_degree_dist(Graph& g) + { + std::map< unsigned long, double > dist, n; + typedef + typename graph_traits< Graph >::adjacency_iterator a_iterator_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_type; + typedef typename property_map< Graph, edge_weight_t >::const_type + edge_map_type; + typedef typename property_traits< edge_map_type >::value_type + edge_weight_type; + + typename property_map< Graph, edge_weight_t >::type em + = get(edge_weight, g); + + BGL_FORALL_VERTICES_T(v, g, Graph) + { + edge_weight_type tmp = 0; + BGL_FORALL_OUTEDGES_T(v, e, g, Graph) { tmp += em[e]; } + n[out_degree(v, g)] += 1.; + dist[out_degree(v, g)] += tmp; + } + + for (std::map< unsigned long, double >::iterator iter = dist.begin(); + iter != dist.end(); ++iter) + { + BOOST_ASSERT(n[iter->first] != 0); + dist[iter->first] /= n[iter->first]; + } + + return dist; + } + +} +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/graph_utility.hpp b/contrib/restricted/boost/graph/include/boost/graph/graph_utility.hpp new file mode 100644 index 0000000000..4e5ef141ac --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/graph_utility.hpp @@ -0,0 +1,488 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_UTILITY_HPP +#define BOOST_GRAPH_UTILITY_HPP + +#include <stdlib.h> +#include <iostream> +#include <algorithm> +#include <assert.h> +#include <boost/config.hpp> +#include <boost/tuple/tuple.hpp> + +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/properties.hpp> +#include <boost/pending/container_traits.hpp> +#include <boost/graph/depth_first_search.hpp> +// iota moved to detail/algorithm.hpp +#include <boost/detail/algorithm.hpp> + +namespace boost +{ + +// Provide an undirected graph interface alternative to the +// the source() and target() edge functions. +template < class UndirectedGraph > +inline std::pair< typename graph_traits< UndirectedGraph >::vertex_descriptor, + typename graph_traits< UndirectedGraph >::vertex_descriptor > +incident(typename graph_traits< UndirectedGraph >::edge_descriptor e, + UndirectedGraph& g) +{ + return std::make_pair(source(e, g), target(e, g)); +} + +// Provide an undirected graph interface alternative +// to the out_edges() function. +template < class Graph > +inline std::pair< typename graph_traits< Graph >::out_edge_iterator, + typename graph_traits< Graph >::out_edge_iterator > +incident_edges(typename graph_traits< Graph >::vertex_descriptor u, Graph& g) +{ + return out_edges(u, g); +} + +template < class Graph > +inline typename graph_traits< Graph >::vertex_descriptor opposite( + typename graph_traits< Graph >::edge_descriptor e, + typename graph_traits< Graph >::vertex_descriptor v, const Graph& g) +{ + typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + if (v == source(e, g)) + return target(e, g); + else if (v == target(e, g)) + return source(e, g); + else + return vertex_descriptor(); +} + +//=========================================================================== +// Some handy predicates + +template < typename Vertex, typename Graph > struct incident_from_predicate +{ + incident_from_predicate(Vertex u, const Graph& g) : m_u(u), m_g(g) {} + template < class Edge > bool operator()(const Edge& e) const + { + return source(e, m_g) == m_u; + } + Vertex m_u; + const Graph& m_g; +}; +template < typename Vertex, typename Graph > +inline incident_from_predicate< Vertex, Graph > incident_from( + Vertex u, const Graph& g) +{ + return incident_from_predicate< Vertex, Graph >(u, g); +} + +template < typename Vertex, typename Graph > struct incident_to_predicate +{ + incident_to_predicate(Vertex u, const Graph& g) : m_u(u), m_g(g) {} + template < class Edge > bool operator()(const Edge& e) const + { + return target(e, m_g) == m_u; + } + Vertex m_u; + const Graph& m_g; +}; +template < typename Vertex, typename Graph > +inline incident_to_predicate< Vertex, Graph > incident_to( + Vertex u, const Graph& g) +{ + return incident_to_predicate< Vertex, Graph >(u, g); +} + +template < typename Vertex, typename Graph > struct incident_on_predicate +{ + incident_on_predicate(Vertex u, const Graph& g) : m_u(u), m_g(g) {} + template < class Edge > bool operator()(const Edge& e) const + { + return source(e, m_g) == m_u || target(e, m_g) == m_u; + } + Vertex m_u; + const Graph& m_g; +}; +template < typename Vertex, typename Graph > +inline incident_on_predicate< Vertex, Graph > incident_on( + Vertex u, const Graph& g) +{ + return incident_on_predicate< Vertex, Graph >(u, g); +} + +template < typename Vertex, typename Graph > struct connects_predicate +{ + connects_predicate(Vertex u, Vertex v, const Graph& g) + : m_u(u), m_v(v), m_g(g) + { + } + template < class Edge > bool operator()(const Edge& e) const + { + if (is_directed(m_g)) + return source(e, m_g) == m_u && target(e, m_g) == m_v; + else + return (source(e, m_g) == m_u && target(e, m_g) == m_v) + || (source(e, m_g) == m_v && target(e, m_g) == m_u); + } + Vertex m_u, m_v; + const Graph& m_g; +}; +template < typename Vertex, typename Graph > +inline connects_predicate< Vertex, Graph > connects( + Vertex u, Vertex v, const Graph& g) +{ + return connects_predicate< Vertex, Graph >(u, v, g); +} + +// Need to convert all of these printing functions to take an ostream object +// -JGS + +template < class IncidenceGraph, class Name > +void print_in_edges( + const IncidenceGraph& G, Name name, std::ostream& os = std::cout) +{ + typename graph_traits< IncidenceGraph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + { + os << get(name, *ui) << " <-- "; + typename graph_traits< IncidenceGraph >::in_edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = in_edges(*ui, G); ei != ei_end; ++ei) + os << get(name, source(*ei, G)) << " "; + os << '\n'; + } +} + +template < class IncidenceGraph, class Name > +void print_graph_dispatch(const IncidenceGraph& G, Name name, directed_tag, + std::ostream& os = std::cout) +{ + typename graph_traits< IncidenceGraph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + { + os << get(name, *ui) << " --> "; + typename graph_traits< IncidenceGraph >::out_edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(*ui, G); ei != ei_end; ++ei) + os << get(name, target(*ei, G)) << " "; + os << '\n'; + } +} +template < class IncidenceGraph, class Name > +void print_graph_dispatch(const IncidenceGraph& G, Name name, undirected_tag, + std::ostream& os = std::cout) +{ + typename graph_traits< IncidenceGraph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + { + os << get(name, *ui) << " <--> "; + typename graph_traits< IncidenceGraph >::out_edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(*ui, G); ei != ei_end; ++ei) + os << get(name, target(*ei, G)) << " "; + os << '\n'; + } +} +template < class IncidenceGraph, class Name > +void print_graph( + const IncidenceGraph& G, Name name, std::ostream& os = std::cout) +{ + typedef typename graph_traits< IncidenceGraph >::directed_category Cat; + print_graph_dispatch(G, name, Cat(), os); +} +template < class IncidenceGraph > +void print_graph(const IncidenceGraph& G, std::ostream& os = std::cout) +{ + print_graph(G, get(vertex_index, G), os); +} + +template < class EdgeListGraph, class Name > +void print_edges( + const EdgeListGraph& G, Name name, std::ostream& os = std::cout) +{ + typename graph_traits< EdgeListGraph >::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) + os << "(" << get(name, source(*ei, G)) << "," + << get(name, target(*ei, G)) << ") "; + os << '\n'; +} + +template < class EdgeListGraph, class VertexName, class EdgeName > +void print_edges2(const EdgeListGraph& G, VertexName vname, EdgeName ename, + std::ostream& os = std::cout) +{ + typename graph_traits< EdgeListGraph >::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = edges(G); ei != ei_end; ++ei) + os << get(ename, *ei) << "(" << get(vname, source(*ei, G)) << "," + << get(vname, target(*ei, G)) << ") "; + os << '\n'; +} + +template < class VertexListGraph, class Name > +void print_vertices( + const VertexListGraph& G, Name name, std::ostream& os = std::cout) +{ + typename graph_traits< VertexListGraph >::vertex_iterator vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(G); vi != vi_end; ++vi) + os << get(name, *vi) << " "; + os << '\n'; +} + +template < class Graph, class Vertex > +bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, bidirectional_tag) +{ + typename graph_traits< Graph >::adjacency_iterator vi, viend, adj_found; + boost::tie(vi, viend) = adjacent_vertices(a, g); + adj_found = std::find(vi, viend, b); + if (adj_found == viend) + return false; + + typename graph_traits< Graph >::out_edge_iterator oi, oiend, out_found; + boost::tie(oi, oiend) = out_edges(a, g); + out_found = std::find_if(oi, oiend, incident_to(b, g)); + if (out_found == oiend) + return false; + + typename graph_traits< Graph >::in_edge_iterator ii, iiend, in_found; + boost::tie(ii, iiend) = in_edges(b, g); + in_found = std::find_if(ii, iiend, incident_from(a, g)); + if (in_found == iiend) + return false; + + return true; +} +template < class Graph, class Vertex > +bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, directed_tag) +{ + typename graph_traits< Graph >::adjacency_iterator vi, viend, found; + boost::tie(vi, viend) = adjacent_vertices(a, g); + found = std::find(vi, viend, b); + if (found == viend) + return false; + + typename graph_traits< Graph >::out_edge_iterator oi, oiend, out_found; + boost::tie(oi, oiend) = out_edges(a, g); + + out_found = std::find_if(oi, oiend, incident_to(b, g)); + if (out_found == oiend) + return false; + return true; +} +template < class Graph, class Vertex > +bool is_adj_dispatch(Graph& g, Vertex a, Vertex b, undirected_tag) +{ + return is_adj_dispatch(g, a, b, directed_tag()); +} + +template < class Graph, class Vertex > +bool is_adjacent(Graph& g, Vertex a, Vertex b) +{ + typedef typename graph_traits< Graph >::directed_category Cat; + return is_adj_dispatch(g, a, b, Cat()); +} + +template < class Graph, class Edge > bool in_edge_set(Graph& g, Edge e) +{ + typename Graph::edge_iterator ei, ei_end, found; + boost::tie(ei, ei_end) = edges(g); + found = std::find(ei, ei_end, e); + return found != ei_end; +} + +template < class Graph, class Vertex > bool in_vertex_set(Graph& g, Vertex v) +{ + typename Graph::vertex_iterator vi, vi_end, found; + boost::tie(vi, vi_end) = vertices(g); + found = std::find(vi, vi_end, v); + return found != vi_end; +} + +template < class Graph, class Vertex > +bool in_edge_set(Graph& g, Vertex u, Vertex v) +{ + typename Graph::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + if (source(*ei, g) == u && target(*ei, g) == v) + return true; + return false; +} + +// is x a descendant of y? +template < typename ParentMap > +inline bool is_descendant(typename property_traits< ParentMap >::value_type x, + typename property_traits< ParentMap >::value_type y, ParentMap parent) +{ + if (get(parent, x) == x) // x is the root of the tree + return false; + else if (get(parent, x) == y) + return true; + else + return is_descendant(get(parent, x), y, parent); +} + +// is y reachable from x? +template < typename IncidenceGraph, typename VertexColorMap > +inline bool is_reachable( + typename graph_traits< IncidenceGraph >::vertex_descriptor x, + typename graph_traits< IncidenceGraph >::vertex_descriptor y, + const IncidenceGraph& g, + VertexColorMap color) // should start out white for every vertex +{ + typedef typename property_traits< VertexColorMap >::value_type ColorValue; + dfs_visitor<> vis; + depth_first_visit(g, x, vis, color); + return get(color, y) != color_traits< ColorValue >::white(); +} + +// Is the undirected graph connected? +// Is the directed graph strongly connected? +template < typename VertexListGraph, typename VertexColorMap > +inline bool is_connected(const VertexListGraph& g, VertexColorMap color) +{ + typedef typename property_traits< VertexColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + typename graph_traits< VertexListGraph >::vertex_iterator ui, ui_end, vi, + vi_end, ci, ci_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + if (*ui != *vi) + { + for (boost::tie(ci, ci_end) = vertices(g); ci != ci_end; ++ci) + put(color, *ci, Color::white()); + if (!is_reachable(*ui, *vi, g, color)) + return false; + } + return true; +} + +template < typename Graph > +bool is_self_loop( + typename graph_traits< Graph >::edge_descriptor e, const Graph& g) +{ + return source(e, g) == target(e, g); +} + +template < class T1, class T2 > +std::pair< T1, T2 > make_list(const T1& t1, const T2& t2) +{ + return std::make_pair(t1, t2); +} + +template < class T1, class T2, class T3 > +std::pair< T1, std::pair< T2, T3 > > make_list( + const T1& t1, const T2& t2, const T3& t3) +{ + return std::make_pair(t1, std::make_pair(t2, t3)); +} + +template < class T1, class T2, class T3, class T4 > +std::pair< T1, std::pair< T2, std::pair< T3, T4 > > > make_list( + const T1& t1, const T2& t2, const T3& t3, const T4& t4) +{ + return std::make_pair(t1, std::make_pair(t2, std::make_pair(t3, t4))); +} + +template < class T1, class T2, class T3, class T4, class T5 > +std::pair< T1, std::pair< T2, std::pair< T3, std::pair< T4, T5 > > > > +make_list(const T1& t1, const T2& t2, const T3& t3, const T4& t4, const T5& t5) +{ + return std::make_pair( + t1, std::make_pair(t2, std::make_pair(t3, std::make_pair(t4, t5)))); +} + +namespace graph +{ + + // Functor for remove_parallel_edges: edge property of the removed edge is + // added to the remaining + template < typename EdgeProperty > struct add_removed_edge_property + { + add_removed_edge_property(EdgeProperty ep) : ep(ep) {} + + template < typename Edge > void operator()(Edge stay, Edge away) + { + put(ep, stay, get(ep, stay) + get(ep, away)); + } + EdgeProperty ep; + }; + + // Same as above: edge property is capacity here + template < typename Graph > + struct add_removed_edge_capacity + : add_removed_edge_property< + typename property_map< Graph, edge_capacity_t >::type > + { + typedef add_removed_edge_property< + typename property_map< Graph, edge_capacity_t >::type > + base; + add_removed_edge_capacity(Graph& g) : base(get(edge_capacity, g)) {} + }; + + template < typename Graph > bool has_no_vertices(const Graph& g) + { + typedef typename boost::graph_traits< Graph >::vertex_iterator vi; + std::pair< vi, vi > p = vertices(g); + return (p.first == p.second); + } + + template < typename Graph > bool has_no_edges(const Graph& g) + { + typedef typename boost::graph_traits< Graph >::edge_iterator ei; + std::pair< ei, ei > p = edges(g); + return (p.first == p.second); + } + + template < typename Graph > + bool has_no_out_edges( + const typename boost::graph_traits< Graph >::vertex_descriptor& v, + const Graph& g) + { + typedef typename boost::graph_traits< Graph >::out_edge_iterator ei; + std::pair< ei, ei > p = out_edges(v, g); + return (p.first == p.second); + } + +} // namespace graph + +template < class PropertyIn, class PropertyOut, class Graph > +void copy_vertex_property(PropertyIn p_in, PropertyOut p_out, Graph& g) +{ + BGL_FORALL_VERTICES_T(u, g, Graph) + put(p_out, u, get(p_in, g)); +} + +template < class PropertyIn, class PropertyOut, class Graph > +void copy_edge_property(PropertyIn p_in, PropertyOut p_out, Graph& g) +{ + BGL_FORALL_EDGES_T(e, g, Graph) + put(p_out, e, get(p_in, g)); +} + +// Return true if property_map1 and property_map2 differ +// for any of the vertices in graph. +template < typename PropertyMapFirst, typename PropertyMapSecond, + typename Graph > +bool are_property_maps_different(const PropertyMapFirst property_map1, + const PropertyMapSecond property_map2, const Graph& graph) +{ + + BGL_FORALL_VERTICES_T(vertex, graph, Graph) + { + if (get(property_map1, vertex) != get(property_map2, vertex)) + { + + return (true); + } + } + + return (false); +} + +} /* namespace boost */ + +#endif /* BOOST_GRAPH_UTILITY_HPP*/ diff --git a/contrib/restricted/boost/graph/include/boost/graph/grid_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/grid_graph.hpp new file mode 100644 index 0000000000..bdcbc6f4d1 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/grid_graph.hpp @@ -0,0 +1,1059 @@ +//======================================================================= +// Copyright 2009 Trustees of Indiana University. +// Authors: Michael Hansen, Andrew Lumsdaine +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_GRID_GRAPH_HPP +#define BOOST_GRAPH_GRID_GRAPH_HPP + +#include <cmath> +#include <functional> +#include <numeric> + +#include <boost/array.hpp> +#include <boost/limits.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/iterator/transform_iterator.hpp> +#include <boost/property_map/property_map.hpp> + +#define BOOST_GRID_GRAPH_TEMPLATE_PARAMS \ + std::size_t DimensionsT, typename VertexIndexT, typename EdgeIndexT + +#define BOOST_GRID_GRAPH_TYPE \ + grid_graph< DimensionsT, VertexIndexT, EdgeIndexT > + +#define BOOST_GRID_GRAPH_TRAITS_T typename graph_traits< BOOST_GRID_GRAPH_TYPE > + +namespace boost +{ + +// Class prototype for grid_graph +template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS > class grid_graph; + +//=================== +// Index Property Map +//=================== + +template < typename Graph, typename Descriptor, typename Index > +struct grid_graph_index_map +{ +public: + typedef Index value_type; + typedef Index reference_type; + typedef reference_type reference; + typedef Descriptor key_type; + typedef readable_property_map_tag category; + + grid_graph_index_map() {} + + grid_graph_index_map(const Graph& graph) : m_graph(&graph) {} + + value_type operator[](key_type key) const + { + return (m_graph->index_of(key)); + } + + friend inline Index get( + const grid_graph_index_map< Graph, Descriptor, Index >& index_map, + const typename grid_graph_index_map< Graph, Descriptor, + Index >::key_type& key) + { + return (index_map[key]); + } + +protected: + const Graph* m_graph; +}; + +template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS > +struct property_map< BOOST_GRID_GRAPH_TYPE, vertex_index_t > +{ + typedef grid_graph_index_map< BOOST_GRID_GRAPH_TYPE, + BOOST_GRID_GRAPH_TRAITS_T::vertex_descriptor, + BOOST_GRID_GRAPH_TRAITS_T::vertices_size_type > + type; + typedef type const_type; +}; + +template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS > +struct property_map< BOOST_GRID_GRAPH_TYPE, edge_index_t > +{ + typedef grid_graph_index_map< BOOST_GRID_GRAPH_TYPE, + BOOST_GRID_GRAPH_TRAITS_T::edge_descriptor, + BOOST_GRID_GRAPH_TRAITS_T::edges_size_type > + type; + typedef type const_type; +}; + +//========================== +// Reverse Edge Property Map +//========================== + +template < typename Descriptor > struct grid_graph_reverse_edge_map +{ +public: + typedef Descriptor value_type; + typedef Descriptor reference_type; + typedef reference_type reference; + typedef Descriptor key_type; + typedef readable_property_map_tag category; + + grid_graph_reverse_edge_map() {} + + value_type operator[](const key_type& key) const + { + return (value_type(key.second, key.first)); + } + + friend inline Descriptor get( + const grid_graph_reverse_edge_map< Descriptor >& rev_map, + const typename grid_graph_reverse_edge_map< Descriptor >::key_type& key) + { + return (rev_map[key]); + } +}; + +template < BOOST_GRID_GRAPH_TEMPLATE_PARAMS > +struct property_map< BOOST_GRID_GRAPH_TYPE, edge_reverse_t > +{ + typedef grid_graph_reverse_edge_map< + BOOST_GRID_GRAPH_TRAITS_T::edge_descriptor > + type; + typedef type const_type; +}; + +//================= +// Function Objects +//================= + +namespace detail +{ + + // vertex_at + template < typename Graph > struct grid_graph_vertex_at + { + + typedef typename graph_traits< Graph >::vertex_descriptor result_type; + + grid_graph_vertex_at() : m_graph(0) {} + + grid_graph_vertex_at(const Graph* graph) : m_graph(graph) {} + + result_type operator()( + typename graph_traits< Graph >::vertices_size_type vertex_index) + const + { + return (vertex(vertex_index, *m_graph)); + } + + private: + const Graph* m_graph; + }; + + // out_edge_at + template < typename Graph > struct grid_graph_out_edge_at + { + + private: + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + + public: + typedef typename graph_traits< Graph >::edge_descriptor result_type; + + grid_graph_out_edge_at() : m_vertex(), m_graph(0) {} + + grid_graph_out_edge_at( + vertex_descriptor source_vertex, const Graph* graph) + : m_vertex(source_vertex), m_graph(graph) + { + } + + result_type operator()( + typename graph_traits< Graph >::degree_size_type out_edge_index) + const + { + return (out_edge_at(m_vertex, out_edge_index, *m_graph)); + } + + private: + vertex_descriptor m_vertex; + const Graph* m_graph; + }; + + // in_edge_at + template < typename Graph > struct grid_graph_in_edge_at + { + + private: + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + + public: + typedef typename graph_traits< Graph >::edge_descriptor result_type; + + grid_graph_in_edge_at() : m_vertex(), m_graph(0) {} + + grid_graph_in_edge_at( + vertex_descriptor target_vertex, const Graph* graph) + : m_vertex(target_vertex), m_graph(graph) + { + } + + result_type operator()( + typename graph_traits< Graph >::degree_size_type in_edge_index) + const + { + return (in_edge_at(m_vertex, in_edge_index, *m_graph)); + } + + private: + vertex_descriptor m_vertex; + const Graph* m_graph; + }; + + // edge_at + template < typename Graph > struct grid_graph_edge_at + { + + typedef typename graph_traits< Graph >::edge_descriptor result_type; + + grid_graph_edge_at() : m_graph(0) {} + + grid_graph_edge_at(const Graph* graph) : m_graph(graph) {} + + result_type operator()( + typename graph_traits< Graph >::edges_size_type edge_index) const + { + return (edge_at(edge_index, *m_graph)); + } + + private: + const Graph* m_graph; + }; + + // adjacent_vertex_at + template < typename Graph > struct grid_graph_adjacent_vertex_at + { + + public: + typedef typename graph_traits< Graph >::vertex_descriptor result_type; + + grid_graph_adjacent_vertex_at( + result_type source_vertex, const Graph* graph) + : m_vertex(source_vertex), m_graph(graph) + { + } + + result_type operator()( + typename graph_traits< Graph >::degree_size_type adjacent_index) + const + { + return (target( + out_edge_at(m_vertex, adjacent_index, *m_graph), *m_graph)); + } + + private: + result_type m_vertex; + const Graph* m_graph; + }; + +} // namespace detail + +//=========== +// Grid Graph +//=========== + +template < std::size_t Dimensions, typename VertexIndex = std::size_t, + typename EdgeIndex = VertexIndex > +class grid_graph +{ + +private: + typedef boost::array< bool, Dimensions > WrapDimensionArray; + grid_graph() {}; + +public: + typedef grid_graph< Dimensions, VertexIndex, EdgeIndex > type; + + // sizes + typedef VertexIndex vertices_size_type; + typedef EdgeIndex edges_size_type; + typedef EdgeIndex degree_size_type; + + // descriptors + typedef boost::array< VertexIndex, Dimensions > vertex_descriptor; + typedef std::pair< vertex_descriptor, vertex_descriptor > edge_descriptor; + + // vertex_iterator + typedef counting_iterator< vertices_size_type > vertex_index_iterator; + typedef detail::grid_graph_vertex_at< type > vertex_function; + typedef transform_iterator< vertex_function, vertex_index_iterator > + vertex_iterator; + + // edge_iterator + typedef counting_iterator< edges_size_type > edge_index_iterator; + typedef detail::grid_graph_edge_at< type > edge_function; + typedef transform_iterator< edge_function, edge_index_iterator > + edge_iterator; + + // out_edge_iterator + typedef counting_iterator< degree_size_type > degree_iterator; + typedef detail::grid_graph_out_edge_at< type > out_edge_function; + typedef transform_iterator< out_edge_function, degree_iterator > + out_edge_iterator; + + // in_edge_iterator + typedef detail::grid_graph_in_edge_at< type > in_edge_function; + typedef transform_iterator< in_edge_function, degree_iterator > + in_edge_iterator; + + // adjacency_iterator + typedef detail::grid_graph_adjacent_vertex_at< type > + adjacent_vertex_function; + typedef transform_iterator< adjacent_vertex_function, degree_iterator > + adjacency_iterator; + + // categories + typedef directed_tag directed_category; + typedef disallow_parallel_edge_tag edge_parallel_category; + struct traversal_category : virtual public incidence_graph_tag, + virtual public adjacency_graph_tag, + virtual public vertex_list_graph_tag, + virtual public edge_list_graph_tag, + virtual public bidirectional_graph_tag, + virtual public adjacency_matrix_tag + { + }; + + static inline vertex_descriptor null_vertex() + { + vertex_descriptor maxed_out_vertex; + std::fill(maxed_out_vertex.begin(), maxed_out_vertex.end(), + (std::numeric_limits< vertices_size_type >::max)()); + + return (maxed_out_vertex); + } + + // Constructor that defaults to no wrapping for all dimensions. + grid_graph(vertex_descriptor dimension_lengths) + : m_dimension_lengths(dimension_lengths) + { + + std::fill(m_wrap_dimension.begin(), m_wrap_dimension.end(), false); + + precalculate(); + } + + // Constructor that allows for wrapping to be specified for all + // dimensions at once. + grid_graph(vertex_descriptor dimension_lengths, bool wrap_all_dimensions) + : m_dimension_lengths(dimension_lengths) + { + + std::fill(m_wrap_dimension.begin(), m_wrap_dimension.end(), + wrap_all_dimensions); + + precalculate(); + } + + // Constructor that allows for individual dimension wrapping to be + // specified. + grid_graph( + vertex_descriptor dimension_lengths, WrapDimensionArray wrap_dimension) + : m_dimension_lengths(dimension_lengths), m_wrap_dimension(wrap_dimension) + { + + precalculate(); + } + + // Returns the number of dimensions in the graph + inline std::size_t dimensions() const { return (Dimensions); } + + // Returns the length of dimension [dimension_index] + inline vertices_size_type length(std::size_t dimension) const + { + return (m_dimension_lengths[dimension]); + } + + // Returns a value indicating if dimension [dimension_index] wraps + inline bool wrapped(std::size_t dimension) const + { + return (m_wrap_dimension[dimension]); + } + + // Gets the vertex that is [distance] units ahead of [vertex] in + // dimension [dimension_index]. + vertex_descriptor next(vertex_descriptor vertex, + std::size_t dimension_index, vertices_size_type distance = 1) const + { + + vertices_size_type new_position = vertex[dimension_index] + distance; + + if (wrapped(dimension_index)) + { + new_position %= length(dimension_index); + } + else + { + // Stop at the end of this dimension if necessary. + new_position = (std::min)( + new_position, vertices_size_type(length(dimension_index) - 1)); + } + + vertex[dimension_index] = new_position; + + return (vertex); + } + + // Gets the vertex that is [distance] units behind [vertex] in + // dimension [dimension_index]. + vertex_descriptor previous(vertex_descriptor vertex, + std::size_t dimension_index, vertices_size_type distance = 1) const + { + + // We're assuming that vertices_size_type is unsigned, so we + // need to be careful about the math. + vertex[dimension_index] = (distance > vertex[dimension_index]) + ? (wrapped(dimension_index) ? (length(dimension_index) + - (distance % length(dimension_index))) + : 0) + : vertex[dimension_index] - distance; + + return (vertex); + } + +protected: + // Returns the number of vertices in the graph + inline vertices_size_type num_vertices() const { return (m_num_vertices); } + + // Returns the number of edges in the graph + inline edges_size_type num_edges() const { return (m_num_edges); } + + // Returns the number of edges in dimension [dimension_index] + inline edges_size_type num_edges(std::size_t dimension_index) const + { + return (m_edge_count[dimension_index]); + } + + // Returns the index of [vertex] (See also vertex_at) + vertices_size_type index_of(vertex_descriptor vertex) const + { + + vertices_size_type vertex_index = 0; + vertices_size_type index_multiplier = 1; + + for (std::size_t dimension_index = 0; dimension_index < Dimensions; + ++dimension_index) + { + + vertex_index += (vertex[dimension_index] * index_multiplier); + index_multiplier *= length(dimension_index); + } + + return (vertex_index); + } + + // Returns the vertex whose index is [vertex_index] (See also + // index_of(vertex_descriptor)) + vertex_descriptor vertex_at(vertices_size_type vertex_index) const + { + + boost::array< vertices_size_type, Dimensions > vertex; + vertices_size_type index_divider = 1; + + for (std::size_t dimension_index = 0; dimension_index < Dimensions; + ++dimension_index) + { + + vertex[dimension_index] + = (vertex_index / index_divider) % length(dimension_index); + + index_divider *= length(dimension_index); + } + + return (vertex); + } + + // Returns the edge whose index is [edge_index] (See also + // index_of(edge_descriptor)). NOTE: The index mapping is + // dependent upon dimension wrapping. + edge_descriptor edge_at(edges_size_type edge_index) const + { + + // Edge indices are sorted into bins by dimension + std::size_t dimension_index = 0; + edges_size_type dimension_edges = num_edges(0); + + while (edge_index >= dimension_edges) + { + edge_index -= dimension_edges; + ++dimension_index; + dimension_edges = num_edges(dimension_index); + } + + vertex_descriptor vertex_source, vertex_target; + bool is_forward + = ((edge_index / (num_edges(dimension_index) / 2)) == 0); + + if (wrapped(dimension_index)) + { + vertex_source = vertex_at(edge_index % num_vertices()); + vertex_target = is_forward + ? next(vertex_source, dimension_index) + : previous(vertex_source, dimension_index); + } + else + { + + // Dimensions can wrap arbitrarily, so an index needs to be + // computed in a more complex manner. This is done by + // grouping the edges for each dimension together into "bins" + // and considering [edge_index] as an offset into the bin. + // Each bin consists of two parts: the "forward" looking edges + // and the "backward" looking edges for the dimension. + + edges_size_type vertex_offset + = edge_index % num_edges(dimension_index); + + // Consider vertex_offset an index into the graph's vertex + // space but with the dimension [dimension_index] reduced in + // size by one. + vertices_size_type index_divider = 1; + + for (std::size_t dimension_index_iter = 0; + dimension_index_iter < Dimensions; ++dimension_index_iter) + { + + std::size_t dimension_length + = (dimension_index_iter == dimension_index) + ? length(dimension_index_iter) - 1 + : length(dimension_index_iter); + + vertex_source[dimension_index_iter] + = (vertex_offset / index_divider) % dimension_length; + + index_divider *= dimension_length; + } + + if (is_forward) + { + vertex_target = next(vertex_source, dimension_index); + } + else + { + // Shift forward one more unit in the dimension for backward + // edges since the algorithm above will leave us one behind. + vertex_target = vertex_source; + ++vertex_source[dimension_index]; + } + + } // if (wrapped(dimension_index)) + + return (std::make_pair(vertex_source, vertex_target)); + } + + // Returns the index for [edge] (See also edge_at) + edges_size_type index_of(edge_descriptor edge) const + { + vertex_descriptor source_vertex = source(edge, *this); + vertex_descriptor target_vertex = target(edge, *this); + + BOOST_ASSERT(source_vertex != target_vertex); + + // Determine the dimension where the source and target vertices + // differ (should only be one if this is a valid edge). + std::size_t different_dimension_index = 0; + + while (source_vertex[different_dimension_index] + == target_vertex[different_dimension_index]) + { + + ++different_dimension_index; + } + + edges_size_type edge_index = 0; + + // Offset the edge index into the appropriate "bin" (see edge_at + // for a more in-depth description). + for (std::size_t dimension_index = 0; + dimension_index < different_dimension_index; ++dimension_index) + { + + edge_index += num_edges(dimension_index); + } + + // Get the position of both vertices in the differing dimension. + vertices_size_type source_position + = source_vertex[different_dimension_index]; + vertices_size_type target_position + = target_vertex[different_dimension_index]; + + // Determine if edge is forward or backward + bool is_forward = true; + + if (wrapped(different_dimension_index)) + { + + // If the dimension is wrapped, an edge is going backward if + // either A: its target precedes the source in the differing + // dimension and the vertices are adjacent or B: its source + // precedes the target and they're not adjacent. + if (((target_position < source_position) + && ((source_position - target_position) == 1)) + || ((source_position < target_position) + && ((target_position - source_position) > 1))) + { + + is_forward = false; + } + } + else if (target_position < source_position) + { + is_forward = false; + } + + // "Backward" edges are in the second half of the bin. + if (!is_forward) + { + edge_index += (num_edges(different_dimension_index) / 2); + } + + // Finally, apply the vertex offset + if (wrapped(different_dimension_index)) + { + edge_index += index_of(source_vertex); + } + else + { + vertices_size_type index_multiplier = 1; + + if (!is_forward) + { + --source_vertex[different_dimension_index]; + } + + for (std::size_t dimension_index = 0; dimension_index < Dimensions; + ++dimension_index) + { + + edge_index + += (source_vertex[dimension_index] * index_multiplier); + index_multiplier + *= (dimension_index == different_dimension_index) + ? length(dimension_index) - 1 + : length(dimension_index); + } + } + + return (edge_index); + } + + // Returns the number of out-edges for [vertex] + degree_size_type out_degree(vertex_descriptor vertex) const + { + + degree_size_type out_edge_count = 0; + + for (std::size_t dimension_index = 0; dimension_index < Dimensions; + ++dimension_index) + { + + // If the vertex is on the edge of this dimension, then its + // number of out edges is dependent upon whether the dimension + // wraps or not. + if ((vertex[dimension_index] == 0) + || (vertex[dimension_index] == (length(dimension_index) - 1))) + { + out_edge_count += (wrapped(dimension_index) ? 2 : 1); + } + else + { + // Next and previous edges, regardless or wrapping + out_edge_count += 2; + } + } + + return (out_edge_count); + } + + // Returns an out-edge for [vertex] by index. Indices are in the + // range [0, out_degree(vertex)). + edge_descriptor out_edge_at( + vertex_descriptor vertex, degree_size_type out_edge_index) const + { + + edges_size_type edges_left = out_edge_index + 1; + std::size_t dimension_index = 0; + bool is_forward = false; + + // Walks the out edges of [vertex] and accommodates for dimension + // wrapping. + while (edges_left > 0) + { + + if (!wrapped(dimension_index)) + { + if (!is_forward && (vertex[dimension_index] == 0)) + { + is_forward = true; + continue; + } + else if (is_forward + && (vertex[dimension_index] + == (length(dimension_index) - 1))) + { + is_forward = false; + ++dimension_index; + continue; + } + } + + --edges_left; + + if (edges_left > 0) + { + is_forward = !is_forward; + + if (!is_forward) + { + ++dimension_index; + } + } + } + + return (std::make_pair(vertex, + is_forward ? next(vertex, dimension_index) + : previous(vertex, dimension_index))); + } + + // Returns the number of in-edges for [vertex] + inline degree_size_type in_degree(vertex_descriptor vertex) const + { + return (out_degree(vertex)); + } + + // Returns an in-edge for [vertex] by index. Indices are in the + // range [0, in_degree(vertex)). + edge_descriptor in_edge_at( + vertex_descriptor vertex, edges_size_type in_edge_index) const + { + + edge_descriptor out_edge = out_edge_at(vertex, in_edge_index); + return ( + std::make_pair(target(out_edge, *this), source(out_edge, *this))); + } + + // Pre-computes the number of vertices and edges + void precalculate() + { + m_num_vertices = std::accumulate(m_dimension_lengths.begin(), + m_dimension_lengths.end(), vertices_size_type(1), + std::multiplies< vertices_size_type >()); + + // Calculate number of edges in each dimension + m_num_edges = 0; + + for (std::size_t dimension_index = 0; dimension_index < Dimensions; + ++dimension_index) + { + + if (wrapped(dimension_index)) + { + m_edge_count[dimension_index] = num_vertices() * 2; + } + else + { + m_edge_count[dimension_index] + = (num_vertices() + - (num_vertices() / length(dimension_index))) + * 2; + } + + m_num_edges += num_edges(dimension_index); + } + } + + const vertex_descriptor m_dimension_lengths; + WrapDimensionArray m_wrap_dimension; + vertices_size_type m_num_vertices; + + boost::array< edges_size_type, Dimensions > m_edge_count; + edges_size_type m_num_edges; + +public: + //================ + // VertexListGraph + //================ + + friend inline std::pair< typename type::vertex_iterator, + typename type::vertex_iterator > + vertices(const type& graph) + { + typedef typename type::vertex_iterator vertex_iterator; + typedef typename type::vertex_function vertex_function; + typedef typename type::vertex_index_iterator vertex_index_iterator; + + return (std::make_pair( + vertex_iterator(vertex_index_iterator(0), vertex_function(&graph)), + vertex_iterator(vertex_index_iterator(graph.num_vertices()), + vertex_function(&graph)))); + } + + friend inline typename type::vertices_size_type num_vertices( + const type& graph) + { + return (graph.num_vertices()); + } + + friend inline typename type::vertex_descriptor vertex( + typename type::vertices_size_type vertex_index, const type& graph) + { + + return (graph.vertex_at(vertex_index)); + } + + //=============== + // IncidenceGraph + //=============== + + friend inline std::pair< typename type::out_edge_iterator, + typename type::out_edge_iterator > + out_edges(typename type::vertex_descriptor vertex, const type& graph) + { + typedef typename type::degree_iterator degree_iterator; + typedef typename type::out_edge_function out_edge_function; + typedef typename type::out_edge_iterator out_edge_iterator; + + return (std::make_pair(out_edge_iterator(degree_iterator(0), + out_edge_function(vertex, &graph)), + out_edge_iterator(degree_iterator(graph.out_degree(vertex)), + out_edge_function(vertex, &graph)))); + } + + friend inline typename type::degree_size_type out_degree( + typename type::vertex_descriptor vertex, const type& graph) + { + return (graph.out_degree(vertex)); + } + + friend inline typename type::edge_descriptor out_edge_at( + typename type::vertex_descriptor vertex, + typename type::degree_size_type out_edge_index, const type& graph) + { + return (graph.out_edge_at(vertex, out_edge_index)); + } + + //=============== + // AdjacencyGraph + //=============== + + friend typename std::pair< typename type::adjacency_iterator, + typename type::adjacency_iterator > + adjacent_vertices( + typename type::vertex_descriptor vertex, const type& graph) + { + typedef typename type::degree_iterator degree_iterator; + typedef + typename type::adjacent_vertex_function adjacent_vertex_function; + typedef typename type::adjacency_iterator adjacency_iterator; + + return (std::make_pair(adjacency_iterator(degree_iterator(0), + adjacent_vertex_function(vertex, &graph)), + adjacency_iterator(degree_iterator(graph.out_degree(vertex)), + adjacent_vertex_function(vertex, &graph)))); + } + + //============== + // EdgeListGraph + //============== + + friend inline typename type::edges_size_type num_edges(const type& graph) + { + return (graph.num_edges()); + } + + friend inline typename type::edge_descriptor edge_at( + typename type::edges_size_type edge_index, const type& graph) + { + return (graph.edge_at(edge_index)); + } + + friend inline std::pair< typename type::edge_iterator, + typename type::edge_iterator > + edges(const type& graph) + { + typedef typename type::edge_index_iterator edge_index_iterator; + typedef typename type::edge_function edge_function; + typedef typename type::edge_iterator edge_iterator; + + return (std::make_pair( + edge_iterator(edge_index_iterator(0), edge_function(&graph)), + edge_iterator(edge_index_iterator(graph.num_edges()), + edge_function(&graph)))); + } + + //=================== + // BiDirectionalGraph + //=================== + + friend inline std::pair< typename type::in_edge_iterator, + typename type::in_edge_iterator > + in_edges(typename type::vertex_descriptor vertex, const type& graph) + { + typedef typename type::in_edge_function in_edge_function; + typedef typename type::degree_iterator degree_iterator; + typedef typename type::in_edge_iterator in_edge_iterator; + + return (std::make_pair(in_edge_iterator(degree_iterator(0), + in_edge_function(vertex, &graph)), + in_edge_iterator(degree_iterator(graph.in_degree(vertex)), + in_edge_function(vertex, &graph)))); + } + + friend inline typename type::degree_size_type in_degree( + typename type::vertex_descriptor vertex, const type& graph) + { + return (graph.in_degree(vertex)); + } + + friend inline typename type::degree_size_type degree( + typename type::vertex_descriptor vertex, const type& graph) + { + return (graph.out_degree(vertex) * 2); + } + + friend inline typename type::edge_descriptor in_edge_at( + typename type::vertex_descriptor vertex, + typename type::degree_size_type in_edge_index, const type& graph) + { + return (graph.in_edge_at(vertex, in_edge_index)); + } + + //================== + // Adjacency Matrix + //================== + + friend std::pair< typename type::edge_descriptor, bool > edge( + typename type::vertex_descriptor source_vertex, + typename type::vertex_descriptor destination_vertex, const type& graph) + { + + std::pair< typename type::edge_descriptor, bool > edge_exists + = std::make_pair( + std::make_pair(source_vertex, destination_vertex), false); + + for (std::size_t dimension_index = 0; dimension_index < Dimensions; + ++dimension_index) + { + + typename type::vertices_size_type dim_difference = 0; + typename type::vertices_size_type source_dim + = source_vertex[dimension_index], + dest_dim = destination_vertex[dimension_index]; + + dim_difference = (source_dim > dest_dim) ? (source_dim - dest_dim) + : (dest_dim - source_dim); + + if (dim_difference > 0) + { + + // If we've already found a valid edge, this would mean that + // the vertices are really diagonal across dimensions and + // therefore not connected. + if (edge_exists.second) + { + edge_exists.second = false; + break; + } + + // If the difference is one, the vertices are right next to + // each other and the edge is valid. The edge is still + // valid, though, if the dimension wraps and the vertices + // are on opposite ends. + if ((dim_difference == 1) + || (graph.wrapped(dimension_index) + && (((source_dim == 0) + && (dest_dim + == (graph.length(dimension_index) - 1))) + || ((dest_dim == 0) + && (source_dim + == (graph.length(dimension_index) - 1)))))) + { + + edge_exists.second = true; + // Stay in the loop to check for diagonal vertices. + } + else + { + + // Stop checking - the vertices are too far apart. + edge_exists.second = false; + break; + } + } + + } // for dimension_index + + return (edge_exists); + } + + //============================= + // Index Property Map Functions + //============================= + + friend inline typename type::vertices_size_type get(vertex_index_t, + const type& graph, typename type::vertex_descriptor vertex) + { + return (graph.index_of(vertex)); + } + + friend inline typename type::edges_size_type get( + edge_index_t, const type& graph, typename type::edge_descriptor edge) + { + return (graph.index_of(edge)); + } + + friend inline grid_graph_index_map< type, typename type::vertex_descriptor, + typename type::vertices_size_type > + get(vertex_index_t, const type& graph) + { + return (grid_graph_index_map< type, typename type::vertex_descriptor, + typename type::vertices_size_type >(graph)); + } + + friend inline grid_graph_index_map< type, typename type::edge_descriptor, + typename type::edges_size_type > + get(edge_index_t, const type& graph) + { + return (grid_graph_index_map< type, typename type::edge_descriptor, + typename type::edges_size_type >(graph)); + } + + friend inline grid_graph_reverse_edge_map< typename type::edge_descriptor > + get(edge_reverse_t, const type& graph) + { + return ( + grid_graph_reverse_edge_map< typename type::edge_descriptor >()); + } + + template < typename Graph, typename Descriptor, typename Index > + friend struct grid_graph_index_map; + + template < typename Descriptor > friend struct grid_graph_reverse_edge_map; + +}; // grid_graph + +} // namespace boost + +#undef BOOST_GRID_GRAPH_TYPE +#undef BOOST_GRID_GRAPH_TEMPLATE_PARAMS +#undef BOOST_GRID_GRAPH_TRAITS_T + +#endif // BOOST_GRAPH_GRID_GRAPH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/gursoy_atun_layout.hpp b/contrib/restricted/boost/graph/include/boost/graph/gursoy_atun_layout.hpp new file mode 100644 index 0000000000..1a8709b178 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/gursoy_atun_layout.hpp @@ -0,0 +1,338 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP +#define BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP + +// Gürsoy-Atun graph layout, based on: +// "Neighbourhood Preserving Load Balancing: A Self-Organizing Approach" +// in 6th International Euro-Par Conference Munich, Germany, August 29 – +// September 1, 2000 Proceedings, pp 234-241 +// https://doi.org/10.1007/3-540-44520-X_32 + +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/throw_exception.hpp> +#include <boost/assert.hpp> +#include <vector> +#include <exception> +#include <algorithm> + +#include <boost/graph/visitors.hpp> +#include <boost/graph/properties.hpp> +#include <boost/random/uniform_01.hpp> +#include <boost/random/linear_congruential.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/graph/breadth_first_search.hpp> +#include <boost/graph/dijkstra_shortest_paths.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/graph/topology.hpp> + +namespace boost +{ + +namespace detail +{ + + struct over_distance_limit : public std::exception + { + }; + + template < typename PositionMap, typename NodeDistanceMap, + typename Topology, typename Graph > + struct update_position_visitor + { + typedef typename Topology::point_type Point; + PositionMap position_map; + NodeDistanceMap node_distance; + const Topology& space; + Point input_vector; + double distance_limit; + double learning_constant; + double falloff_ratio; + + typedef boost::on_examine_vertex event_filter; + + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + + update_position_visitor(PositionMap position_map, + NodeDistanceMap node_distance, const Topology& space, + const Point& input_vector, double distance_limit, + double learning_constant, double falloff_ratio) + : position_map(position_map) + , node_distance(node_distance) + , space(space) + , input_vector(input_vector) + , distance_limit(distance_limit) + , learning_constant(learning_constant) + , falloff_ratio(falloff_ratio) + { + } + + void operator()(vertex_descriptor v, const Graph&) const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::pow; +#endif + + if (get(node_distance, v) > distance_limit) + BOOST_THROW_EXCEPTION(over_distance_limit()); + Point old_position = get(position_map, v); + double distance = get(node_distance, v); + double fraction + = learning_constant * pow(falloff_ratio, distance * distance); + put(position_map, v, + space.move_position_toward( + old_position, fraction, input_vector)); + } + }; + + template < typename EdgeWeightMap > struct gursoy_shortest + { + template < typename Graph, typename NodeDistanceMap, + typename UpdatePosition > + static inline void run(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + NodeDistanceMap node_distance, UpdatePosition& update_position, + EdgeWeightMap weight) + { + boost::dijkstra_shortest_paths(g, s, + weight_map(weight).visitor(boost::make_dijkstra_visitor( + std::make_pair(boost::record_distances( + node_distance, boost::on_edge_relaxed()), + update_position)))); + } + }; + + template <> struct gursoy_shortest< dummy_property_map > + { + template < typename Graph, typename NodeDistanceMap, + typename UpdatePosition > + static inline void run(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + NodeDistanceMap node_distance, UpdatePosition& update_position, + dummy_property_map) + { + boost::breadth_first_search(g, s, + visitor(boost::make_bfs_visitor( + std::make_pair(boost::record_distances( + node_distance, boost::on_tree_edge()), + update_position)))); + } + }; + +} // namespace detail + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap, typename Diameter, typename VertexIndexMap, + typename EdgeWeightMap > +void gursoy_atun_step(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position, Diameter diameter, + double learning_constant, VertexIndexMap vertex_index_map, + EdgeWeightMap weight) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::exp; + using std::pow; +#endif + + typedef + typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator + vertex_iterator; + typedef + typename graph_traits< VertexListAndIncidenceGraph >::vertex_descriptor + vertex_descriptor; + typedef typename Topology::point_type point_type; + vertex_iterator i, iend; + std::vector< double > distance_from_input_vector(num_vertices(graph)); + typedef boost::iterator_property_map< std::vector< double >::iterator, + VertexIndexMap, double, double& > + DistanceFromInputMap; + DistanceFromInputMap distance_from_input( + distance_from_input_vector.begin(), vertex_index_map); + std::vector< double > node_distance_map_vector(num_vertices(graph)); + typedef boost::iterator_property_map< std::vector< double >::iterator, + VertexIndexMap, double, double& > + NodeDistanceMap; + NodeDistanceMap node_distance( + node_distance_map_vector.begin(), vertex_index_map); + point_type input_vector = space.random_point(); + vertex_descriptor min_distance_loc + = graph_traits< VertexListAndIncidenceGraph >::null_vertex(); + double min_distance = 0.0; + bool min_distance_unset = true; + for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) + { + double this_distance = space.distance(get(position, *i), input_vector); + put(distance_from_input, *i, this_distance); + if (min_distance_unset || this_distance < min_distance) + { + min_distance = this_distance; + min_distance_loc = *i; + } + min_distance_unset = false; + } + BOOST_ASSERT(!min_distance_unset); // Graph must have at least one vertex + boost::detail::update_position_visitor< PositionMap, NodeDistanceMap, + Topology, VertexListAndIncidenceGraph > + update_position(position, node_distance, space, input_vector, diameter, + learning_constant, exp(-1. / (2 * diameter * diameter))); + std::fill( + node_distance_map_vector.begin(), node_distance_map_vector.end(), 0); + try + { + typedef detail::gursoy_shortest< EdgeWeightMap > shortest; + shortest::run( + graph, min_distance_loc, node_distance, update_position, weight); + } + catch (const detail::over_distance_limit&) + { + /* Thrown to break out of BFS or Dijkstra early */ + } +} + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap, typename VertexIndexMap, typename EdgeWeightMap > +void gursoy_atun_refine(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position, int nsteps, + double diameter_initial, double diameter_final, + double learning_constant_initial, double learning_constant_final, + VertexIndexMap vertex_index_map, EdgeWeightMap weight) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::exp; + using std::pow; +#endif + + typedef + typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator + vertex_iterator; + vertex_iterator i, iend; + double diameter_ratio = (double)diameter_final / diameter_initial; + double learning_constant_ratio + = learning_constant_final / learning_constant_initial; + std::vector< double > distance_from_input_vector(num_vertices(graph)); + typedef boost::iterator_property_map< std::vector< double >::iterator, + VertexIndexMap, double, double& > + DistanceFromInputMap; + DistanceFromInputMap distance_from_input( + distance_from_input_vector.begin(), vertex_index_map); + std::vector< int > node_distance_map_vector(num_vertices(graph)); + typedef boost::iterator_property_map< std::vector< int >::iterator, + VertexIndexMap, double, double& > + NodeDistanceMap; + NodeDistanceMap node_distance( + node_distance_map_vector.begin(), vertex_index_map); + for (int round = 0; round < nsteps; ++round) + { + double part_done = (double)round / (nsteps - 1); + // fprintf(stderr, "%2d%% done\n", int(rint(part_done * 100.))); + int diameter = (int)(diameter_initial * pow(diameter_ratio, part_done)); + double learning_constant = learning_constant_initial + * pow(learning_constant_ratio, part_done); + gursoy_atun_step(graph, space, position, diameter, learning_constant, + vertex_index_map, weight); + } +} + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap, typename VertexIndexMap, typename EdgeWeightMap > +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position, int nsteps, + double diameter_initial, double diameter_final, + double learning_constant_initial, double learning_constant_final, + VertexIndexMap vertex_index_map, EdgeWeightMap weight) +{ + typedef + typename graph_traits< VertexListAndIncidenceGraph >::vertex_iterator + vertex_iterator; + vertex_iterator i, iend; + for (boost::tie(i, iend) = vertices(graph); i != iend; ++i) + { + put(position, *i, space.random_point()); + } + gursoy_atun_refine(graph, space, position, nsteps, diameter_initial, + diameter_final, learning_constant_initial, learning_constant_final, + vertex_index_map, weight); +} + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap, typename VertexIndexMap > +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position, int nsteps, + double diameter_initial, double diameter_final, + double learning_constant_initial, double learning_constant_final, + VertexIndexMap vertex_index_map) +{ + gursoy_atun_layout(graph, space, position, nsteps, diameter_initial, + diameter_final, learning_constant_initial, learning_constant_final, + vertex_index_map, dummy_property_map()); +} + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap > +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position, int nsteps, + double diameter_initial, double diameter_final = 1.0, + double learning_constant_initial = 0.8, + double learning_constant_final = 0.2) +{ + gursoy_atun_layout(graph, space, position, nsteps, diameter_initial, + diameter_final, learning_constant_initial, learning_constant_final, + get(vertex_index, graph)); +} + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap > +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position, int nsteps) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + + gursoy_atun_layout( + graph, space, position, nsteps, sqrt((double)num_vertices(graph))); +} + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap > +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position) +{ + gursoy_atun_layout(graph, space, position, num_vertices(graph)); +} + +template < typename VertexListAndIncidenceGraph, typename Topology, + typename PositionMap, typename P, typename T, typename R > +void gursoy_atun_layout(const VertexListAndIncidenceGraph& graph, + const Topology& space, PositionMap position, + const bgl_named_params< P, T, R >& params) +{ +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif + + std::pair< double, double > diam(sqrt(double(num_vertices(graph))), 1.0); + std::pair< double, double > learn(0.8, 0.2); + gursoy_atun_layout(graph, space, position, + choose_param(get_param(params, iterations_t()), num_vertices(graph)), + choose_param(get_param(params, diameter_range_t()), diam).first, + choose_param(get_param(params, diameter_range_t()), diam).second, + choose_param(get_param(params, learning_constant_range_t()), learn) + .first, + choose_param(get_param(params, learning_constant_range_t()), learn) + .second, + choose_const_pmap(get_param(params, vertex_index), graph, vertex_index), + choose_param(get_param(params, edge_weight), dummy_property_map())); +} + +} // namespace boost + +#endif // BOOST_GRAPH_GURSOY_ATUN_LAYOUT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/hawick_circuits.hpp b/contrib/restricted/boost/graph/include/boost/graph/hawick_circuits.hpp new file mode 100644 index 0000000000..cefd6a13a6 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/hawick_circuits.hpp @@ -0,0 +1,409 @@ +// Copyright Louis Dionne 2013 + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy +// at http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_HAWICK_CIRCUITS_HPP +#define BOOST_GRAPH_HAWICK_CIRCUITS_HPP + +#include <algorithm> +#include <boost/assert.hpp> +#include <boost/foreach.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/one_bit_color_map.hpp> +#include <boost/graph/properties.hpp> +#include <boost/move/utility.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/range/begin.hpp> +#include <boost/range/end.hpp> +#include <boost/range/iterator.hpp> +#include <boost/tuple/tuple.hpp> // for boost::tie +#include <boost/type_traits/remove_reference.hpp> +#include <boost/utility/result_of.hpp> +#include <set> +#include <utility> // for std::pair +#include <vector> + +namespace boost +{ +namespace hawick_circuits_detail +{ + //! @internal Functor returning all the vertices adjacent to a vertex. + struct get_all_adjacent_vertices + { + template < typename Sig > struct result; + + template < typename This, typename Vertex, typename Graph > + struct result< This(Vertex, Graph) > + { + private: + typedef typename remove_reference< Graph >::type RawGraph; + typedef graph_traits< RawGraph > Traits; + typedef typename Traits::adjacency_iterator AdjacencyIterator; + + public: + typedef std::pair< AdjacencyIterator, AdjacencyIterator > type; + }; + + template < typename Vertex, typename Graph > + typename result< get_all_adjacent_vertices( + BOOST_FWD_REF(Vertex), BOOST_FWD_REF(Graph)) >::type + operator()(BOOST_FWD_REF(Vertex) v, BOOST_FWD_REF(Graph) g) const + { + return adjacent_vertices( + boost::forward< Vertex >(v), boost::forward< Graph >(g)); + } + }; + + //! @internal Functor returning a set of the vertices adjacent to a vertex. + struct get_unique_adjacent_vertices + { + template < typename Sig > struct result; + + template < typename This, typename Vertex, typename Graph > + struct result< This(Vertex, Graph) > + { + typedef std::set< typename remove_reference< Vertex >::type > type; + }; + + template < typename Vertex, typename Graph > + typename result< get_unique_adjacent_vertices( + Vertex, Graph const&) >::type + operator()(Vertex v, Graph const& g) const + { + typedef typename result< get_unique_adjacent_vertices( + Vertex, Graph const&) >::type Set; + return Set( + adjacent_vertices(v, g).first, adjacent_vertices(v, g).second); + } + }; + + //! @internal + //! Return whether a container contains a given value. + //! This is not meant as a general purpose membership testing function; it + //! would have to be more clever about possible optimizations. + template < typename Container, typename Value > + bool contains(Container const& c, Value const& v) + { + return std::find(boost::begin(c), boost::end(c), v) != boost::end(c); + } + + /*! + * @internal + * Algorithm finding all the cycles starting from a given vertex. + * + * The search is only done in the subgraph induced by the starting vertex + * and the vertices with an index higher than the starting vertex. + */ + template < typename Graph, typename Visitor, typename VertexIndexMap, + typename Stack, typename ClosedMatrix, typename GetAdjacentVertices > + struct hawick_circuits_from + { + private: + typedef graph_traits< Graph > Traits; + typedef typename Traits::vertex_descriptor Vertex; + typedef typename Traits::edge_descriptor Edge; + typedef typename Traits::vertices_size_type VerticesSize; + typedef + typename property_traits< VertexIndexMap >::value_type VertexIndex; + + typedef typename result_of< GetAdjacentVertices( + Vertex, Graph const&) >::type AdjacentVertices; + typedef typename range_iterator< AdjacentVertices const >::type + AdjacencyIterator; + + // The one_bit_color_map starts all white, i.e. not blocked. + // Since we make that assumption (I looked at the implementation, but + // I can't find anything that documents this behavior), we're gonna + // assert it in the constructor. + typedef one_bit_color_map< VertexIndexMap > BlockedMap; + typedef typename property_traits< BlockedMap >::value_type BlockedColor; + + static BlockedColor blocked_false_color() + { + return color_traits< BlockedColor >::white(); + } + + static BlockedColor blocked_true_color() + { + return color_traits< BlockedColor >::black(); + } + + // This is used by the constructor to secure the assumption + // documented above. + bool blocked_map_starts_all_unblocked() const + { + BOOST_FOREACH (Vertex v, vertices(graph_)) + if (is_blocked(v)) + return false; + return true; + } + + // This is only used in the constructor to make sure the optimization of + // sharing data structures between iterations does not break the code. + bool all_closed_rows_are_empty() const + { + BOOST_FOREACH (typename ClosedMatrix::reference row, closed_) + if (!row.empty()) + return false; + return true; + } + + public: + hawick_circuits_from(Graph const& graph, Visitor& visitor, + VertexIndexMap const& vim, Stack& stack, ClosedMatrix& closed, + VerticesSize n_vertices, unsigned int max_length) + : graph_(graph) + , visitor_(visitor) + , vim_(vim) + , stack_(stack) + , closed_(closed) + , blocked_(n_vertices, vim_) + , max_length_(max_length) + { + BOOST_ASSERT(blocked_map_starts_all_unblocked()); + + // Since sharing the data structures between iterations is + // just an optimization, it must always be equivalent to + // constructing new ones in this constructor. + BOOST_ASSERT(stack_.empty()); + BOOST_ASSERT(closed_.size() == n_vertices); + BOOST_ASSERT(all_closed_rows_are_empty()); + } + + private: + //! @internal Return the index of a given vertex. + VertexIndex index_of(Vertex v) const { return get(vim_, v); } + + //! @internal Return whether a vertex `v` is closed to a vertex `u`. + bool is_closed_to(Vertex u, Vertex v) const + { + typedef typename ClosedMatrix::const_reference VertexList; + VertexList closed_to_u = closed_[index_of(u)]; + return contains(closed_to_u, v); + } + + //! @internal Close a vertex `v` to a vertex `u`. + void close_to(Vertex u, Vertex v) + { + BOOST_ASSERT(!is_closed_to(u, v)); + closed_[index_of(u)].push_back(v); + } + + //! @internal Return whether a given vertex is blocked. + bool is_blocked(Vertex v) const + { + return get(blocked_, v) == blocked_true_color(); + } + + //! @internal Block a given vertex. + void block(Vertex v) { put(blocked_, v, blocked_true_color()); } + + //! @internal Unblock a given vertex. + void unblock(Vertex u) + { + typedef typename ClosedMatrix::reference VertexList; + + put(blocked_, u, blocked_false_color()); + VertexList closed_to_u = closed_[index_of(u)]; + + while (!closed_to_u.empty()) + { + Vertex const w = closed_to_u.back(); + closed_to_u.pop_back(); + if (is_blocked(w)) + unblock(w); + } + BOOST_ASSERT(closed_to_u.empty()); + } + + //! @internal Main procedure as described in the paper. + bool circuit(Vertex start, Vertex v) + { + bool found_circuit = false; + stack_.push_back(v); + block(v); + + // Truncate the search if any circuits would exceed max_length_. + bool const truncate_search = + (max_length_ > 0 && stack_.size() >= max_length_); + + // Cache some values that are used more than once in the function. + VertexIndex const index_of_start = index_of(start); + AdjacentVertices const adj_vertices + = GetAdjacentVertices()(v, graph_); + AdjacencyIterator const w_end = boost::end(adj_vertices); + + for (AdjacencyIterator w_it = boost::begin(adj_vertices); + w_it != w_end; ++w_it) + { + Vertex const w = *w_it; + // Since we're only looking in the subgraph induced by `start` + // and the vertices with an index higher than `start`, we skip + // any vertex that does not satisfy that. + if (index_of(w) < index_of_start) + continue; + + // If the last vertex is equal to `start`, we have a circuit. + else if (w == start) + { + // const_cast to ensure the visitor does not modify the + // stack + visitor_.cycle(const_cast< Stack const& >(stack_), graph_); + found_circuit = true; + } + + // If required, truncate the search before the subsequent + // recursive call to circuit(). + else if (truncate_search) + continue; + + // If `w` is not blocked, we continue searching further down the + // same path for a cycle with `w` in it. + else if (!is_blocked(w) && circuit(start, w)) + found_circuit = true; + } + + bool const finish_circuit = (found_circuit || truncate_search); + if (finish_circuit) + unblock(v); + else + for (AdjacencyIterator w_it = boost::begin(adj_vertices); + w_it != w_end; ++w_it) + { + Vertex const w = *w_it; + // Like above, we skip vertices that are not in the subgraph + // we're considering. + if (index_of(w) < index_of_start) + continue; + + // If `v` is not closed to `w`, we make it so. + if (!is_closed_to(w, v)) + close_to(w, v); + } + + BOOST_ASSERT(v == stack_.back()); + stack_.pop_back(); + return finish_circuit; + } + + public: + void operator()(Vertex start) { circuit(start, start); } + + private: + Graph const& graph_; + Visitor& visitor_; + VertexIndexMap const& vim_; + Stack& stack_; + ClosedMatrix& closed_; + BlockedMap blocked_; + unsigned int max_length_; + }; + + template < typename GetAdjacentVertices, typename Graph, typename Visitor, + typename VertexIndexMap > + void call_hawick_circuits(Graph const& graph, + Visitor /* by value */ visitor, VertexIndexMap const& vertex_index_map, + unsigned int max_length) + { + typedef graph_traits< Graph > Traits; + typedef typename Traits::vertex_descriptor Vertex; + typedef typename Traits::vertices_size_type VerticesSize; + typedef typename Traits::vertex_iterator VertexIterator; + + typedef std::vector< Vertex > Stack; + typedef std::vector< std::vector< Vertex > > ClosedMatrix; + + typedef hawick_circuits_from< Graph, Visitor, VertexIndexMap, Stack, + ClosedMatrix, GetAdjacentVertices > + SubAlgorithm; + + VerticesSize const n_vertices = num_vertices(graph); + Stack stack; + stack.reserve(n_vertices); + ClosedMatrix closed(n_vertices); + + VertexIterator start, last; + for (boost::tie(start, last) = vertices(graph); start != last; ++start) + { + // Note1: The sub algorithm may NOT be reused once it has been + // called. + + // Note2: We reuse the Stack and the ClosedMatrix (after clearing + // them) in each iteration to avoid redundant destruction and + // construction. It would be strictly equivalent to have these as + // member variables of the sub algorithm. + SubAlgorithm sub_algo( + graph, visitor, vertex_index_map, stack, closed, n_vertices, + max_length); + sub_algo(*start); + stack.clear(); + typename ClosedMatrix::iterator row, last_row = closed.end(); + for (row = closed.begin(); row != last_row; ++row) + row->clear(); + } + } + + template < typename GetAdjacentVertices, typename Graph, typename Visitor > + void call_hawick_circuits( + Graph const& graph, BOOST_FWD_REF(Visitor) visitor, + unsigned int max_length) + { + call_hawick_circuits< GetAdjacentVertices >(graph, + boost::forward< Visitor >(visitor), get(vertex_index, graph), + max_length); + } +} // end namespace hawick_circuits_detail + +//! Enumerate all the elementary circuits in a directed multigraph. +template < typename Graph, typename Visitor, typename VertexIndexMap > +void hawick_circuits(BOOST_FWD_REF(Graph) graph, BOOST_FWD_REF(Visitor) visitor, + BOOST_FWD_REF(VertexIndexMap) vertex_index_map, + unsigned int max_length = 0) +{ + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_all_adjacent_vertices >( + boost::forward< Graph >(graph), boost::forward< Visitor >(visitor), + boost::forward< VertexIndexMap >(vertex_index_map), max_length); +} + +template < typename Graph, typename Visitor > +void hawick_circuits(BOOST_FWD_REF(Graph) graph, BOOST_FWD_REF(Visitor) visitor, + unsigned int max_length = 0) +{ + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_all_adjacent_vertices >( + boost::forward< Graph >(graph), boost::forward< Visitor >(visitor), + max_length); +} + +/*! + * Same as `boost::hawick_circuits`, but duplicate circuits caused by parallel + * edges will not be considered. Each circuit will be considered only once. + */ +template < typename Graph, typename Visitor, typename VertexIndexMap > +void hawick_unique_circuits(BOOST_FWD_REF(Graph) graph, + BOOST_FWD_REF(Visitor) visitor, + BOOST_FWD_REF(VertexIndexMap) vertex_index_map, + unsigned int max_length = 0) +{ + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_unique_adjacent_vertices >( + boost::forward< Graph >(graph), boost::forward< Visitor >(visitor), + boost::forward< VertexIndexMap >(vertex_index_map), max_length); +} + +template < typename Graph, typename Visitor > +void hawick_unique_circuits( + BOOST_FWD_REF(Graph) graph, BOOST_FWD_REF(Visitor) visitor, + unsigned int max_length = 0) +{ + hawick_circuits_detail::call_hawick_circuits< + hawick_circuits_detail::get_unique_adjacent_vertices >( + boost::forward< Graph >(graph), boost::forward< Visitor >(visitor), + max_length); +} +} // end namespace boost + +#endif // !BOOST_GRAPH_HAWICK_CIRCUITS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/howard_cycle_ratio.hpp b/contrib/restricted/boost/graph/include/boost/graph/howard_cycle_ratio.hpp new file mode 100644 index 0000000000..fe6c5bd94d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/howard_cycle_ratio.hpp @@ -0,0 +1,643 @@ +// Copyright (C) 2006-2009 Dmitry Bufistov and Andrey Parfenov + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_CYCLE_RATIO_HOWARD_HPP +#define BOOST_GRAPH_CYCLE_RATIO_HOWARD_HPP + +#include <vector> +#include <list> +#include <algorithm> +#include <functional> +#include <limits> + +#include <boost/bind/bind.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/remove_const.hpp> +#include <boost/concept_check.hpp> +#include <boost/pending/queue.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/concept/assert.hpp> +#include <boost/algorithm/minmax_element.hpp> + +/** @file howard_cycle_ratio.hpp + * @brief The implementation of the maximum/minimum cycle ratio/mean algorithm. + * @author Dmitry Bufistov + * @author Andrey Parfenov + */ + +namespace boost +{ + +/** + * The mcr_float is like numeric_limits, but only for floating point types + * and only defines infinity() and epsilon(). This class is primarily used + * to encapsulate a less-precise epsilon than natively supported by the + * floating point type. + */ +template < typename Float = double > struct mcr_float +{ + typedef Float value_type; + + static Float infinity() + { + return std::numeric_limits< value_type >::infinity(); + } + + static Float epsilon() { return Float(-0.005); } +}; + +namespace detail +{ + + template < typename FloatTraits > struct min_comparator_props + { + typedef std::greater< typename FloatTraits::value_type > comparator; + static const int multiplier = 1; + }; + + template < typename FloatTraits > struct max_comparator_props + { + typedef std::less< typename FloatTraits::value_type > comparator; + static const int multiplier = -1; + }; + + template < typename FloatTraits, typename ComparatorProps > + struct float_wrapper + { + typedef typename FloatTraits::value_type value_type; + typedef ComparatorProps comparator_props_t; + typedef typename ComparatorProps::comparator comparator; + + static value_type infinity() + { + return FloatTraits::infinity() * ComparatorProps::multiplier; + } + + static value_type epsilon() + { + return FloatTraits::epsilon() * ComparatorProps::multiplier; + } + }; + + /*! @class mcr_howard + * @brief Calculates optimum (maximum/minimum) cycle ratio of a directed + * graph. Uses Howard's iteration policy algorithm. </br>(It is described + * in the paper "Experimental Analysis of the Fastest Optimum Cycle Ratio + * and Mean Algorithm" by Ali Dasdan). + */ + template < typename FloatTraits, typename Graph, typename VertexIndexMap, + typename EdgeWeight1, typename EdgeWeight2 > + class mcr_howard + { + public: + typedef typename FloatTraits::value_type float_t; + typedef typename FloatTraits::comparator_props_t cmp_props_t; + typedef typename FloatTraits::comparator comparator_t; + typedef enum + { + my_white = 0, + my_black + } my_color_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef typename graph_traits< Graph >::vertices_size_type vn_t; + typedef std::vector< float_t > vp_t; + typedef typename boost::iterator_property_map< typename vp_t::iterator, + VertexIndexMap > + distance_map_t; // V -> float_t + + typedef typename std::vector< edge_t > ve_t; + typedef std::vector< my_color_type > vcol_t; + typedef + typename ::boost::iterator_property_map< typename ve_t::iterator, + VertexIndexMap > + policy_t; // Vertex -> Edge + typedef + typename ::boost::iterator_property_map< typename vcol_t::iterator, + VertexIndexMap > + color_map_t; + + typedef typename std::list< vertex_t > + pinel_t; // The in_edges list of the policy graph + typedef typename std::vector< pinel_t > inedges1_t; + typedef typename ::boost::iterator_property_map< + typename inedges1_t::iterator, VertexIndexMap > + inedges_t; + typedef typename std::vector< edge_t > critical_cycle_t; + + // Bad vertex flag. If true, then the vertex is "bad". + // Vertex is "bad" if its out_degree is equal to zero. + typedef + typename boost::iterator_property_map< std::vector< int >::iterator, + VertexIndexMap > + badv_t; + + /*! + * Constructor + * \param g = (V, E) - a directed multigraph. + * \param vim Vertex Index Map. Read property Map: V -> [0, + * num_vertices(g)). \param ewm edge weight map. Read property map: E + * -> R \param ew2m edge weight map. Read property map: E -> R+ \param + * infty A big enough value to guaranty that there exist a cycle with + * better ratio. + * \param cmp The compare operator for float_ts. + */ + mcr_howard(const Graph& g, VertexIndexMap vim, EdgeWeight1 ewm, + EdgeWeight2 ew2m) + : m_g(g) + , m_vim(vim) + , m_ew1m(ewm) + , m_ew2m(ew2m) + , m_bound(mcr_bound()) + , m_cr(m_bound) + , m_V(num_vertices(m_g)) + , m_dis(m_V, 0) + , m_dm(m_dis.begin(), m_vim) + , m_policyc(m_V) + , m_policy(m_policyc.begin(), m_vim) + , m_inelc(m_V) + , m_inel(m_inelc.begin(), m_vim) + , m_badvc(m_V, false) + , m_badv(m_badvc.begin(), m_vim) + , m_colcv(m_V) + , m_col_bfs(m_V) + { + } + + /*! + * \return maximum/minimum_{for all cycles C} + * [sum_{e in C} w1(e)] / [sum_{e in C} w2(e)], + * or FloatTraits::infinity() if graph has no cycles. + */ + float_t ocr_howard() + { + construct_policy_graph(); + int k = 0; + float_t mcr = 0; + do + { + mcr = policy_mcr(); + ++k; + } while ( + try_improve_policy(mcr) && k < 100); // To avoid infinite loop + + const float_t eps_ = -0.00000001 * cmp_props_t::multiplier; + if (m_cmp(mcr, m_bound + eps_)) + { + return FloatTraits::infinity(); + } + else + { + return mcr; + } + } + virtual ~mcr_howard() {} + + protected: + virtual void store_critical_edge(edge_t, critical_cycle_t&) {} + virtual void store_critical_cycle(critical_cycle_t&) {} + + private: + /*! + * \return lower/upper bound for the maximal/minimal cycle ratio + */ + float_t mcr_bound() + { + typename graph_traits< Graph >::vertex_iterator vi, vie; + typename graph_traits< Graph >::out_edge_iterator oei, oeie; + float_t cz = (std::numeric_limits< float_t >::max)(); // Closest to + // zero value + float_t s = 0; + const float_t eps_ = std::numeric_limits< float_t >::epsilon(); + for (boost::tie(vi, vie) = vertices(m_g); vi != vie; ++vi) + { + for (boost::tie(oei, oeie) = out_edges(*vi, m_g); oei != oeie; + ++oei) + { + s += std::abs(m_ew1m[*oei]); + float_t a = std::abs(m_ew2m[*oei]); + if (a > eps_ && a < cz) + { + cz = a; + } + } + } + return cmp_props_t::multiplier * (s / cz); + } + + /*! + * Constructs an arbitrary policy graph. + */ + void construct_policy_graph() + { + m_sink = graph_traits< Graph >().null_vertex(); + typename graph_traits< Graph >::vertex_iterator vi, vie; + typename graph_traits< Graph >::out_edge_iterator oei, oeie; + for (boost::tie(vi, vie) = vertices(m_g); vi != vie; ++vi) + { + using namespace boost::placeholders; + + boost::tie(oei, oeie) = out_edges(*vi, m_g); + typename graph_traits< Graph >::out_edge_iterator mei + = boost::first_max_element(oei, oeie, + boost::bind(m_cmp, + boost::bind(&EdgeWeight1::operator[], m_ew1m, _1), + boost::bind(&EdgeWeight1::operator[], m_ew1m, _2))); + if (mei == oeie) + { + if (m_sink == graph_traits< Graph >().null_vertex()) + { + m_sink = *vi; + } + m_badv[*vi] = true; + m_inel[m_sink].push_back(*vi); + } + else + { + m_inel[target(*mei, m_g)].push_back(*vi); + m_policy[*vi] = *mei; + } + } + } + /*! Sets the distance value for all vertices "v" such that there is + * a path from "v" to "sv". It does "inverse" breadth first visit of the + * policy graph, starting from the vertex "sv". + */ + void mcr_bfv(vertex_t sv, float_t cr, color_map_t c) + { + boost::queue< vertex_t > Q; + c[sv] = my_black; + Q.push(sv); + while (!Q.empty()) + { + vertex_t v = Q.top(); + Q.pop(); + for (typename pinel_t::const_iterator itr = m_inel[v].begin(); + itr != m_inel[v].end(); ++itr) + // For all in_edges of the policy graph + { + if (*itr != sv) + { + if (m_badv[*itr]) + { + m_dm[*itr] = m_dm[v] + m_bound - cr; + } + else + { + m_dm[*itr] = m_dm[v] + m_ew1m[m_policy[*itr]] + - m_ew2m[m_policy[*itr]] * cr; + } + c[*itr] = my_black; + Q.push(*itr); + } + } + } + } + + /*! + * \param sv an arbitrary (undiscovered) vertex of the policy graph. + * \return a vertex in the policy graph that belongs to a cycle. + * Performs a depth first visit until a cycle edge is found. + */ + vertex_t find_cycle_vertex(vertex_t sv) + { + vertex_t gv = sv; + std::fill(m_colcv.begin(), m_colcv.end(), my_white); + color_map_t cm(m_colcv.begin(), m_vim); + do + { + cm[gv] = my_black; + if (!m_badv[gv]) + { + gv = target(m_policy[gv], m_g); + } + else + { + gv = m_sink; + } + } while (cm[gv] != my_black); + return gv; + } + + /*! + * \param sv - vertex that belongs to a cycle in the policy graph. + */ + float_t cycle_ratio(vertex_t sv) + { + if (sv == m_sink) + return m_bound; + std::pair< float_t, float_t > sums_(float_t(0), float_t(0)); + vertex_t v = sv; + critical_cycle_t cc; + do + { + store_critical_edge(m_policy[v], cc); + sums_.first += m_ew1m[m_policy[v]]; + sums_.second += m_ew2m[m_policy[v]]; + v = target(m_policy[v], m_g); + } while (v != sv); + float_t cr = sums_.first / sums_.second; + if (m_cmp(m_cr, cr)) + { + m_cr = cr; + store_critical_cycle(cc); + } + return cr; + } + + /*! + * Finds the optimal cycle ratio of the policy graph + */ + float_t policy_mcr() + { + using namespace boost::placeholders; + + std::fill(m_col_bfs.begin(), m_col_bfs.end(), my_white); + color_map_t vcm_ = color_map_t(m_col_bfs.begin(), m_vim); + typename graph_traits< Graph >::vertex_iterator uv_itr, vie; + boost::tie(uv_itr, vie) = vertices(m_g); + float_t mcr = m_bound; + while ((uv_itr = std::find_if(uv_itr, vie, + boost::bind(std::equal_to< my_color_type >(), my_white, + boost::bind(&color_map_t::operator[], vcm_, _1)))) + != vie) + /// While there are undiscovered vertices + { + vertex_t gv = find_cycle_vertex(*uv_itr); + float_t cr = cycle_ratio(gv); + mcr_bfv(gv, cr, vcm_); + if (m_cmp(mcr, cr)) + mcr = cr; + ++uv_itr; + } + return mcr; + } + + /*! + * Changes the edge m_policy[s] to the new_edge. + */ + void improve_policy(vertex_t s, edge_t new_edge) + { + vertex_t t = target(m_policy[s], m_g); + typename property_traits< VertexIndexMap >::value_type ti + = m_vim[t]; + m_inelc[ti].erase( + std::find(m_inelc[ti].begin(), m_inelc[ti].end(), s)); + m_policy[s] = new_edge; + t = target(new_edge, m_g); + m_inel[t].push_back(s); /// Maintain in_edge list + } + + /*! + * A negative cycle detector. + */ + bool try_improve_policy(float_t cr) + { + bool improved = false; + typename graph_traits< Graph >::vertex_iterator vi, vie; + typename graph_traits< Graph >::out_edge_iterator oei, oeie; + const float_t eps_ = FloatTraits::epsilon(); + for (boost::tie(vi, vie) = vertices(m_g); vi != vie; ++vi) + { + if (!m_badv[*vi]) + { + for (boost::tie(oei, oeie) = out_edges(*vi, m_g); + oei != oeie; ++oei) + { + vertex_t t = target(*oei, m_g); + // Current distance from *vi to some vertex + float_t dis_ + = m_ew1m[*oei] - m_ew2m[*oei] * cr + m_dm[t]; + if (m_cmp(m_dm[*vi] + eps_, dis_)) + { + improve_policy(*vi, *oei); + m_dm[*vi] = dis_; + improved = true; + } + } + } + else + { + float_t dis_ = m_bound - cr + m_dm[m_sink]; + if (m_cmp(m_dm[*vi] + eps_, dis_)) + { + m_dm[*vi] = dis_; + } + } + } + return improved; + } + + private: + const Graph& m_g; + VertexIndexMap m_vim; + EdgeWeight1 m_ew1m; + EdgeWeight2 m_ew2m; + comparator_t m_cmp; + float_t m_bound; //> The lower/upper bound to the maximal/minimal cycle + // ratio + float_t m_cr; //>The best cycle ratio that has been found so far + + vn_t m_V; //>The number of the vertices in the graph + vp_t m_dis; //>Container for the distance map + distance_map_t m_dm; //>Distance map + + ve_t m_policyc; //>Container for the policy graph + policy_t m_policy; //>The interface for the policy graph + + inedges1_t m_inelc; //>Container fot in edges list + inedges_t m_inel; //>Policy graph, input edges list + + std::vector< int > m_badvc; + badv_t m_badv; // Marks "bad" vertices + + vcol_t m_colcv, m_col_bfs; // Color maps + vertex_t m_sink; // To convert any graph to "good" + }; + + /*! \class mcr_howard1 + * \brief Finds optimum cycle raio and a critical cycle + */ + template < typename FloatTraits, typename Graph, typename VertexIndexMap, + typename EdgeWeight1, typename EdgeWeight2 > + class mcr_howard1 : public mcr_howard< FloatTraits, Graph, VertexIndexMap, + EdgeWeight1, EdgeWeight2 > + { + public: + typedef mcr_howard< FloatTraits, Graph, VertexIndexMap, EdgeWeight1, + EdgeWeight2 > + inhr_t; + mcr_howard1(const Graph& g, VertexIndexMap vim, EdgeWeight1 ewm, + EdgeWeight2 ew2m) + : inhr_t(g, vim, ewm, ew2m) + { + } + + void get_critical_cycle(typename inhr_t::critical_cycle_t& cc) + { + return cc.swap(m_cc); + } + + protected: + void store_critical_edge( + typename inhr_t::edge_t ed, typename inhr_t::critical_cycle_t& cc) + { + cc.push_back(ed); + } + + void store_critical_cycle(typename inhr_t::critical_cycle_t& cc) + { + m_cc.swap(cc); + } + + private: + typename inhr_t::critical_cycle_t m_cc; // Critical cycle + }; + + /*! + * \param g a directed multigraph. + * \param vim Vertex Index Map. A map V->[0, num_vertices(g)) + * \param ewm Edge weight1 map. + * \param ew2m Edge weight2 map. + * \param pcc pointer to the critical edges list. + * \return Optimum cycle ratio of g or FloatTraits::infinity() if g has no + * cycles. + */ + template < typename FT, typename TG, typename TVIM, typename TEW1, + typename TEW2, typename EV > + typename FT::value_type optimum_cycle_ratio( + const TG& g, TVIM vim, TEW1 ewm, TEW2 ew2m, EV* pcc) + { + typedef typename graph_traits< TG >::directed_category DirCat; + BOOST_STATIC_ASSERT( + (is_convertible< DirCat*, directed_tag* >::value == true)); + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< TG >)); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< TG >)); + typedef typename graph_traits< TG >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< TVIM, Vertex >)); + typedef typename graph_traits< TG >::edge_descriptor Edge; + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< TEW1, Edge >)); + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< TEW2, Edge >)); + + if (pcc == 0) + { + return detail::mcr_howard< FT, TG, TVIM, TEW1, TEW2 >( + g, vim, ewm, ew2m) + .ocr_howard(); + } + + detail::mcr_howard1< FT, TG, TVIM, TEW1, TEW2 > obj(g, vim, ewm, ew2m); + double ocr = obj.ocr_howard(); + obj.get_critical_cycle(*pcc); + return ocr; + } +} // namespace detail + +// Algorithms +// Maximum Cycle Ratio + +template < typename FloatTraits, typename Graph, typename VertexIndexMap, + typename EdgeWeight1Map, typename EdgeWeight2Map > +inline typename FloatTraits::value_type maximum_cycle_ratio(const Graph& g, + VertexIndexMap vim, EdgeWeight1Map ew1m, EdgeWeight2Map ew2m, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0, + FloatTraits = FloatTraits()) +{ + typedef detail::float_wrapper< FloatTraits, + detail::max_comparator_props< FloatTraits > > + Traits; + return detail::optimum_cycle_ratio< Traits >(g, vim, ew1m, ew2m, pcc); +} + +template < typename Graph, typename VertexIndexMap, typename EdgeWeight1Map, + typename EdgeWeight2Map > +inline double maximum_cycle_ratio(const Graph& g, VertexIndexMap vim, + EdgeWeight1Map ew1m, EdgeWeight2Map ew2m, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0) +{ + return maximum_cycle_ratio(g, vim, ew1m, ew2m, pcc, mcr_float<>()); +} + +// Minimum Cycle Ratio + +template < typename FloatTraits, typename Graph, typename VertexIndexMap, + typename EdgeWeight1Map, typename EdgeWeight2Map > +typename FloatTraits::value_type minimum_cycle_ratio(const Graph& g, + VertexIndexMap vim, EdgeWeight1Map ew1m, EdgeWeight2Map ew2m, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0, + FloatTraits = FloatTraits()) +{ + typedef detail::float_wrapper< FloatTraits, + detail::min_comparator_props< FloatTraits > > + Traits; + return detail::optimum_cycle_ratio< Traits >(g, vim, ew1m, ew2m, pcc); +} + +template < typename Graph, typename VertexIndexMap, typename EdgeWeight1Map, + typename EdgeWeight2Map > +inline double minimum_cycle_ratio(const Graph& g, VertexIndexMap vim, + EdgeWeight1Map ew1m, EdgeWeight2Map ew2m, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0) +{ + return minimum_cycle_ratio(g, vim, ew1m, ew2m, pcc, mcr_float<>()); +} + +// Maximum Cycle Mean + +template < typename FloatTraits, typename Graph, typename VertexIndexMap, + typename EdgeWeightMap, typename EdgeIndexMap > +inline typename FloatTraits::value_type maximum_cycle_mean(const Graph& g, + VertexIndexMap vim, EdgeWeightMap ewm, EdgeIndexMap eim, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0, + FloatTraits ft = FloatTraits()) +{ + typedef typename remove_const< + typename property_traits< EdgeWeightMap >::value_type >::type Weight; + typename std::vector< Weight > ed_w2(boost::num_edges(g), 1); + return maximum_cycle_ratio( + g, vim, ewm, make_iterator_property_map(ed_w2.begin(), eim), pcc, ft); +} + +template < typename Graph, typename VertexIndexMap, typename EdgeWeightMap, + typename EdgeIndexMap > +inline double maximum_cycle_mean(const Graph& g, VertexIndexMap vim, + EdgeWeightMap ewm, EdgeIndexMap eim, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0) +{ + return maximum_cycle_mean(g, vim, ewm, eim, pcc, mcr_float<>()); +} + +// Minimum Cycle Mean + +template < typename FloatTraits, typename Graph, typename VertexIndexMap, + typename EdgeWeightMap, typename EdgeIndexMap > +inline typename FloatTraits::value_type minimum_cycle_mean(const Graph& g, + VertexIndexMap vim, EdgeWeightMap ewm, EdgeIndexMap eim, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0, + FloatTraits ft = FloatTraits()) +{ + typedef typename remove_const< + typename property_traits< EdgeWeightMap >::value_type >::type Weight; + typename std::vector< Weight > ed_w2(boost::num_edges(g), 1); + return minimum_cycle_ratio( + g, vim, ewm, make_iterator_property_map(ed_w2.begin(), eim), pcc, ft); +} + +template < typename Graph, typename VertexIndexMap, typename EdgeWeightMap, + typename EdgeIndexMap > +inline double minimum_cycle_mean(const Graph& g, VertexIndexMap vim, + EdgeWeightMap ewm, EdgeIndexMap eim, + std::vector< typename graph_traits< Graph >::edge_descriptor >* pcc = 0) +{ + return minimum_cycle_mean(g, vim, ewm, eim, pcc, mcr_float<>()); +} + +} // namespace boost + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/incremental_components.hpp b/contrib/restricted/boost/graph/include/boost/graph/incremental_components.hpp new file mode 100644 index 0000000000..f16882e2a5 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/incremental_components.hpp @@ -0,0 +1,234 @@ +// +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Copyright 2009 Trustees of Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Michael Hansen +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_INCREMENTAL_COMPONENTS_HPP +#define BOOST_INCREMENTAL_COMPONENTS_HPP + +#include <boost/tuple/tuple.hpp> +#include <boost/graph/detail/incremental_components.hpp> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/smart_ptr/make_shared.hpp> +#include <boost/pending/disjoint_sets.hpp> +#include <iterator> + +namespace boost +{ + +// A connected component algorithm for the case when dynamically +// adding (but not removing) edges is common. The +// incremental_components() function is a preparing operation. Call +// same_component to check whether two vertices are in the same +// component, or use disjoint_set::find_set to determine the +// representative for a vertex. + +// This version of connected components does not require a full +// Graph. Instead, it just needs an edge list, where the vertices of +// each edge need to be of integer type. The edges are assumed to +// be undirected. The other difference is that the result is stored in +// a container, instead of just a decorator. The container should be +// empty before the algorithm is called. It will grow during the +// course of the algorithm. The container must be a model of +// BackInsertionSequence and RandomAccessContainer +// (std::vector is a good choice). After running the algorithm the +// index container will map each vertex to the representative +// vertex of the component to which it belongs. +// +// Adapted from an implementation by Alex Stepanov. The disjoint +// sets data structure is from Tarjan's "Data Structures and Network +// Algorithms", and the application to connected components is +// similar to the algorithm described in Ch. 22 of "Intro to +// Algorithms" by Cormen, et. all. +// + +// An implementation of disjoint sets can be found in +// boost/pending/disjoint_sets.hpp + +template < class EdgeListGraph, class DisjointSets > +void incremental_components(EdgeListGraph& g, DisjointSets& ds) +{ + typename graph_traits< EdgeListGraph >::edge_iterator e, end; + for (boost::tie(e, end) = edges(g); e != end; ++e) + ds.union_set(source(*e, g), target(*e, g)); +} + +template < class ParentIterator > +void compress_components(ParentIterator first, ParentIterator last) +{ + for (ParentIterator current = first; current != last; ++current) + detail::find_representative_with_full_compression( + first, current - first); +} + +template < class ParentIterator > +typename std::iterator_traits< ParentIterator >::difference_type +component_count(ParentIterator first, ParentIterator last) +{ + std::ptrdiff_t count = 0; + for (ParentIterator current = first; current != last; ++current) + if (*current == current - first) + ++count; + return count; +} + +// This algorithm can be applied to the result container of the +// connected_components algorithm to normalize +// the components. +template < class ParentIterator > +void normalize_components(ParentIterator first, ParentIterator last) +{ + for (ParentIterator current = first; current != last; ++current) + detail::normalize_node(first, current - first); +} + +template < class VertexListGraph, class DisjointSets > +void initialize_incremental_components(VertexListGraph& G, DisjointSets& ds) +{ + typename graph_traits< VertexListGraph >::vertex_iterator v, vend; + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) + ds.make_set(*v); +} + +template < class Vertex, class DisjointSet > +inline bool same_component(Vertex u, Vertex v, DisjointSet& ds) +{ + return ds.find_set(u) == ds.find_set(v); +} + +// Class that builds a quick-access indexed linked list that allows +// for fast iterating through a parent component's children. +template < typename IndexType > class component_index +{ + +private: + typedef std::vector< IndexType > IndexContainer; + +public: + typedef counting_iterator< IndexType > iterator; + typedef iterator const_iterator; + typedef IndexType value_type; + typedef IndexType size_type; + + typedef detail::component_index_iterator< + typename IndexContainer::iterator > + component_iterator; + +public: + template < typename ParentIterator, typename ElementIndexMap > + component_index(ParentIterator parent_start, ParentIterator parent_end, + const ElementIndexMap& index_map) + : m_num_elements(std::distance(parent_start, parent_end)) + , m_components(make_shared< IndexContainer >()) + , m_index_list(make_shared< IndexContainer >(m_num_elements)) + { + + build_index_lists(parent_start, index_map); + + } // component_index + + template < typename ParentIterator > + component_index(ParentIterator parent_start, ParentIterator parent_end) + : m_num_elements(std::distance(parent_start, parent_end)) + , m_components(make_shared< IndexContainer >()) + , m_index_list(make_shared< IndexContainer >(m_num_elements)) + { + + build_index_lists(parent_start, boost::identity_property_map()); + + } // component_index + + // Returns the number of components + inline std::size_t size() const { return (m_components->size()); } + + // Beginning iterator for component indices + iterator begin() const { return (iterator(0)); } + + // End iterator for component indices + iterator end() const { return (iterator(this->size())); } + + // Returns a pair of begin and end iterators for the child + // elements of component [component_index]. + std::pair< component_iterator, component_iterator > operator[]( + IndexType component_index) const + { + + IndexType first_index = (*m_components)[component_index]; + + return (std::make_pair( + component_iterator(m_index_list->begin(), first_index), + component_iterator(m_num_elements))); + } + +private: + template < typename ParentIterator, typename ElementIndexMap > + void build_index_lists( + ParentIterator parent_start, const ElementIndexMap& index_map) + { + + typedef + typename std::iterator_traits< ParentIterator >::value_type Element; + typename IndexContainer::iterator index_list = m_index_list->begin(); + + // First pass - find root elements, construct index list + for (IndexType element_index = 0; element_index < m_num_elements; + ++element_index) + { + + Element parent_element = parent_start[element_index]; + IndexType parent_index = get(index_map, parent_element); + + if (element_index != parent_index) + { + index_list[element_index] = parent_index; + } + else + { + m_components->push_back(element_index); + + // m_num_elements is the linked list terminator + index_list[element_index] = m_num_elements; + } + } + + // Second pass - build linked list + for (IndexType element_index = 0; element_index < m_num_elements; + ++element_index) + { + + Element parent_element = parent_start[element_index]; + IndexType parent_index = get(index_map, parent_element); + + if (element_index != parent_index) + { + + // Follow list until a component parent is found + while (index_list[parent_index] != m_num_elements) + { + parent_index = index_list[parent_index]; + } + + // Push element to the front of the linked list + index_list[element_index] = index_list[parent_index]; + index_list[parent_index] = element_index; + } + } + + } // build_index_lists + +protected: + IndexType m_num_elements; + shared_ptr< IndexContainer > m_components, m_index_list; + +}; // class component_index + +} // namespace boost + +#endif // BOOST_INCREMENTAL_COMPONENTS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/is_kuratowski_subgraph.hpp b/contrib/restricted/boost/graph/include/boost/graph/is_kuratowski_subgraph.hpp new file mode 100644 index 0000000000..1624a96462 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/is_kuratowski_subgraph.hpp @@ -0,0 +1,295 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __IS_KURATOWSKI_SUBGRAPH_HPP__ +#define __IS_KURATOWSKI_SUBGRAPH_HPP__ + +#include <boost/config.hpp> +#include <boost/tuple/tuple.hpp> //for tie +#include <boost/property_map/property_map.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/isomorphism.hpp> +#include <boost/graph/adjacency_list.hpp> + +#include <algorithm> +#include <vector> +#include <set> + +namespace boost +{ + +namespace detail +{ + + template < typename Graph > Graph make_K_5() + { + typename graph_traits< Graph >::vertex_iterator vi, vi_end, inner_vi; + Graph K_5(5); + for (boost::tie(vi, vi_end) = vertices(K_5); vi != vi_end; ++vi) + for (inner_vi = next(vi); inner_vi != vi_end; ++inner_vi) + add_edge(*vi, *inner_vi, K_5); + return K_5; + } + + template < typename Graph > Graph make_K_3_3() + { + typename graph_traits< Graph >::vertex_iterator vi, vi_end, + bipartition_start, inner_vi; + Graph K_3_3(6); + bipartition_start = next(next(next(vertices(K_3_3).first))); + for (boost::tie(vi, vi_end) = vertices(K_3_3); vi != bipartition_start; + ++vi) + for (inner_vi = bipartition_start; inner_vi != vi_end; ++inner_vi) + add_edge(*vi, *inner_vi, K_3_3); + return K_3_3; + } + + template < typename AdjacencyList, typename Vertex > + void contract_edge(AdjacencyList& neighbors, Vertex u, Vertex v) + { + // Remove u from v's neighbor list + neighbors[v].erase( + std::remove(neighbors[v].begin(), neighbors[v].end(), u), + neighbors[v].end()); + + // Replace any references to u with references to v + typedef + typename AdjacencyList::value_type::iterator adjacency_iterator_t; + + adjacency_iterator_t u_neighbor_end = neighbors[u].end(); + for (adjacency_iterator_t u_neighbor_itr = neighbors[u].begin(); + u_neighbor_itr != u_neighbor_end; ++u_neighbor_itr) + { + Vertex u_neighbor(*u_neighbor_itr); + std::replace(neighbors[u_neighbor].begin(), + neighbors[u_neighbor].end(), u, v); + } + + // Remove v from u's neighbor list + neighbors[u].erase( + std::remove(neighbors[u].begin(), neighbors[u].end(), v), + neighbors[u].end()); + + // Add everything in u's neighbor list to v's neighbor list + std::copy(neighbors[u].begin(), neighbors[u].end(), + std::back_inserter(neighbors[v])); + + // Clear u's neighbor list + neighbors[u].clear(); + } + + enum target_graph_t + { + tg_k_3_3, + tg_k_5 + }; + +} // namespace detail + +template < typename Graph, typename ForwardIterator, typename VertexIndexMap > +bool is_kuratowski_subgraph(const Graph& g, ForwardIterator begin, + ForwardIterator end, VertexIndexMap vm) +{ + + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef typename graph_traits< Graph >::edges_size_type e_size_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + typedef typename std::vector< vertex_t > v_list_t; + typedef typename v_list_t::iterator v_list_iterator_t; + typedef iterator_property_map< typename std::vector< v_list_t >::iterator, + VertexIndexMap > + vertex_to_v_list_map_t; + + typedef adjacency_list< vecS, vecS, undirectedS > small_graph_t; + + detail::target_graph_t target_graph + = detail::tg_k_3_3; // unless we decide otherwise later + + static small_graph_t K_5(detail::make_K_5< small_graph_t >()); + + static small_graph_t K_3_3(detail::make_K_3_3< small_graph_t >()); + + v_size_t n_vertices(num_vertices(g)); + v_size_t max_num_edges(3 * n_vertices - 5); + + std::vector< v_list_t > neighbors_vector(n_vertices); + vertex_to_v_list_map_t neighbors(neighbors_vector.begin(), vm); + + e_size_t count = 0; + for (ForwardIterator itr = begin; itr != end; ++itr) + { + + if (count++ > max_num_edges) + return false; + + edge_t e(*itr); + vertex_t u(source(e, g)); + vertex_t v(target(e, g)); + + neighbors[u].push_back(v); + neighbors[v].push_back(u); + } + + for (v_size_t max_size = 2; max_size < 5; ++max_size) + { + + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + + // a hack to make sure we don't contract the middle edge of a path + // of four degree-3 vertices + if (max_size == 4 && neighbors[v].size() == 3) + { + if (neighbors[neighbors[v][0]].size() + + neighbors[neighbors[v][1]].size() + + neighbors[neighbors[v][2]].size() + < 11 // so, it has two degree-3 neighbors + ) + continue; + } + + while (neighbors[v].size() > 0 && neighbors[v].size() < max_size) + { + // Find one of v's neighbors u such that v and u + // have no neighbors in common. We'll look for such a + // neighbor with a naive cubic-time algorithm since the + // max size of any of the neighbor sets we'll consider + // merging is 3 + + bool neighbor_sets_intersect = false; + + vertex_t min_u = graph_traits< Graph >::null_vertex(); + vertex_t u; + v_list_iterator_t v_neighbor_end = neighbors[v].end(); + for (v_list_iterator_t v_neighbor_itr = neighbors[v].begin(); + v_neighbor_itr != v_neighbor_end; ++v_neighbor_itr) + { + neighbor_sets_intersect = false; + u = *v_neighbor_itr; + v_list_iterator_t u_neighbor_end = neighbors[u].end(); + for (v_list_iterator_t u_neighbor_itr + = neighbors[u].begin(); + u_neighbor_itr != u_neighbor_end + && !neighbor_sets_intersect; + ++u_neighbor_itr) + { + for (v_list_iterator_t inner_v_neighbor_itr + = neighbors[v].begin(); + inner_v_neighbor_itr != v_neighbor_end; + ++inner_v_neighbor_itr) + { + if (*u_neighbor_itr == *inner_v_neighbor_itr) + { + neighbor_sets_intersect = true; + break; + } + } + } + if (!neighbor_sets_intersect + && (min_u == graph_traits< Graph >::null_vertex() + || neighbors[u].size() < neighbors[min_u].size())) + { + min_u = u; + } + } + + if (min_u == graph_traits< Graph >::null_vertex()) + // Exited the loop without finding an appropriate neighbor + // of v, so v must be a lost cause. Move on to other + // vertices. + break; + else + u = min_u; + + detail::contract_edge(neighbors, u, v); + + } // end iteration over v's neighbors + + } // end iteration through vertices v + + if (max_size == 3) + { + // check to see whether we should go on to find a K_5 + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + if (neighbors[*vi].size() == 4) + { + target_graph = detail::tg_k_5; + break; + } + + if (target_graph == detail::tg_k_3_3) + break; + } + + } // end iteration through max degree 2,3, and 4 + + // Now, there should only be 5 or 6 vertices with any neighbors. Find them. + + v_list_t main_vertices; + vertex_iterator_t vi, vi_end; + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + if (!neighbors[*vi].empty()) + main_vertices.push_back(*vi); + } + + // create a graph isomorphic to the contracted graph to test + // against K_5 and K_3_3 + small_graph_t contracted_graph(main_vertices.size()); + std::map< vertex_t, + typename graph_traits< small_graph_t >::vertex_descriptor > + contracted_vertex_map; + + typename v_list_t::iterator itr, itr_end; + itr_end = main_vertices.end(); + typename graph_traits< small_graph_t >::vertex_iterator si + = vertices(contracted_graph).first; + + for (itr = main_vertices.begin(); itr != itr_end; ++itr, ++si) + { + contracted_vertex_map[*itr] = *si; + } + + typename v_list_t::iterator jtr, jtr_end; + for (itr = main_vertices.begin(); itr != itr_end; ++itr) + { + jtr_end = neighbors[*itr].end(); + for (jtr = neighbors[*itr].begin(); jtr != jtr_end; ++jtr) + { + if (get(vm, *itr) < get(vm, *jtr)) + { + add_edge(contracted_vertex_map[*itr], + contracted_vertex_map[*jtr], contracted_graph); + } + } + } + + if (target_graph == detail::tg_k_5) + { + return boost::isomorphism(K_5, contracted_graph); + } + else // target_graph == tg_k_3_3 + { + return boost::isomorphism(K_3_3, contracted_graph); + } +} + +template < typename Graph, typename ForwardIterator > +bool is_kuratowski_subgraph( + const Graph& g, ForwardIterator begin, ForwardIterator end) +{ + return is_kuratowski_subgraph(g, begin, end, get(vertex_index, g)); +} + +} + +#endif //__IS_KURATOWSKI_SUBGRAPH_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/is_straight_line_drawing.hpp b/contrib/restricted/boost/graph/include/boost/graph/is_straight_line_drawing.hpp new file mode 100644 index 0000000000..013f4b400a --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/is_straight_line_drawing.hpp @@ -0,0 +1,209 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __IS_STRAIGHT_LINE_DRAWING_HPP__ +#define __IS_STRAIGHT_LINE_DRAWING_HPP__ + +#include <boost/config.hpp> +#include <boost/next_prior.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/tuple/tuple_comparison.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/planar_detail/bucket_sort.hpp> + +#include <algorithm> +#include <vector> +#include <set> +#include <map> + +namespace boost +{ + +// Return true exactly when the line segments s1 = ((x1,y1), (x2,y2)) and +// s2 = ((a1,b1), (a2,b2)) intersect in a point other than the endpoints of +// the line segments. The one exception to this rule is when s1 = s2, in +// which case false is returned - this is to accomodate multiple edges +// between the same pair of vertices, which shouldn't invalidate the straight +// line embedding. A tolerance variable epsilon can also be used, which +// defines how far away from the endpoints of s1 and s2 we want to consider +// an intersection. + +inline bool intersects(double x1, double y1, double x2, double y2, double a1, + double b1, double a2, double b2, double epsilon = 0.000001) +{ + + if (x1 - x2 == 0) + { + std::swap(x1, a1); + std::swap(y1, b1); + std::swap(x2, a2); + std::swap(y2, b2); + } + + if (x1 - x2 == 0) + { + BOOST_USING_STD_MAX(); + BOOST_USING_STD_MIN(); + + // two vertical line segments + double min_y = min BOOST_PREVENT_MACRO_SUBSTITUTION(y1, y2); + double max_y = max BOOST_PREVENT_MACRO_SUBSTITUTION(y1, y2); + double min_b = min BOOST_PREVENT_MACRO_SUBSTITUTION(b1, b2); + double max_b = max BOOST_PREVENT_MACRO_SUBSTITUTION(b1, b2); + if ((max_y > max_b && max_b > min_y) + || (max_b > max_y && max_y > min_b)) + return true; + else + return false; + } + + double x_diff = x1 - x2; + double y_diff = y1 - y2; + double a_diff = a2 - a1; + double b_diff = b2 - b1; + + double beta_denominator = b_diff - (y_diff / ((double)x_diff)) * a_diff; + + if (beta_denominator == 0) + { + // parallel lines + return false; + } + + double beta = (b2 - y2 - (y_diff / ((double)x_diff)) * (a2 - x2)) + / beta_denominator; + double alpha = (a2 - x2 - beta * (a_diff)) / x_diff; + + double upper_bound = 1 - epsilon; + double lower_bound = 0 + epsilon; + + return (beta < upper_bound && beta > lower_bound && alpha < upper_bound + && alpha > lower_bound); +} + +template < typename Graph, typename GridPositionMap, typename VertexIndexMap > +bool is_straight_line_drawing( + const Graph& g, GridPositionMap drawing, VertexIndexMap) +{ + + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + + typedef std::size_t x_coord_t; + typedef std::size_t y_coord_t; + typedef boost::tuple< edge_t, x_coord_t, y_coord_t > edge_event_t; + typedef typename std::vector< edge_event_t > edge_event_queue_t; + + typedef tuple< y_coord_t, y_coord_t, x_coord_t, x_coord_t > + active_map_key_t; + typedef edge_t active_map_value_t; + typedef std::map< active_map_key_t, active_map_value_t > active_map_t; + typedef typename active_map_t::iterator active_map_iterator_t; + + edge_event_queue_t edge_event_queue; + active_map_t active_edges; + + edge_iterator_t ei, ei_end; + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + vertex_t s(source(e, g)); + vertex_t t(target(e, g)); + edge_event_queue.push_back( + make_tuple(e, static_cast< std::size_t >(drawing[s].x), + static_cast< std::size_t >(drawing[s].y))); + edge_event_queue.push_back( + make_tuple(e, static_cast< std::size_t >(drawing[t].x), + static_cast< std::size_t >(drawing[t].y))); + } + + // Order by edge_event_queue by first, then second coordinate + // (bucket_sort is a stable sort.) + bucket_sort(edge_event_queue.begin(), edge_event_queue.end(), + property_map_tuple_adaptor< edge_event_t, 2 >()); + + bucket_sort(edge_event_queue.begin(), edge_event_queue.end(), + property_map_tuple_adaptor< edge_event_t, 1 >()); + + typedef typename edge_event_queue_t::iterator event_queue_iterator_t; + event_queue_iterator_t itr_end = edge_event_queue.end(); + for (event_queue_iterator_t itr = edge_event_queue.begin(); itr != itr_end; + ++itr) + { + edge_t e(get< 0 >(*itr)); + vertex_t source_v(source(e, g)); + vertex_t target_v(target(e, g)); + if (drawing[source_v].y > drawing[target_v].y) + std::swap(source_v, target_v); + + active_map_key_t key(get(drawing, source_v).y, get(drawing, target_v).y, + get(drawing, source_v).x, get(drawing, target_v).x); + + active_map_iterator_t a_itr = active_edges.find(key); + if (a_itr == active_edges.end()) + { + active_edges[key] = e; + } + else + { + active_map_iterator_t before, after; + if (a_itr == active_edges.begin()) + before = active_edges.end(); + else + before = prior(a_itr); + after = boost::next(a_itr); + + if (before != active_edges.end()) + { + + edge_t f = before->second; + vertex_t e_source(source(e, g)); + vertex_t e_target(target(e, g)); + vertex_t f_source(source(f, g)); + vertex_t f_target(target(f, g)); + + if (intersects(drawing[e_source].x, drawing[e_source].y, + drawing[e_target].x, drawing[e_target].y, + drawing[f_source].x, drawing[f_source].y, + drawing[f_target].x, drawing[f_target].y)) + return false; + } + + if (after != active_edges.end()) + { + + edge_t f = after->second; + vertex_t e_source(source(e, g)); + vertex_t e_target(target(e, g)); + vertex_t f_source(source(f, g)); + vertex_t f_target(target(f, g)); + + if (intersects(drawing[e_source].x, drawing[e_source].y, + drawing[e_target].x, drawing[e_target].y, + drawing[f_source].x, drawing[f_source].y, + drawing[f_target].x, drawing[f_target].y)) + return false; + } + + active_edges.erase(a_itr); + } + } + + return true; +} + +template < typename Graph, typename GridPositionMap > +bool is_straight_line_drawing(const Graph& g, GridPositionMap drawing) +{ + return is_straight_line_drawing(g, drawing, get(vertex_index, g)); +} + +} + +#endif // __IS_STRAIGHT_LINE_DRAWING_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/isomorphism.hpp b/contrib/restricted/boost/graph/include/boost/graph/isomorphism.hpp new file mode 100644 index 0000000000..5a7d31ddc6 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/isomorphism.hpp @@ -0,0 +1,781 @@ +// Copyright (C) 2001 Jeremy Siek, Douglas Gregor, Brian Osman +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_GRAPH_ISOMORPHISM_HPP +#define BOOST_GRAPH_ISOMORPHISM_HPP + +#include <utility> +#include <vector> +#include <iterator> +#include <algorithm> +#include <boost/config.hpp> +#include <boost/assert.hpp> +#include <boost/smart_ptr.hpp> +#include <boost/graph/depth_first_search.hpp> +#include <boost/detail/algorithm.hpp> +#include <boost/unordered_map.hpp> +#include <boost/unordered/unordered_flat_map.hpp> +#include <boost/pending/indirect_cmp.hpp> // for make_indirect_pmap +#include <boost/concept/assert.hpp> + +#ifndef BOOST_GRAPH_ITERATION_MACROS_HPP +#define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file +#include <boost/graph/iteration_macros.hpp> +#endif + +namespace boost +{ + +namespace detail +{ + + template < typename Graph1, typename Graph2, typename IsoMapping, + typename Invariant1, typename Invariant2, typename IndexMap1, + typename IndexMap2, typename InvariantCountMap = boost::unordered_flat_map<typename Invariant1::result_type, typename graph_traits< Graph1 >::vertices_size_type > > + class isomorphism_algo + { + typedef typename graph_traits< Graph1 >::vertex_descriptor vertex1_t; + typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_t; + typedef typename graph_traits< Graph1 >::edge_descriptor edge1_t; + typedef typename graph_traits< Graph1 >::vertices_size_type size_type; + typedef typename Invariant1::result_type invariant_t; + + const Graph1& G1; + const Graph2& G2; + IsoMapping f; + Invariant1 invariant1; + Invariant2 invariant2; + IndexMap1 index_map1; + IndexMap2 index_map2; + + std::vector< vertex1_t > dfs_vertices; + typedef typename std::vector< vertex1_t >::iterator vertex_iter; + std::vector< int > dfs_num_vec; + typedef safe_iterator_property_map< + typename std::vector< int >::iterator, IndexMap1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , + int, int& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > + DFSNumMap; + DFSNumMap dfs_num; + std::vector< edge1_t > ordered_edges; + typedef typename std::vector< edge1_t >::iterator edge_iter; + + std::vector< char > in_S_vec; + typedef safe_iterator_property_map< + typename std::vector< char >::iterator, IndexMap2 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , + char, char& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > + InSMap; + InSMap in_S; + + int num_edges_on_k; + + friend struct compare_multiplicity; + struct compare_multiplicity + { + compare_multiplicity(Invariant1 invariant1, const InvariantCountMap& multiplicity) + : invariant1(invariant1), multiplicity(&multiplicity) + { + } + bool operator()(const vertex1_t& x, const vertex1_t& y) const + { + auto x_multiplicity_iter = multiplicity->find(invariant1(x)); + assert(x_multiplicity_iter != multiplicity->end()); + auto y_multiplicity_iter = multiplicity->find(invariant1(y)); + assert(y_multiplicity_iter != multiplicity->end()); + return *x_multiplicity_iter < *y_multiplicity_iter; + } + Invariant1 invariant1; + const InvariantCountMap* multiplicity; + }; + + struct record_dfs_order : default_dfs_visitor + { + record_dfs_order( + std::vector< vertex1_t >& v, std::vector< edge1_t >& e) + : vertices(v), edges(e) + { + } + + void discover_vertex(vertex1_t v, const Graph1&) const + { + vertices.push_back(v); + } + void examine_edge(edge1_t e, const Graph1&) const + { + edges.push_back(e); + } + std::vector< vertex1_t >& vertices; + std::vector< edge1_t >& edges; + }; + + struct edge_cmp + { + edge_cmp(const Graph1& G1, DFSNumMap dfs_num) + : G1(G1), dfs_num(dfs_num) + { + } + bool operator()(const edge1_t& e1, const edge1_t& e2) const + { + using namespace std; + int u1 = dfs_num[source(e1, G1)], v1 = dfs_num[target(e1, G1)]; + int u2 = dfs_num[source(e2, G1)], v2 = dfs_num[target(e2, G1)]; + int m1 = (max)(u1, v1); + int m2 = (max)(u2, v2); + // lexicographical comparison + return std::make_pair(m1, std::make_pair(u1, v1)) + < std::make_pair(m2, std::make_pair(u2, v2)); + } + const Graph1& G1; + DFSNumMap dfs_num; + }; + + public: + isomorphism_algo(const Graph1& G1, const Graph2& G2, IsoMapping f, + Invariant1 invariant1, Invariant2 invariant2, + std::size_t /* max_invariant */, IndexMap1 index_map1, + IndexMap2 index_map2) + : G1(G1) + , G2(G2) + , f(f) + , invariant1(invariant1) + , invariant2(invariant2) + , index_map1(index_map1) + , index_map2(index_map2) + { + in_S_vec.resize(num_vertices(G1)); + in_S = make_safe_iterator_property_map( + in_S_vec.begin(), in_S_vec.size(), index_map2 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , + in_S_vec.front() +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + ); + } + + // Generates map of invariant multiplicity from sorted invariants + template<typename ForwardIterator> + InvariantCountMap multiplicities(ForwardIterator first, const ForwardIterator last) + { + typedef typename InvariantCountMap::iterator invar_map_iter; + + assert(std::is_sorted(first, last)); + InvariantCountMap invar_multiplicity; + + if(first == last) + return invar_multiplicity; + + invariant_t invar = *first; + invar_map_iter inserted = invar_multiplicity.emplace(invar, 1).first; + ++first; + for(; first != last; ++first) + { + if(*first == invar) + { + inserted->second += 1; + } + else + { + invar = *first; + inserted = invar_multiplicity.emplace(invar, 1).first; + } + } + + return invar_multiplicity; + } + + bool test_isomorphism() + { + // reset isomapping + BGL_FORALL_VERTICES_T(v, G1, Graph1) + f[v] = graph_traits< Graph2 >::null_vertex(); + + // Calculate all invariants of G1 and G2, sort and compare + std::vector< invariant_t > invar1_array; + invar1_array.reserve(num_vertices(G1)); + BGL_FORALL_VERTICES_T(v, G1, Graph1) + invar1_array.push_back(invariant1(v)); + sort(invar1_array); + + std::vector< invariant_t > invar2_array; + invar2_array.reserve(num_vertices(G2)); + BGL_FORALL_VERTICES_T(v, G2, Graph2) + invar2_array.push_back(invariant2(v)); + sort(invar2_array); + if (!equal(invar1_array, invar2_array)) + return false; + + // Sort vertices by the multiplicity of their invariants + std::vector< vertex1_t > V_mult; + BGL_FORALL_VERTICES_T(v, G1, Graph1) + V_mult.push_back(v); + sort(V_mult, compare_multiplicity(invariant1, multiplicities(invar1_array.begin(), invar1_array.end()))); + + std::vector< default_color_type > color_vec(num_vertices(G1)); + safe_iterator_property_map< + std::vector< default_color_type >::iterator, IndexMap1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , + default_color_type, default_color_type& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > + color_map(color_vec.begin(), color_vec.size(), index_map1); + record_dfs_order dfs_visitor(dfs_vertices, ordered_edges); + typedef color_traits< default_color_type > Color; + for (vertex_iter u = V_mult.begin(); u != V_mult.end(); ++u) + { + if (color_map[*u] == Color::white()) + { + dfs_visitor.start_vertex(*u, G1); + depth_first_visit(G1, *u, dfs_visitor, color_map); + } + } + // Create the dfs_num array and dfs_num_map + dfs_num_vec.resize(num_vertices(G1)); + dfs_num = make_safe_iterator_property_map( + dfs_num_vec.begin(), dfs_num_vec.size(), index_map1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , + dfs_num_vec.front() +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + ); + size_type n = 0; + for (vertex_iter v = dfs_vertices.begin(); v != dfs_vertices.end(); + ++v) + dfs_num[*v] = n++; + + sort(ordered_edges, edge_cmp(G1, dfs_num)); + + int dfs_num_k = -1; + return this->match(ordered_edges.begin(), dfs_num_k); + } + + private: + struct match_continuation + { + enum + { + pos_G2_vertex_loop, + pos_fi_adj_loop, + pos_dfs_num + } position; + typedef typename graph_traits< Graph2 >::vertex_iterator + vertex_iterator; + std::pair< vertex_iterator, vertex_iterator > G2_verts; + typedef typename graph_traits< Graph2 >::adjacency_iterator + adjacency_iterator; + std::pair< adjacency_iterator, adjacency_iterator > fi_adj; + edge_iter iter; + int dfs_num_k; + }; + + bool match(edge_iter iter, int dfs_num_k) + { + std::vector< match_continuation > k; + typedef typename graph_traits< Graph2 >::vertex_iterator + vertex_iterator; + std::pair< vertex_iterator, vertex_iterator > G2_verts( + vertices(G2)); + typedef typename graph_traits< Graph2 >::adjacency_iterator + adjacency_iterator; + std::pair< adjacency_iterator, adjacency_iterator > fi_adj; + vertex1_t i, j; + + recur: + if (iter != ordered_edges.end()) + { + i = source(*iter, G1); + j = target(*iter, G1); + if (dfs_num[i] > dfs_num_k) + { + G2_verts = vertices(G2); + while (G2_verts.first != G2_verts.second) + { + { + vertex2_t u = *G2_verts.first; + vertex1_t kp1 = dfs_vertices[dfs_num_k + 1]; + if (invariant1(kp1) == invariant2(u) + && in_S[u] == false) + { + { + f[kp1] = u; + in_S[u] = true; + num_edges_on_k = 0; + + match_continuation new_k; + new_k.position = match_continuation:: + pos_G2_vertex_loop; + new_k.G2_verts = G2_verts; + new_k.iter = iter; + new_k.dfs_num_k = dfs_num_k; + k.push_back(new_k); + ++dfs_num_k; + goto recur; + } + } + } + G2_loop_k: + ++G2_verts.first; + } + } + else if (dfs_num[j] > dfs_num_k) + { + { + vertex1_t vk = dfs_vertices[dfs_num_k]; + num_edges_on_k -= count_if(adjacent_vertices(f[vk], G2), + make_indirect_pmap(in_S)); + + for (int jj = 0; jj < dfs_num_k; ++jj) + { + vertex1_t j = dfs_vertices[jj]; + num_edges_on_k + -= count(adjacent_vertices(f[j], G2), f[vk]); + } + } + + if (num_edges_on_k != 0) + goto return_point_false; + fi_adj = adjacent_vertices(f[i], G2); + while (fi_adj.first != fi_adj.second) + { + { + vertex2_t v = *fi_adj.first; + if (invariant2(v) == invariant1(j) + && in_S[v] == false) + { + f[j] = v; + in_S[v] = true; + num_edges_on_k = 1; + BOOST_USING_STD_MAX(); + int next_k + = max BOOST_PREVENT_MACRO_SUBSTITUTION( + dfs_num_k, + max BOOST_PREVENT_MACRO_SUBSTITUTION( + dfs_num[i], dfs_num[j])); + match_continuation new_k; + new_k.position + = match_continuation::pos_fi_adj_loop; + new_k.fi_adj = fi_adj; + new_k.iter = iter; + new_k.dfs_num_k = dfs_num_k; + ++iter; + dfs_num_k = next_k; + k.push_back(new_k); + goto recur; + } + } + fi_adj_loop_k: + ++fi_adj.first; + } + } + else + { + if (container_contains(adjacent_vertices(f[i], G2), f[j])) + { + ++num_edges_on_k; + match_continuation new_k; + new_k.position = match_continuation::pos_dfs_num; + k.push_back(new_k); + ++iter; + goto recur; + } + } + } + else + goto return_point_true; + goto return_point_false; + + { + return_point_true: + // At this point, there may still be null vertices in the + // mapping for disconnected vertices + map_disconnected_vertices(); + return true; + + return_point_false: + if (k.empty()) + return false; + const match_continuation& this_k = k.back(); + switch (this_k.position) + { + case match_continuation::pos_G2_vertex_loop: + { + G2_verts = this_k.G2_verts; + iter = this_k.iter; + dfs_num_k = this_k.dfs_num_k; + k.pop_back(); + in_S[*G2_verts.first] = false; + i = source(*iter, G1); + j = target(*iter, G1); + goto G2_loop_k; + } + case match_continuation::pos_fi_adj_loop: + { + fi_adj = this_k.fi_adj; + iter = this_k.iter; + dfs_num_k = this_k.dfs_num_k; + k.pop_back(); + in_S[*fi_adj.first] = false; + i = source(*iter, G1); + j = target(*iter, G1); + goto fi_adj_loop_k; + } + case match_continuation::pos_dfs_num: + { + k.pop_back(); + goto return_point_false; + } + default: + { + BOOST_ASSERT(!"Bad position"); +#ifdef UNDER_CE + exit(-1); +#else + abort(); +#endif + } + } + } + } + + void map_disconnected_vertices() + { + std::vector< vertex1_t > unmatched_g1_vertices; + BGL_FORALL_VERTICES_T(v, G1, Graph1) + { + if(f[v] == graph_traits< Graph2 >::null_vertex()) { + unmatched_g1_vertices.push_back(v); + } + } + + if(!unmatched_g1_vertices.empty()) + { + typedef unordered_multimap< invariant_t, vertex2_t > g2_invariant_vertex_multimap; + typedef typename g2_invariant_vertex_multimap::iterator multimap_iter; + g2_invariant_vertex_multimap unmatched_invariants; + BGL_FORALL_VERTICES_T(v, G2, Graph2) + { + if(!in_S[v]) + { + unmatched_invariants.emplace(invariant2(v), v); + } + } + + typedef typename std::vector< vertex1_t >::iterator v1_iter; + const v1_iter end = unmatched_g1_vertices.end(); + for(v1_iter iter = unmatched_g1_vertices.begin(); iter != end; ++iter) + { + invariant_t unmatched_g1_vertex_invariant = invariant1(*iter); + multimap_iter matching_invariant = unmatched_invariants.find(unmatched_g1_vertex_invariant); + BOOST_ASSERT(matching_invariant != unmatched_invariants.end()); + f[*iter] = matching_invariant->second; + unmatched_invariants.erase(matching_invariant); + } + } + } + }; + + template < typename Graph, typename InDegreeMap > + void compute_in_degree(const Graph& g, InDegreeMap in_degree_map) + { + BGL_FORALL_VERTICES_T(v, g, Graph) + put(in_degree_map, v, 0); + + BGL_FORALL_VERTICES_T(u, g, Graph) + BGL_FORALL_ADJ_T(u, v, g, Graph) + put(in_degree_map, v, get(in_degree_map, v) + 1); + } + +} // namespace detail + +template < typename InDegreeMap, typename Graph > class degree_vertex_invariant +{ + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::degree_size_type size_type; + +public: + typedef vertex_t argument_type; + typedef size_type result_type; + + degree_vertex_invariant(const InDegreeMap& in_degree_map, const Graph& g) + : m_in_degree_map(in_degree_map) + , m_max_vertex_in_degree(0) + , m_max_vertex_out_degree(0) + , m_g(g) + { + BGL_FORALL_VERTICES_T(v, g, Graph) + { + m_max_vertex_in_degree + = (std::max)(m_max_vertex_in_degree, get(m_in_degree_map, v)); + m_max_vertex_out_degree + = (std::max)(m_max_vertex_out_degree, out_degree(v, g)); + } + } + + size_type operator()(vertex_t v) const + { + return (m_max_vertex_in_degree + 1) * out_degree(v, m_g) + + get(m_in_degree_map, v); + } + // The largest possible vertex invariant number + size_type max BOOST_PREVENT_MACRO_SUBSTITUTION() const + { + return (m_max_vertex_in_degree + 1) * (m_max_vertex_out_degree + 1); + } + +private: + InDegreeMap m_in_degree_map; + size_type m_max_vertex_in_degree; + size_type m_max_vertex_out_degree; + const Graph& m_g; +}; + +// Count actual number of vertices, even in filtered graphs. +template < typename Graph > size_t count_vertices(const Graph& g) +{ + size_t n = 0; + BGL_FORALL_VERTICES_T(v, g, Graph) + { + (void)v; + ++n; + } + return n; +} + +template < typename Graph1, typename Graph2, typename IsoMapping, + typename Invariant1, typename Invariant2, typename IndexMap1, + typename IndexMap2 > +bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f, + Invariant1 invariant1, Invariant2 invariant2, std::size_t /* max_invariant */, + IndexMap1 index_map1, IndexMap2 index_map2) + +{ + // Graph requirements + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph1 >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph1 >)); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph2 >)); + // BOOST_CONCEPT_ASSERT(( BidirectionalGraphConcept<Graph2> )); + + typedef typename graph_traits< Graph1 >::vertex_descriptor vertex1_t; + typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_t; + typedef typename graph_traits< Graph1 >::vertices_size_type size_type; + + typedef typename Invariant1::result_type invariant1_t; + typedef typename Invariant2::result_type invariant2_t; + + BOOST_STATIC_ASSERT(is_same<invariant1_t, invariant2_t>::value); + + // Vertex invariant requirement + BOOST_CONCEPT_ASSERT( + (AdaptableUnaryFunctionConcept< Invariant1, invariant1_t, vertex1_t >)); + BOOST_CONCEPT_ASSERT( + (AdaptableUnaryFunctionConcept< Invariant2, invariant2_t, vertex2_t >)); + + // Property map requirements + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< IsoMapping, vertex1_t >)); + typedef typename property_traits< IsoMapping >::value_type IsoMappingValue; + BOOST_STATIC_ASSERT((is_convertible< IsoMappingValue, vertex2_t >::value)); + + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< IndexMap1, vertex1_t >)); + typedef typename property_traits< IndexMap1 >::value_type IndexMap1Value; + BOOST_STATIC_ASSERT((is_convertible< IndexMap1Value, size_type >::value)); + + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< IndexMap2, vertex2_t >)); + typedef typename property_traits< IndexMap2 >::value_type IndexMap2Value; + BOOST_STATIC_ASSERT((is_convertible< IndexMap2Value, size_type >::value)); + + if (count_vertices(G1) != count_vertices(G2)) + return false; + if (count_vertices(G1) == 0 && count_vertices(G2) == 0) + return true; + + detail::isomorphism_algo< Graph1, Graph2, IsoMapping, Invariant1, + Invariant2, IndexMap1, IndexMap2 > + algo(G1, G2, f, invariant1, invariant2, 0, index_map1, + index_map2); + return algo.test_isomorphism(); +} + +namespace detail +{ + + template < typename Graph1, typename Graph2, typename IsoMapping, + typename IndexMap1, typename IndexMap2, typename P, typename T, + typename R > + bool isomorphism_impl(const Graph1& G1, const Graph2& G2, IsoMapping f, + IndexMap1 index_map1, IndexMap2 index_map2, + const bgl_named_params< P, T, R >& params) + { + std::vector< std::size_t > in_degree1_vec(num_vertices(G1)); + typedef safe_iterator_property_map< + std::vector< std::size_t >::iterator, IndexMap1 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , + std::size_t, std::size_t& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > + InDeg1; + InDeg1 in_degree1( + in_degree1_vec.begin(), in_degree1_vec.size(), index_map1); + compute_in_degree(G1, in_degree1); + + std::vector< std::size_t > in_degree2_vec(num_vertices(G2)); + typedef safe_iterator_property_map< + std::vector< std::size_t >::iterator, IndexMap2 +#ifdef BOOST_NO_STD_ITERATOR_TRAITS + , + std::size_t, std::size_t& +#endif /* BOOST_NO_STD_ITERATOR_TRAITS */ + > + InDeg2; + InDeg2 in_degree2( + in_degree2_vec.begin(), in_degree2_vec.size(), index_map2); + compute_in_degree(G2, in_degree2); + + degree_vertex_invariant< InDeg1, Graph1 > invariant1(in_degree1, G1); + degree_vertex_invariant< InDeg2, Graph2 > invariant2(in_degree2, G2); + + return isomorphism(G1, G2, f, + choose_param(get_param(params, vertex_invariant1_t()), invariant1), + choose_param(get_param(params, vertex_invariant2_t()), invariant2), + 0, + index_map1, index_map2); + } + + template < typename G, typename Index > struct make_degree_invariant + { + const G& g; + const Index& index; + make_degree_invariant(const G& g, const Index& index) + : g(g), index(index) + { + } + typedef typename boost::graph_traits< G >::degree_size_type + degree_size_type; + typedef shared_array_property_map< degree_size_type, Index > + prop_map_type; + typedef degree_vertex_invariant< prop_map_type, G > result_type; + result_type operator()() const + { + prop_map_type pm = make_shared_array_property_map( + num_vertices(g), degree_size_type(), index); + compute_in_degree(g, pm); + return result_type(pm, g); + } + }; + +} // namespace detail + +namespace graph +{ + namespace detail + { + template < typename Graph1, typename Graph2 > struct isomorphism_impl + { + typedef bool result_type; + typedef result_type type; + template < typename ArgPack > + bool operator()(const Graph1& g1, const Graph2& g2, + const ArgPack& arg_pack) const + { + using namespace boost::graph::keywords; + typedef typename boost::detail::override_const_property_result< + ArgPack, tag::vertex_index1_map, boost::vertex_index_t, + Graph1 >::type index1_map_type; + typedef typename boost::detail::override_const_property_result< + ArgPack, tag::vertex_index2_map, boost::vertex_index_t, + Graph2 >::type index2_map_type; + index1_map_type index1_map + = boost::detail::override_const_property( + arg_pack, _vertex_index1_map, g1, boost::vertex_index); + index2_map_type index2_map + = boost::detail::override_const_property( + arg_pack, _vertex_index2_map, g2, boost::vertex_index); + typedef typename graph_traits< Graph2 >::vertex_descriptor + vertex2_t; + typename std::vector< vertex2_t >::size_type n + = (typename std::vector< vertex2_t >::size_type) + num_vertices(g1); + std::vector< vertex2_t > f(n); + typename boost::parameter::lazy_binding< ArgPack, + tag::vertex_invariant1, + boost::detail::make_degree_invariant< Graph1, + index1_map_type > >::type invariant1 + = arg_pack[_vertex_invariant1 + || boost::detail::make_degree_invariant< Graph1, + index1_map_type >(g1, index1_map)]; + typename boost::parameter::lazy_binding< ArgPack, + tag::vertex_invariant2, + boost::detail::make_degree_invariant< Graph2, + index2_map_type > >::type invariant2 + = arg_pack[_vertex_invariant2 + || boost::detail::make_degree_invariant< Graph2, + index2_map_type >(g2, index2_map)]; + return boost::isomorphism(g1, g2, + choose_param( + arg_pack[_isomorphism_map | boost::param_not_found()], + make_shared_array_property_map( + num_vertices(g1), vertex2_t(), index1_map)), + invariant1, invariant2, + 0, + index1_map, index2_map); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(isomorphism, 2, 6) +} + +// Named parameter interface +BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(isomorphism, 2) + +// Verify that the given mapping iso_map from the vertices of g1 to the +// vertices of g2 describes an isomorphism. +// Note: this could be made much faster by specializing based on the graph +// concepts modeled, but since we're verifying an O(n^(lg n)) algorithm, +// O(n^4) won't hurt us. +template < typename Graph1, typename Graph2, typename IsoMap > +inline bool verify_isomorphism( + const Graph1& g1, const Graph2& g2, IsoMap iso_map) +{ +#if 0 + // problematic for filtered_graph! + if (num_vertices(g1) != num_vertices(g2) || num_edges(g1) != num_edges(g2)) + return false; +#endif + + BGL_FORALL_EDGES_T(e1, g1, Graph1) + { + bool found_edge = false; + BGL_FORALL_EDGES_T(e2, g2, Graph2) + { + if (source(e2, g2) == get(iso_map, source(e1, g1)) + && target(e2, g2) == get(iso_map, target(e1, g1))) + { + found_edge = true; + } + } + + if (!found_edge) + return false; + } + + return true; +} + +} // namespace boost + +#ifdef BOOST_ISO_INCLUDED_ITER_MACROS +#undef BOOST_ISO_INCLUDED_ITER_MACROS +#include <boost/graph/iteration_macros_undef.hpp> +#endif + +#endif // BOOST_GRAPH_ISOMORPHISM_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/iteration_macros_undef.hpp b/contrib/restricted/boost/graph/include/boost/graph/iteration_macros_undef.hpp new file mode 100644 index 0000000000..0b3f4174df --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/iteration_macros_undef.hpp @@ -0,0 +1,22 @@ +//======================================================================= +// Copyright 2002 Indiana University. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifdef BOOST_GRAPH_ITERATION_MACROS_HPP + +#undef BOOST_GRAPH_ITERATION_MACROS_HPP +#undef BGL_CAT +#undef BGL_FIRST +#undef BGL_LAST +#undef BGL_FORALL_VERTICES +#undef BGL_FORALL_EDGES +#undef BGL_FORALL_ADJACENT +#undef BGL_FORALL_OUTEDGES +#undef BGL_FORALL_INEDGES + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/johnson_all_pairs_shortest.hpp b/contrib/restricted/boost/graph/include/boost/graph/johnson_all_pairs_shortest.hpp new file mode 100644 index 0000000000..2cc4697a11 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/johnson_all_pairs_shortest.hpp @@ -0,0 +1,198 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +/* + This file implements the function + + template <class VertexAndEdgeListGraph, class DistanceMatrix, + class P, class T, class R> + bool + johnson_all_pairs_shortest_paths + (VertexAndEdgeListGraph& g, + DistanceMatrix& D, + const bgl_named_params<P, T, R>& params) + */ + +#ifndef BOOST_GRAPH_JOHNSON_HPP +#define BOOST_GRAPH_JOHNSON_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/property_map/shared_array_property_map.hpp> +#include <boost/graph/bellman_ford_shortest_paths.hpp> +#include <boost/graph/dijkstra_shortest_paths.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/type_traits/same_traits.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +template < class VertexAndEdgeListGraph, class DistanceMatrix, class VertexID, + class Weight, typename BinaryPredicate, typename BinaryFunction, + typename Infinity, class DistanceZero > +bool johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1, + DistanceMatrix& D, VertexID id1, Weight w1, const BinaryPredicate& compare, + const BinaryFunction& combine, const Infinity& inf, DistanceZero zero) +{ + typedef graph_traits< VertexAndEdgeListGraph > Traits1; + typedef typename property_traits< Weight >::value_type DT; + BOOST_CONCEPT_ASSERT((BasicMatrixConcept< DistanceMatrix, + typename Traits1::vertices_size_type, DT >)); + + typedef typename Traits1::directed_category DirCat; + bool is_undirected = is_same< DirCat, undirected_tag >::value; + + typedef adjacency_list< vecS, vecS, directedS, + property< vertex_distance_t, DT >, + property< edge_weight_t, DT, property< edge_weight2_t, DT > > > + Graph2; + typedef graph_traits< Graph2 > Traits2; + + Graph2 g2(num_vertices(g1) + 1); + typename property_map< Graph2, edge_weight_t >::type w + = get(edge_weight, g2); + typename property_map< Graph2, edge_weight2_t >::type w_hat + = get(edge_weight2, g2); + typename property_map< Graph2, vertex_distance_t >::type d + = get(vertex_distance, g2); + typedef typename property_map< Graph2, vertex_index_t >::type VertexID2; + VertexID2 id2 = get(vertex_index, g2); + + // Construct g2 where V[g2] = V[g1] U {s} + // and E[g2] = E[g1] U {(s,v)| v in V[g1]} + std::vector< typename Traits1::vertex_descriptor > verts1( + num_vertices(g1) + 1); + typename Traits2::vertex_descriptor s = *vertices(g2).first; + { + typename Traits1::vertex_iterator v, v_end; + int i = 1; + for (boost::tie(v, v_end) = vertices(g1); v != v_end; ++v, ++i) + { + typename Traits2::edge_descriptor e; + bool z; + boost::tie(e, z) = add_edge(s, get(id1, *v) + 1, g2); + put(w, e, zero); + verts1[i] = *v; + } + typename Traits1::edge_iterator e, e_end; + for (boost::tie(e, e_end) = edges(g1); e != e_end; ++e) + { + typename Traits2::edge_descriptor e2; + bool z; + boost::tie(e2, z) = add_edge( + get(id1, source(*e, g1)) + 1, get(id1, target(*e, g1)) + 1, g2); + put(w, e2, get(w1, *e)); + if (is_undirected) + { + boost::tie(e2, z) = add_edge(get(id1, target(*e, g1)) + 1, + get(id1, source(*e, g1)) + 1, g2); + put(w, e2, get(w1, *e)); + } + } + } + typename Traits2::vertex_iterator v, v_end, u, u_end; + typename Traits2::edge_iterator e, e_end; + shared_array_property_map< DT, VertexID2 > h(num_vertices(g2), id2); + + for (boost::tie(v, v_end) = vertices(g2); v != v_end; ++v) + put(d, *v, inf); + + put(d, s, zero); + // Using the non-named parameter versions of bellman_ford and + // dijkstra for portability reasons. + dummy_property_map pred; + bellman_visitor<> bvis; + if (bellman_ford_shortest_paths( + g2, num_vertices(g2), w, pred, d, combine, compare, bvis)) + { + for (boost::tie(v, v_end) = vertices(g2); v != v_end; ++v) + put(h, *v, get(d, *v)); + // Reweight the edges to remove negatives + for (boost::tie(e, e_end) = edges(g2); e != e_end; ++e) + { + typename Traits2::vertex_descriptor a = source(*e, g2), + b = target(*e, g2); + put(w_hat, *e, combine((get(h, a) - get(h, b)), get(w, *e))); + } + for (boost::tie(u, u_end) = vertices(g2); u != u_end; ++u) + { + dijkstra_visitor<> dvis; + dijkstra_shortest_paths( + g2, *u, pred, d, w_hat, id2, compare, combine, inf, zero, dvis); + for (boost::tie(v, v_end) = vertices(g2); v != v_end; ++v) + { + if (*u != s && *v != s) + { + D[get(id2, *u) - 1][get(id2, *v) - 1] + = combine((get(h, *v) - get(h, *u)), get(d, *v)); + } + } + } + return true; + } + else + return false; +} + +template < class VertexAndEdgeListGraph, class DistanceMatrix, class VertexID, + class Weight, class DistanceZero > +bool johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g1, + DistanceMatrix& D, VertexID id1, Weight w1, DistanceZero zero) +{ + typedef typename property_traits< Weight >::value_type WT; + return johnson_all_pairs_shortest_paths(g1, D, id1, w1, std::less< WT >(), + closed_plus< WT >(), (std::numeric_limits< WT >::max)(), zero); +} + +namespace detail +{ + + template < class VertexAndEdgeListGraph, class DistanceMatrix, class P, + class T, class R, class Weight, class VertexID > + bool johnson_dispatch(VertexAndEdgeListGraph& g, DistanceMatrix& D, + const bgl_named_params< P, T, R >& params, Weight w, VertexID id) + { + typedef typename property_traits< Weight >::value_type WT; + + return johnson_all_pairs_shortest_paths(g, D, id, w, + choose_param( + get_param(params, distance_compare_t()), std::less< WT >()), + choose_param( + get_param(params, distance_combine_t()), closed_plus< WT >()), + choose_param(get_param(params, distance_inf_t()), + std::numeric_limits< WT >::max + BOOST_PREVENT_MACRO_SUBSTITUTION()), + choose_param(get_param(params, distance_zero_t()), WT())); + } + +} // namespace detail + +template < class VertexAndEdgeListGraph, class DistanceMatrix, class P, class T, + class R > +bool johnson_all_pairs_shortest_paths(VertexAndEdgeListGraph& g, + DistanceMatrix& D, const bgl_named_params< P, T, R >& params) +{ + return detail::johnson_dispatch(g, D, params, + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index)); +} + +template < class VertexAndEdgeListGraph, class DistanceMatrix > +bool johnson_all_pairs_shortest_paths( + VertexAndEdgeListGraph& g, DistanceMatrix& D) +{ + bgl_named_params< int, int > params(1); + return detail::johnson_dispatch( + g, D, params, get(edge_weight, g), get(vertex_index, g)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_JOHNSON_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/kamada_kawai_spring_layout.hpp b/contrib/restricted/boost/graph/include/boost/graph/kamada_kawai_spring_layout.hpp new file mode 100644 index 0000000000..148ebd9ee9 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/kamada_kawai_spring_layout.hpp @@ -0,0 +1,688 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP +#define BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/topology.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/johnson_all_pairs_shortest.hpp> +#include <boost/type_traits/is_convertible.hpp> +#include <utility> +#include <iterator> +#include <vector> +#include <iostream> +#include <boost/limits.hpp> +#include <boost/config/no_tr1/cmath.hpp> + +namespace boost +{ +namespace detail +{ + namespace graph + { + /** + * Denotes an edge or display area side length used to scale a + * Kamada-Kawai drawing. + */ + template < bool Edge, typename T > struct edge_or_side + { + explicit edge_or_side(T value) : value(value) {} + + T value; + }; + + /** + * Compute the edge length from an edge length. This is trivial. + */ + template < typename Graph, typename DistanceMap, typename IndexMap, + typename T > + T compute_edge_length( + const Graph&, DistanceMap, IndexMap, edge_or_side< true, T > length) + { + return length.value; + } + + /** + * Compute the edge length based on the display area side + length. We do this by dividing the side length by the largest + shortest distance between any two vertices in the graph. + */ + template < typename Graph, typename DistanceMap, typename IndexMap, + typename T > + T compute_edge_length(const Graph& g, DistanceMap distance, + IndexMap index, edge_or_side< false, T > length) + { + T result(0); + + typedef + typename graph_traits< Graph >::vertex_iterator vertex_iterator; + + for (vertex_iterator ui = vertices(g).first, + end = vertices(g).second; + ui != end; ++ui) + { + vertex_iterator vi = ui; + for (++vi; vi != end; ++vi) + { + T dij = distance[get(index, *ui)][get(index, *vi)]; + if (dij > result) + result = dij; + } + } + return length.value / result; + } + + /** + * Dense linear solver for fixed-size matrices. + */ + template < std::size_t Size > struct linear_solver + { + // Indices in mat are (row, column) + // template <typename Vec> + // static Vec solve(double mat[Size][Size], Vec rhs); + }; + + template <> struct linear_solver< 1 > + { + template < typename Vec > + static Vec solve(double mat[1][1], Vec rhs) + { + return rhs / mat[0][0]; + } + }; + + // These are from http://en.wikipedia.org/wiki/Cramer%27s_rule + template <> struct linear_solver< 2 > + { + template < typename Vec > + static Vec solve(double mat[2][2], Vec rhs) + { + double denom = mat[0][0] * mat[1][1] - mat[1][0] * mat[0][1]; + double x_num = rhs[0] * mat[1][1] - rhs[1] * mat[0][1]; + double y_num = mat[0][0] * rhs[1] - mat[1][0] * rhs[0]; + Vec result; + result[0] = x_num / denom; + result[1] = y_num / denom; + return result; + } + }; + + template <> struct linear_solver< 3 > + { + template < typename Vec > + static Vec solve(double mat[3][3], Vec rhs) + { + double denom = mat[0][0] + * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2]) + - mat[1][0] + * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2]) + + mat[2][0] + * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]); + double x_num + = rhs[0] * (mat[1][1] * mat[2][2] - mat[2][1] * mat[1][2]) + - rhs[1] * (mat[0][1] * mat[2][2] - mat[2][1] * mat[0][2]) + + rhs[2] * (mat[0][1] * mat[1][2] - mat[1][1] * mat[0][2]); + double y_num + = mat[0][0] * (rhs[1] * mat[2][2] - rhs[2] * mat[1][2]) + - mat[1][0] * (rhs[0] * mat[2][2] - rhs[2] * mat[0][2]) + + mat[2][0] * (rhs[0] * mat[1][2] - rhs[1] * mat[0][2]); + double z_num + = mat[0][0] * (mat[1][1] * rhs[2] - mat[2][1] * rhs[1]) + - mat[1][0] * (mat[0][1] * rhs[2] - mat[2][1] * rhs[0]) + + mat[2][0] * (mat[0][1] * rhs[1] - mat[1][1] * rhs[0]); + Vec result; + result[0] = x_num / denom; + result[1] = y_num / denom; + result[2] = z_num / denom; + return result; + } + }; + + /** + * Implementation of the Kamada-Kawai spring layout algorithm. + */ + template < typename Topology, typename Graph, typename PositionMap, + typename WeightMap, typename EdgeOrSideLength, typename Done, + typename VertexIndexMap, typename DistanceMatrix, + typename SpringStrengthMatrix, typename PartialDerivativeMap > + struct kamada_kawai_spring_layout_impl + { + typedef + typename property_traits< WeightMap >::value_type weight_type; + typedef typename Topology::point_type Point; + typedef + typename Topology::point_difference_type point_difference_type; + typedef point_difference_type deriv_type; + typedef + typename graph_traits< Graph >::vertex_iterator vertex_iterator; + typedef typename graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + + kamada_kawai_spring_layout_impl(const Topology& topology, + const Graph& g, PositionMap position, WeightMap weight, + EdgeOrSideLength edge_or_side_length, Done done, + weight_type spring_constant, VertexIndexMap index, + DistanceMatrix distance, SpringStrengthMatrix spring_strength, + PartialDerivativeMap partial_derivatives) + : topology(topology) + , g(g) + , position(position) + , weight(weight) + , edge_or_side_length(edge_or_side_length) + , done(done) + , spring_constant(spring_constant) + , index(index) + , distance(distance) + , spring_strength(spring_strength) + , partial_derivatives(partial_derivatives) + { + } + + // Compute contribution of vertex i to the first partial + // derivatives (dE/dx_m, dE/dy_m) (for vertex m) + deriv_type compute_partial_derivative( + vertex_descriptor m, vertex_descriptor i) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + + deriv_type result; + if (i != m) + { + point_difference_type diff + = topology.difference(position[m], position[i]); + weight_type dist = topology.norm(diff); + result = spring_strength[get(index, m)][get(index, i)] + * (diff + - distance[get(index, m)][get(index, i)] / dist + * diff); + } + + return result; + } + + // Compute partial derivatives dE/dx_m and dE/dy_m + deriv_type compute_partial_derivatives(vertex_descriptor m) + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + + deriv_type result; + + // TBD: looks like an accumulate to me + BGL_FORALL_VERTICES_T(i, g, Graph) + { + deriv_type deriv = compute_partial_derivative(m, i); + result += deriv; + } + + return result; + } + + // The actual Kamada-Kawai spring layout algorithm implementation + bool run() + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::sqrt; +#endif // BOOST_NO_STDC_NAMESPACE + + // Compute d_{ij} and place it in the distance matrix + if (!johnson_all_pairs_shortest_paths( + g, distance, index, weight, weight_type(0))) + return false; + + // Compute L based on side length (if needed), or retrieve L + weight_type edge_length = detail::graph::compute_edge_length( + g, distance, index, edge_or_side_length); + + // std::cerr << "edge_length = " << edge_length << std::endl; + + // Compute l_{ij} and k_{ij} + const weight_type K = spring_constant; + vertex_iterator ui, end; + for (ui = vertices(g).first, end = vertices(g).second; + ui != end; ++ui) + { + vertex_iterator vi = ui; + for (++vi; vi != end; ++vi) + { + weight_type dij + = distance[get(index, *ui)][get(index, *vi)]; + if (dij == (std::numeric_limits< weight_type >::max)()) + return false; + distance[get(index, *ui)][get(index, *vi)] + = edge_length * dij; + distance[get(index, *vi)][get(index, *ui)] + = edge_length * dij; + spring_strength[get(index, *ui)][get(index, *vi)] + = K / (dij * dij); + spring_strength[get(index, *vi)][get(index, *ui)] + = K / (dij * dij); + } + } + + // Compute Delta_i and find max + vertex_descriptor p = *vertices(g).first; + weight_type delta_p(0); + + for (ui = vertices(g).first, end = vertices(g).second; + ui != end; ++ui) + { + deriv_type deriv = compute_partial_derivatives(*ui); + put(partial_derivatives, *ui, deriv); + + weight_type delta = topology.norm(deriv); + + if (delta > delta_p) + { + p = *ui; + delta_p = delta; + } + } + + while (!done(delta_p, p, g, true)) + { + // The contribution p makes to the partial derivatives of + // each vertex. Computing this (at O(n) cost) allows us to + // update the delta_i values in O(n) time instead of O(n^2) + // time. + std::vector< deriv_type > p_partials(num_vertices(g)); + for (ui = vertices(g).first, end = vertices(g).second; + ui != end; ++ui) + { + vertex_descriptor i = *ui; + p_partials[get(index, i)] + = compute_partial_derivative(i, p); + } + + do + { + // For debugging, compute the energy value E + double E = 0.; + for (ui = vertices(g).first, end = vertices(g).second; + ui != end; ++ui) + { + vertex_iterator vi = ui; + for (++vi; vi != end; ++vi) + { + double dist = topology.distance( + position[*ui], position[*vi]); + weight_type k_ij = spring_strength[get( + index, *ui)][get(index, *vi)]; + weight_type l_ij = distance[get(index, *ui)] + [get(index, *vi)]; + E += .5 * k_ij * (dist - l_ij) * (dist - l_ij); + } + } + // std::cerr << "E = " << E << std::endl; + + // Compute the elements of the Jacobian + // From + // http://www.cs.panam.edu/~rfowler/papers/1994_kumar_fowler_A_Spring_UTPACSTR.pdf + // with the bugs fixed in the off-diagonal case + weight_type dE_d_d[Point::dimensions] + [Point::dimensions]; + for (std::size_t i = 0; i < Point::dimensions; ++i) + for (std::size_t j = 0; j < Point::dimensions; ++j) + dE_d_d[i][j] = 0.; + for (ui = vertices(g).first, end = vertices(g).second; + ui != end; ++ui) + { + vertex_descriptor i = *ui; + if (i != p) + { + point_difference_type diff + = topology.difference( + position[p], position[i]); + weight_type dist = topology.norm(diff); + weight_type dist_squared = dist * dist; + weight_type inv_dist_cubed + = 1. / (dist_squared * dist); + weight_type k_mi = spring_strength[get( + index, p)][get(index, i)]; + weight_type l_mi + = distance[get(index, p)][get(index, i)]; + for (std::size_t i = 0; i < Point::dimensions; + ++i) + { + for (std::size_t j = 0; + j < Point::dimensions; ++j) + { + if (i == j) + { + dE_d_d[i][i] += k_mi + * (1 + + (l_mi + * (diff[i] * diff[i] + - dist_squared) + * inv_dist_cubed)); + } + else + { + dE_d_d[i][j] += k_mi * l_mi + * diff[i] * diff[j] + * inv_dist_cubed; + // dE_d_d[i][j] += k_mi * l_mi * + // sqrt(hypot(diff[i], diff[j])) * + // inv_dist_cubed; + } + } + } + } + } + + deriv_type dE_d = get(partial_derivatives, p); + + // Solve dE_d_d * delta = -dE_d to get delta + point_difference_type delta + = -linear_solver< Point::dimensions >::solve( + dE_d_d, dE_d); + + // Move p by delta + position[p] = topology.adjust(position[p], delta); + + // Recompute partial derivatives and delta_p + deriv_type deriv = compute_partial_derivatives(p); + put(partial_derivatives, p, deriv); + + delta_p = topology.norm(deriv); + } while (!done(delta_p, p, g, false)); + + // Select new p by updating each partial derivative and + // delta + vertex_descriptor old_p = p; + for (ui = vertices(g).first, end = vertices(g).second; + ui != end; ++ui) + { + deriv_type old_deriv_p = p_partials[get(index, *ui)]; + deriv_type old_p_partial + = compute_partial_derivative(*ui, old_p); + deriv_type deriv = get(partial_derivatives, *ui); + + deriv += old_p_partial - old_deriv_p; + + put(partial_derivatives, *ui, deriv); + weight_type delta = topology.norm(deriv); + + if (delta > delta_p) + { + p = *ui; + delta_p = delta; + } + } + } + + return true; + } + + const Topology& topology; + const Graph& g; + PositionMap position; + WeightMap weight; + EdgeOrSideLength edge_or_side_length; + Done done; + weight_type spring_constant; + VertexIndexMap index; + DistanceMatrix distance; + SpringStrengthMatrix spring_strength; + PartialDerivativeMap partial_derivatives; + }; + } +} // end namespace detail::graph + +/// States that the given quantity is an edge length. +template < typename T > +inline detail::graph::edge_or_side< true, T > edge_length(T x) +{ + return detail::graph::edge_or_side< true, T >(x); +} + +/// States that the given quantity is a display area side length. +template < typename T > +inline detail::graph::edge_or_side< false, T > side_length(T x) +{ + return detail::graph::edge_or_side< false, T >(x); +} + +/** + * \brief Determines when to terminate layout of a particular graph based + * on a given relative tolerance. + */ +template < typename T = double > struct layout_tolerance +{ + layout_tolerance(const T& tolerance = T(0.001)) + : tolerance(tolerance) + , last_energy((std::numeric_limits< T >::max)()) + , last_local_energy((std::numeric_limits< T >::max)()) + { + } + + template < typename Graph > + bool operator()(T delta_p, + typename boost::graph_traits< Graph >::vertex_descriptor p, + const Graph& g, bool global) + { + if (global) + { + if (last_energy == (std::numeric_limits< T >::max)()) + { + last_energy = delta_p; + return false; + } + + T diff = last_energy - delta_p; + if (diff < T(0)) + diff = -diff; + bool done = (delta_p == T(0) || diff / last_energy < tolerance); + last_energy = delta_p; + return done; + } + else + { + if (last_local_energy == (std::numeric_limits< T >::max)()) + { + last_local_energy = delta_p; + return delta_p == T(0); + } + + T diff = last_local_energy - delta_p; + bool done + = (delta_p == T(0) || (diff / last_local_energy) < tolerance); + last_local_energy = delta_p; + return done; + } + } + +private: + T tolerance; + T last_energy; + T last_local_energy; +}; + +/** \brief Kamada-Kawai spring layout for undirected graphs. + * + * This algorithm performs graph layout (in two dimensions) for + * connected, undirected graphs. It operates by relating the layout + * of graphs to a dynamic spring system and minimizing the energy + * within that system. The strength of a spring between two vertices + * is inversely proportional to the square of the shortest distance + * (in graph terms) between those two vertices. Essentially, + * vertices that are closer in the graph-theoretic sense (i.e., by + * following edges) will have stronger springs and will therefore be + * placed closer together. + * + * Prior to invoking this algorithm, it is recommended that the + * vertices be placed along the vertices of a regular n-sided + * polygon. + * + * \param g (IN) must be a model of Vertex List Graph, Edge List + * Graph, and Incidence Graph and must be undirected. + * + * \param position (OUT) must be a model of Lvalue Property Map, + * where the value type is a class containing fields @c x and @c y + * that will be set to the @c x and @c y coordinates of each vertex. + * + * \param weight (IN) must be a model of Readable Property Map, + * which provides the weight of each edge in the graph @p g. + * + * \param topology (IN) must be a topology object (see topology.hpp), + * which provides operations on points and differences between them. + * + * \param edge_or_side_length (IN) provides either the unit length + * @c e of an edge in the layout or the length of a side @c s of the + * display area, and must be either @c boost::edge_length(e) or @c + * boost::side_length(s), respectively. + * + * \param done (IN) is a 4-argument function object that is passed + * the current value of delta_p (i.e., the energy of vertex @p p), + * the vertex @p p, the graph @p g, and a boolean flag indicating + * whether @p delta_p is the maximum energy in the system (when @c + * true) or the energy of the vertex being moved. Defaults to @c + * layout_tolerance instantiated over the value type of the weight + * map. + * + * \param spring_constant (IN) is the constant multiplied by each + * spring's strength. Larger values create systems with more energy + * that can take longer to stabilize; smaller values create systems + * with less energy that stabilize quickly but do not necessarily + * result in pleasing layouts. The default value is 1. + * + * \param index (IN) is a mapping from vertices to index values + * between 0 and @c num_vertices(g). The default is @c + * get(vertex_index,g). + * + * \param distance (UTIL/OUT) will be used to store the distance + * from every vertex to every other vertex, which is computed in the + * first stages of the algorithm. This value's type must be a model + * of BasicMatrix with value type equal to the value type of the + * weight map. The default is a vector of vectors. + * + * \param spring_strength (UTIL/OUT) will be used to store the + * strength of the spring between every pair of vertices. This + * value's type must be a model of BasicMatrix with value type equal + * to the value type of the weight map. The default is a vector of + * vectors. + * + * \param partial_derivatives (UTIL) will be used to store the + * partial derivates of each vertex with respect to the @c x and @c + * y coordinates. This must be a Read/Write Property Map whose value + * type is a pair with both types equivalent to the value type of + * the weight map. The default is an iterator property map. + * + * \returns @c true if layout was successful or @c false if a + * negative weight cycle was detected. + */ +template < typename Topology, typename Graph, typename PositionMap, + typename WeightMap, typename T, bool EdgeOrSideLength, typename Done, + typename VertexIndexMap, typename DistanceMatrix, + typename SpringStrengthMatrix, typename PartialDerivativeMap > +bool kamada_kawai_spring_layout(const Graph& g, PositionMap position, + WeightMap weight, const Topology& topology, + detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length, + Done done, + typename property_traits< WeightMap >::value_type spring_constant, + VertexIndexMap index, DistanceMatrix distance, + SpringStrengthMatrix spring_strength, + PartialDerivativeMap partial_derivatives) +{ + BOOST_STATIC_ASSERT( + (is_convertible< typename graph_traits< Graph >::directed_category*, + undirected_tag* >::value)); + + detail::graph::kamada_kawai_spring_layout_impl< Topology, Graph, + PositionMap, WeightMap, + detail::graph::edge_or_side< EdgeOrSideLength, T >, Done, + VertexIndexMap, DistanceMatrix, SpringStrengthMatrix, + PartialDerivativeMap > + alg(topology, g, position, weight, edge_or_side_length, done, + spring_constant, index, distance, spring_strength, + partial_derivatives); + return alg.run(); +} + +/** + * \overload + */ +template < typename Topology, typename Graph, typename PositionMap, + typename WeightMap, typename T, bool EdgeOrSideLength, typename Done, + typename VertexIndexMap > +bool kamada_kawai_spring_layout(const Graph& g, PositionMap position, + WeightMap weight, const Topology& topology, + detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length, + Done done, + typename property_traits< WeightMap >::value_type spring_constant, + VertexIndexMap index) +{ + typedef typename property_traits< WeightMap >::value_type weight_type; + + typename graph_traits< Graph >::vertices_size_type n = num_vertices(g); + typedef std::vector< weight_type > weight_vec; + + std::vector< weight_vec > distance(n, weight_vec(n)); + std::vector< weight_vec > spring_strength(n, weight_vec(n)); + std::vector< typename Topology::point_difference_type > partial_derivatives( + n); + + return kamada_kawai_spring_layout(g, position, weight, topology, + edge_or_side_length, done, spring_constant, index, distance.begin(), + spring_strength.begin(), + make_iterator_property_map(partial_derivatives.begin(), index, + typename Topology::point_difference_type())); +} + +/** + * \overload + */ +template < typename Topology, typename Graph, typename PositionMap, + typename WeightMap, typename T, bool EdgeOrSideLength, typename Done > +bool kamada_kawai_spring_layout(const Graph& g, PositionMap position, + WeightMap weight, const Topology& topology, + detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length, + Done done, + typename property_traits< WeightMap >::value_type spring_constant) +{ + return kamada_kawai_spring_layout(g, position, weight, topology, + edge_or_side_length, done, spring_constant, get(vertex_index, g)); +} + +/** + * \overload + */ +template < typename Topology, typename Graph, typename PositionMap, + typename WeightMap, typename T, bool EdgeOrSideLength, typename Done > +bool kamada_kawai_spring_layout(const Graph& g, PositionMap position, + WeightMap weight, const Topology& topology, + detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length, + Done done) +{ + typedef typename property_traits< WeightMap >::value_type weight_type; + return kamada_kawai_spring_layout(g, position, weight, topology, + edge_or_side_length, done, weight_type(1)); +} + +/** + * \overload + */ +template < typename Topology, typename Graph, typename PositionMap, + typename WeightMap, typename T, bool EdgeOrSideLength > +bool kamada_kawai_spring_layout(const Graph& g, PositionMap position, + WeightMap weight, const Topology& topology, + detail::graph::edge_or_side< EdgeOrSideLength, T > edge_or_side_length) +{ + typedef typename property_traits< WeightMap >::value_type weight_type; + return kamada_kawai_spring_layout(g, position, weight, topology, + edge_or_side_length, layout_tolerance< weight_type >(), + weight_type(1.0), get(vertex_index, g)); +} +} // end namespace boost + +#endif // BOOST_GRAPH_KAMADA_KAWAI_SPRING_LAYOUT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/king_ordering.hpp b/contrib/restricted/boost/graph/include/boost/graph/king_ordering.hpp new file mode 100644 index 0000000000..6a0bd93944 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/king_ordering.hpp @@ -0,0 +1,346 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004, 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, +// Doug Gregor, D. Kevin McGrath +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//=======================================================================// +#ifndef BOOST_GRAPH_KING_HPP +#define BOOST_GRAPH_KING_HPP + +#include <deque> +#include <vector> +#include <algorithm> +#include <boost/config.hpp> +#include <boost/bind/bind.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/graph/detail/sparse_ordering.hpp> +#include <boost/graph/graph_utility.hpp> + +/* + King Algorithm for matrix reordering +*/ + +namespace boost +{ +namespace detail +{ + template < typename OutputIterator, typename Buffer, typename Compare, + typename PseudoDegreeMap, typename VecMap, typename VertexIndexMap > + class bfs_king_visitor : public default_bfs_visitor + { + public: + bfs_king_visitor(OutputIterator* iter, Buffer* b, Compare compare, + PseudoDegreeMap deg, std::vector< int > loc, VecMap color, + VertexIndexMap vertices) + : permutation(iter) + , Qptr(b) + , degree(deg) + , comp(compare) + , Qlocation(loc) + , colors(color) + , vertex_map(vertices) + { + } + + template < typename Vertex, typename Graph > + void finish_vertex(Vertex, Graph& g) + { + using namespace boost::placeholders; + + typename graph_traits< Graph >::out_edge_iterator ei, ei_end; + Vertex v, w; + + typedef typename std::deque< Vertex >::reverse_iterator + reverse_iterator; + + reverse_iterator rend = Qptr->rend() - index_begin; + reverse_iterator rbegin = Qptr->rbegin(); + + // heap the vertices already there + std::make_heap(rbegin, rend, boost::bind< bool >(comp, _2, _1)); + + unsigned i = 0; + + for (i = index_begin; i != Qptr->size(); ++i) + { + colors[get(vertex_map, (*Qptr)[i])] = 1; + Qlocation[get(vertex_map, (*Qptr)[i])] = i; + } + + i = 0; + + for (; rbegin != rend; rend--) + { + percolate_down< Vertex >(i); + w = (*Qptr)[index_begin + i]; + for (boost::tie(ei, ei_end) = out_edges(w, g); ei != ei_end; + ++ei) + { + v = target(*ei, g); + put(degree, v, get(degree, v) - 1); + + if (colors[get(vertex_map, v)] == 1) + { + percolate_up< Vertex >(get(vertex_map, v), i); + } + } + + colors[get(vertex_map, w)] = 0; + i++; + } + } + + template < typename Vertex, typename Graph > + void examine_vertex(Vertex u, const Graph&) + { + + *(*permutation)++ = u; + index_begin = Qptr->size(); + } + + protected: + // this function replaces pop_heap, and tracks state information + template < typename Vertex > void percolate_down(int offset) + { + int heap_last = index_begin + offset; + int heap_first = Qptr->size() - 1; + + // pop_heap functionality: + // swap first, last + std::swap((*Qptr)[heap_last], (*Qptr)[heap_first]); + + // swap in the location queue + std::swap(Qlocation[heap_first], Qlocation[heap_last]); + + // set drifter, children + int drifter = heap_first; + int drifter_heap = Qptr->size() - drifter; + + int right_child_heap = drifter_heap * 2 + 1; + int right_child = Qptr->size() - right_child_heap; + + int left_child_heap = drifter_heap * 2; + int left_child = Qptr->size() - left_child_heap; + + // check that we are staying in the heap + bool valid = (right_child < heap_last) ? false : true; + + // pick smallest child of drifter, and keep in mind there might only + // be left child + int smallest_child = (valid + && get(degree, (*Qptr)[left_child]) + > get(degree, (*Qptr)[right_child])) + ? right_child + : left_child; + + while (valid && smallest_child < heap_last + && comp((*Qptr)[drifter], (*Qptr)[smallest_child])) + { + + // if smallest child smaller than drifter, swap them + std::swap((*Qptr)[smallest_child], (*Qptr)[drifter]); + std::swap(Qlocation[drifter], Qlocation[smallest_child]); + + // update the values, run again, as necessary + drifter = smallest_child; + drifter_heap = Qptr->size() - drifter; + + right_child_heap = drifter_heap * 2 + 1; + right_child = Qptr->size() - right_child_heap; + + left_child_heap = drifter_heap * 2; + left_child = Qptr->size() - left_child_heap; + + valid = (right_child < heap_last) ? false : true; + + smallest_child = (valid + && get(degree, (*Qptr)[left_child]) + > get(degree, (*Qptr)[right_child])) + ? right_child + : left_child; + } + } + + // this is like percolate down, but we always compare against the + // parent, as there is only a single choice + template < typename Vertex > void percolate_up(int vertex, int offset) + { + + int child_location = Qlocation[vertex]; + int heap_child_location = Qptr->size() - child_location; + int heap_parent_location = (int)(heap_child_location / 2); + unsigned parent_location = Qptr->size() - heap_parent_location; + + bool valid = (heap_parent_location != 0 + && child_location > index_begin + offset + && parent_location < Qptr->size()); + + while (valid + && comp((*Qptr)[child_location], (*Qptr)[parent_location])) + { + + // swap in the heap + std::swap((*Qptr)[child_location], (*Qptr)[parent_location]); + + // swap in the location queue + std::swap( + Qlocation[child_location], Qlocation[parent_location]); + + child_location = parent_location; + heap_child_location = heap_parent_location; + heap_parent_location = (int)(heap_child_location / 2); + parent_location = Qptr->size() - heap_parent_location; + valid = (heap_parent_location != 0 + && child_location > index_begin + offset); + } + } + + OutputIterator* permutation; + int index_begin; + Buffer* Qptr; + PseudoDegreeMap degree; + Compare comp; + std::vector< int > Qlocation; + VecMap colors; + VertexIndexMap vertex_map; + }; + +} // namespace detail + +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap, + typename VertexIndexMap > +OutputIterator king_ordering(const Graph& g, + std::deque< typename graph_traits< Graph >::vertex_descriptor > + vertex_queue, + OutputIterator permutation, ColorMap color, DegreeMap degree, + VertexIndexMap index_map) +{ + typedef typename property_traits< DegreeMap >::value_type ds_type; + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef iterator_property_map< typename std::vector< ds_type >::iterator, + VertexIndexMap, ds_type, ds_type& > + PseudoDegreeMap; + typedef indirect_cmp< PseudoDegreeMap, std::less< ds_type > > Compare; + typedef typename boost::sparse::sparse_ordering_queue< Vertex > queue; + typedef typename detail::bfs_king_visitor< OutputIterator, queue, Compare, + PseudoDegreeMap, std::vector< int >, VertexIndexMap > + Visitor; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + std::vector< ds_type > pseudo_degree_vec(num_vertices(g)); + PseudoDegreeMap pseudo_degree(pseudo_degree_vec.begin(), index_map); + + typename graph_traits< Graph >::vertex_iterator ui, ui_end; + queue Q; + // Copy degree to pseudo_degree + // initialize the color map + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + put(pseudo_degree, *ui, get(degree, *ui)); + put(color, *ui, Color::white()); + } + + Compare comp(pseudo_degree); + std::vector< int > colors(num_vertices(g)); + + for (vertices_size_type i = 0; i < num_vertices(g); i++) + colors[i] = 0; + + std::vector< int > loc(num_vertices(g)); + + // create the visitor + Visitor vis(&permutation, &Q, comp, pseudo_degree, loc, colors, index_map); + + while (!vertex_queue.empty()) + { + Vertex s = vertex_queue.front(); + vertex_queue.pop_front(); + + // call BFS with visitor + breadth_first_visit(g, s, Q, vis, color); + } + + return permutation; +} + +// This is the case where only a single starting vertex is supplied. +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap, + typename VertexIndexMap > +OutputIterator king_ordering(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + OutputIterator permutation, ColorMap color, DegreeMap degree, + VertexIndexMap index_map) +{ + + std::deque< typename graph_traits< Graph >::vertex_descriptor > + vertex_queue; + vertex_queue.push_front(s); + return king_ordering( + g, vertex_queue, permutation, color, degree, index_map); +} + +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap, + class VertexIndexMap > +OutputIterator king_ordering(const Graph& G, OutputIterator permutation, + ColorMap color, DegreeMap degree, VertexIndexMap index_map) +{ + if (has_no_vertices(G)) + return permutation; + + typedef typename boost::graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + + std::deque< Vertex > vertex_queue; + + // Mark everything white + BGL_FORALL_VERTICES_T(v, G, Graph) put(color, v, Color::white()); + + // Find one vertex from each connected component + BGL_FORALL_VERTICES_T(v, G, Graph) + { + if (get(color, v) == Color::white()) + { + depth_first_visit(G, v, dfs_visitor<>(), color); + vertex_queue.push_back(v); + } + } + + // Find starting nodes for all vertices + // TBD: How to do this with a directed graph? + for (typename std::deque< Vertex >::iterator i = vertex_queue.begin(); + i != vertex_queue.end(); ++i) + *i = find_starting_node(G, *i, color, degree); + + return king_ordering( + G, vertex_queue, permutation, color, degree, index_map); +} + +template < typename Graph, typename OutputIterator, typename VertexIndexMap > +OutputIterator king_ordering( + const Graph& G, OutputIterator permutation, VertexIndexMap index_map) +{ + if (has_no_vertices(G)) + return permutation; + + std::vector< default_color_type > colors(num_vertices(G)); + return king_ordering(G, permutation, + make_iterator_property_map(&colors[0], index_map, colors[0]), + make_out_degree_map(G), index_map); +} + +template < typename Graph, typename OutputIterator > +inline OutputIterator king_ordering(const Graph& G, OutputIterator permutation) +{ + return king_ordering(G, permutation, get(vertex_index, G)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_KING_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/kruskal_min_spanning_tree.hpp b/contrib/restricted/boost/graph/include/boost/graph/kruskal_min_spanning_tree.hpp new file mode 100644 index 0000000000..1e91feb49c --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/kruskal_min_spanning_tree.hpp @@ -0,0 +1,152 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_MST_KRUSKAL_HPP +#define BOOST_GRAPH_MST_KRUSKAL_HPP + +/* + *Minimum Spanning Tree + * Kruskal Algorithm + * + *Requirement: + * undirected graph + */ + +#include <vector> +#include <queue> +#include <functional> + +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/pending/disjoint_sets.hpp> +#include <boost/pending/indirect_cmp.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +// Kruskal's algorithm for Minimum Spanning Tree +// +// This is a greedy algorithm to calculate the Minimum Spanning Tree +// for an undirected graph with weighted edges. The output will be a +// set of edges. +// + +namespace detail +{ + + template < class Graph, class OutputIterator, class Rank, class Parent, + class Weight > + void kruskal_mst_impl(const Graph& G, OutputIterator spanning_tree_edges, + Rank rank, Parent parent, Weight weight) + { + if (num_vertices(G) == 0) + return; // Nothing to do in this case + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::edge_descriptor Edge; + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((OutputIteratorConcept< OutputIterator, Edge >)); + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< Rank, Vertex >)); + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< Parent, Vertex >)); + BOOST_CONCEPT_ASSERT((ReadablePropertyMapConcept< Weight, Edge >)); + typedef typename property_traits< Weight >::value_type W_value; + typedef typename property_traits< Rank >::value_type R_value; + typedef typename property_traits< Parent >::value_type P_value; + BOOST_CONCEPT_ASSERT((ComparableConcept< W_value >)); + BOOST_CONCEPT_ASSERT((ConvertibleConcept< P_value, Vertex >)); + BOOST_CONCEPT_ASSERT((IntegerConcept< R_value >)); + + disjoint_sets< Rank, Parent > dset(rank, parent); + + typename graph_traits< Graph >::vertex_iterator ui, uiend; + for (boost::tie(ui, uiend) = vertices(G); ui != uiend; ++ui) + dset.make_set(*ui); + + typedef indirect_cmp< Weight, std::greater< W_value > > weight_greater; + weight_greater wl(weight); + std::priority_queue< Edge, std::vector< Edge >, weight_greater > Q(wl); + /*push all edge into Q*/ + typename graph_traits< Graph >::edge_iterator ei, eiend; + for (boost::tie(ei, eiend) = edges(G); ei != eiend; ++ei) + Q.push(*ei); + + while (!Q.empty()) + { + Edge e = Q.top(); + Q.pop(); + Vertex u = dset.find_set(source(e, G)); + Vertex v = dset.find_set(target(e, G)); + if (u != v) + { + *spanning_tree_edges++ = e; + dset.link(u, v); + } + } + } + +} // namespace detail + +// Named Parameters Variants + +template < class Graph, class OutputIterator > +inline void kruskal_minimum_spanning_tree( + const Graph& g, OutputIterator spanning_tree_edges) +{ + typedef typename graph_traits< Graph >::vertices_size_type size_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + if (num_vertices(g) == 0) + return; // Nothing to do in this case + typename graph_traits< Graph >::vertices_size_type n = num_vertices(g); + std::vector< size_type > rank_map(n); + std::vector< vertex_t > pred_map(n); + + detail::kruskal_mst_impl(g, spanning_tree_edges, + make_iterator_property_map( + rank_map.begin(), get(vertex_index, g), rank_map[0]), + make_iterator_property_map( + pred_map.begin(), get(vertex_index, g), pred_map[0]), + get(edge_weight, g)); +} + +template < class Graph, class OutputIterator, class P, class T, class R > +inline void kruskal_minimum_spanning_tree(const Graph& g, + OutputIterator spanning_tree_edges, + const bgl_named_params< P, T, R >& params) +{ + typedef typename graph_traits< Graph >::vertices_size_type size_type; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + if (num_vertices(g) == 0) + return; // Nothing to do in this case + typename graph_traits< Graph >::vertices_size_type n; + n = is_default_param(get_param(params, vertex_rank)) ? num_vertices(g) : 1; + std::vector< size_type > rank_map(n); + n = is_default_param(get_param(params, vertex_predecessor)) + ? num_vertices(g) + : 1; + std::vector< vertex_t > pred_map(n); + + detail::kruskal_mst_impl(g, spanning_tree_edges, + choose_param(get_param(params, vertex_rank), + make_iterator_property_map(rank_map.begin(), + choose_pmap(get_param(params, vertex_index), g, vertex_index), + rank_map[0])), + choose_param(get_param(params, vertex_predecessor), + make_iterator_property_map(pred_map.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index), + pred_map[0])), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_MST_KRUSKAL_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/labeled_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/labeled_graph.hpp new file mode 100644 index 0000000000..1c7706e101 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/labeled_graph.hpp @@ -0,0 +1,1010 @@ +// Copyright (C) 2009 Andrew Sutton + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_LABELED_GRAPH_HPP +#define BOOST_GRAPH_LABELED_GRAPH_HPP + +#include <boost/config.hpp> +#include <vector> +#include <map> + +#include <boost/static_assert.hpp> +#include <boost/mpl/if.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/unordered_map.hpp> +#include <boost/type_traits/is_same.hpp> +#include <boost/type_traits/is_unsigned.hpp> +#include <boost/pending/container_traits.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/property_map/property_map.hpp> + +// This file implements a utility for creating mappings from arbitrary +// identifiers to the vertices of a graph. + +namespace boost +{ + +// A type selector that denotes the use of some default value. +struct defaultS +{ +}; + +/** @internal */ +namespace graph_detail +{ + /** Returns true if the selector is the default selector. */ + template < typename Selector > + struct is_default : mpl::bool_< is_same< Selector, defaultS >::value > + { + }; + + /** + * Choose the default map instance. If Label is an unsigned integral type + * the we can use a vector to store the information. + */ + template < typename Label, typename Vertex > struct choose_default_map + { + typedef typename mpl::if_< is_unsigned< Label >, std::vector< Vertex >, + std::map< Label, Vertex > // TODO: Should use unordered_map? + >::type type; + }; + + /** + * @name Generate Label Map + * These type generators are responsible for instantiating an associative + * container for the the labeled graph. Note that the Selector must be + * select a pair associative container or a vecS, which is only valid if + * Label is an integral type. + */ + //@{ + template < typename Selector, typename Label, typename Vertex > + struct generate_label_map + { + }; + + template < typename Label, typename Vertex > + struct generate_label_map< vecS, Label, Vertex > + { + typedef std::vector< Vertex > type; + }; + + template < typename Label, typename Vertex > + struct generate_label_map< mapS, Label, Vertex > + { + typedef std::map< Label, Vertex > type; + }; + + template < typename Label, typename Vertex > + struct generate_label_map< multimapS, Label, Vertex > + { + typedef std::multimap< Label, Vertex > type; + }; + + template < typename Label, typename Vertex > + struct generate_label_map< hash_mapS, Label, Vertex > + { + typedef boost::unordered_map< Label, Vertex > type; + }; + + template < typename Label, typename Vertex > + struct generate_label_map< hash_multimapS, Label, Vertex > + { + typedef boost::unordered_multimap< Label, Vertex > type; + }; + + template < typename Selector, typename Label, typename Vertex > + struct choose_custom_map + { + typedef + typename generate_label_map< Selector, Label, Vertex >::type type; + }; + //@} + + /** + * Choose and instantiate an "associative" container. Note that this can + * also choose vector. + */ + template < typename Selector, typename Label, typename Vertex > + struct choose_map + { + typedef typename mpl::eval_if< is_default< Selector >, + choose_default_map< Label, Vertex >, + choose_custom_map< Selector, Label, Vertex > >::type type; + }; + + /** @name Insert Labeled Vertex */ + //@{ + // Tag dispatch on random access containers (i.e., vectors). This function + // basically requires a) that Container is vector<Label> and that Label + // is an unsigned integral value. Note that this will resize the vector + // to accommodate indices. + template < typename Container, typename Graph, typename Label, + typename Prop > + std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > + insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p, + random_access_container_tag) + { + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + // If the label is out of bounds, resize the vector to accommodate. + // Resize by 2x the index so we don't cause quadratic insertions over + // time. + if (l >= c.size()) + { + c.resize((l + 1) * 2); + } + Vertex v = add_vertex(p, g); + c[l] = v; + return std::make_pair(c[l], true); + } + + // Tag dispatch on multi associative containers (i.e. multimaps). + template < typename Container, typename Graph, typename Label, + typename Prop > + std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > + insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p, + multiple_associative_container_tag const&) + { + // Note that insertion always succeeds so we can add the vertex first + // and then the mapping to the label. + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + Vertex v = add_vertex(p, g); + c.insert(std::make_pair(l, v)); + return std::make_pair(v, true); + } + + // Tag dispatch on unique associative containers (i.e. maps). + template < typename Container, typename Graph, typename Label, + typename Prop > + std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > + insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p, + unique_associative_container_tag) + { + // Here, we actually have to try the insertion first, and only add + // the vertex if we get a new element. + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename Container::iterator Iterator; + std::pair< Iterator, bool > x = c.insert(std::make_pair(l, Vertex())); + if (x.second) + { + x.first->second = add_vertex(g); + put(boost::vertex_all, g, x.first->second, p); + } + return std::make_pair(x.first->second, x.second); + } + + // Dispatcher + template < typename Container, typename Graph, typename Label, + typename Prop > + std::pair< typename graph_traits< Graph >::vertex_descriptor, bool > + insert_labeled_vertex(Container& c, Graph& g, Label const& l, Prop const& p) + { + return insert_labeled_vertex(c, g, l, p, container_category(c)); + } + //@} + + /** @name Find Labeled Vertex */ + //@{ + // Tag dispatch for sequential maps (i.e., vectors). + template < typename Container, typename Graph, typename Label > + typename graph_traits< Graph >::vertex_descriptor find_labeled_vertex( + Container const& c, Graph const&, Label const& l, + random_access_container_tag) + { + return l < c.size() ? c[l] : graph_traits< Graph >::null_vertex(); + } + + // Tag dispatch for pair associative maps (more or less). + template < typename Container, typename Graph, typename Label > + typename graph_traits< Graph >::vertex_descriptor find_labeled_vertex( + Container const& c, Graph const&, Label const& l, + associative_container_tag) + { + typename Container::const_iterator i = c.find(l); + return i != c.end() ? i->second : graph_traits< Graph >::null_vertex(); + } + + // Dispatcher + template < typename Container, typename Graph, typename Label > + typename graph_traits< Graph >::vertex_descriptor find_labeled_vertex( + Container const& c, Graph const& g, Label const& l) + { + return find_labeled_vertex(c, g, l, container_category(c)); + } + //@} + + /** @name Put Vertex Label */ + //@{ + // Tag dispatch on vectors. + template < typename Container, typename Label, typename Graph, + typename Vertex > + bool put_vertex_label(Container& c, Graph const&, Label const& l, Vertex v, + random_access_container_tag) + { + // If the element is already occupied, then we probably don't want to + // overwrite it. + if (c[l] == graph_traits< Graph >::null_vertex()) + return false; + c[l] = v; + return true; + } + + // Attempt the insertion and return its result. + template < typename Container, typename Label, typename Graph, + typename Vertex > + bool put_vertex_label(Container& c, Graph const&, Label const& l, Vertex v, + unique_associative_container_tag) + { + return c.insert(std::make_pair(l, v)).second; + } + + // Insert the pair and return true. + template < typename Container, typename Label, typename Graph, + typename Vertex > + bool put_vertex_label(Container& c, Graph const&, Label const& l, Vertex v, + multiple_associative_container_tag) + { + c.insert(std::make_pair(l, v)); + return true; + } + + // Dispatcher + template < typename Container, typename Label, typename Graph, + typename Vertex > + bool put_vertex_label( + Container& c, Graph const& g, Label const& l, Vertex v) + { + return put_vertex_label(c, g, l, v, container_category(c)); + } + //@} + + /** @name Remove Labeled Vertex */ + //@{ + // Tag dispatch on random access containers (i.e., vectors) + template <typename Container, typename Label, typename Graph> + void remove_labeled_vertex(Container& c, Graph& g, Label const& l, + random_access_container_tag) + { + if (l < c.size()) + { + boost::remove_vertex(c[l], g); + c.erase(c.begin() + l); + } + } + + // Tag dispatch on multi associative containers (i.e. multimaps). + template <typename Container, typename Label, typename Graph> + void remove_labeled_vertex(Container& c, Graph& g, Label const& l, + multiple_associative_container_tag) + { + typename Container::iterator c_it = c.find(l); + if (c_it != c.end()) + { + boost::remove_vertex(c_it->second, g); + c.erase(c_it); + } + } + + // Tag dispatch on unique associative containers (i.e. maps). + template <typename Container, typename Label, typename Graph> + void remove_labeled_vertex(Container& c, Graph& g, Label const& l, + unique_associative_container_tag) + { + typename Container::iterator c_it = c.find(l); + if (c_it != c.end()) + { + boost::remove_vertex(c_it->second, g); + c.erase(c_it); + } + } + + // Dispatcher + template <typename Container, typename Label, typename Graph> + void remove_labeled_vertex(Container& c, Graph& g, Label const& l) + { + remove_labeled_vertex(c, g, l, container_category(c)); + } + //@} + +} // namespace detail + +struct labeled_graph_class_tag +{ +}; + +/** @internal + * This class is responsible for the deduction and declaration of type names + * for the labeled_graph class template. + */ +template < typename Graph, typename Label, typename Selector > +struct labeled_graph_types +{ + typedef Graph graph_type; + + // Label and maps + typedef Label label_type; + typedef typename graph_detail::choose_map< Selector, Label, + typename graph_traits< Graph >::vertex_descriptor >::type map_type; +}; + +/** + * The labeled_graph class is a graph adaptor that maintains a mapping between + * vertex labels and vertex descriptors. + * + * @todo This class is somewhat redundant for adjacency_list<*, vecS> if + * the intended label is an unsigned int (and perhaps some other cases), but + * it does avoid some weird ambiguities (i.e. adding a vertex with a label that + * does not match its target index). + * + * @todo This needs to be reconciled with the named_graph, but since there is + * no documentation or examples, its not going to happen. + */ +template < typename Graph, typename Label, typename Selector = defaultS > +class labeled_graph : protected labeled_graph_types< Graph, Label, Selector > +{ + typedef labeled_graph_types< Graph, Label, Selector > Base; + +public: + typedef labeled_graph_class_tag graph_tag; + + typedef typename Base::graph_type graph_type; + typedef typename graph_traits< graph_type >::vertex_descriptor + vertex_descriptor; + typedef + typename graph_traits< graph_type >::edge_descriptor edge_descriptor; + typedef typename graph_traits< graph_type >::directed_category + directed_category; + typedef typename graph_traits< graph_type >::edge_parallel_category + edge_parallel_category; + typedef typename graph_traits< graph_type >::traversal_category + traversal_category; + + typedef typename graph_traits< graph_type >::out_edge_iterator + out_edge_iterator; + typedef + typename graph_traits< graph_type >::in_edge_iterator in_edge_iterator; + typedef typename graph_traits< graph_type >::adjacency_iterator + adjacency_iterator; + typedef + typename graph_traits< graph_type >::degree_size_type degree_size_type; + + typedef + typename graph_traits< graph_type >::vertex_iterator vertex_iterator; + typedef typename graph_traits< graph_type >::vertices_size_type + vertices_size_type; + typedef typename graph_traits< graph_type >::edge_iterator edge_iterator; + typedef + typename graph_traits< graph_type >::edges_size_type edges_size_type; + + typedef typename graph_type::graph_property_type graph_property_type; + typedef typename graph_type::graph_bundled graph_bundled; + + typedef typename graph_type::vertex_property_type vertex_property_type; + typedef typename graph_type::vertex_bundled vertex_bundled; + + typedef typename graph_type::edge_property_type edge_property_type; + typedef typename graph_type::edge_bundled edge_bundled; + + typedef typename Base::label_type label_type; + typedef typename Base::map_type map_type; + +public: + labeled_graph(graph_property_type const& gp = graph_property_type()) + : _graph(gp), _map() + { + } + + labeled_graph(labeled_graph const& x) : _graph(x._graph), _map(x._map) {} + + // This constructor can only be used if map_type supports positional + // range insertion (i.e. its a vector). This is the only case where we can + // try to guess the intended labels for graph. + labeled_graph(vertices_size_type n, + graph_property_type const& gp = graph_property_type()) + : _graph(n, gp), _map() + { + std::pair< vertex_iterator, vertex_iterator > rng = vertices(_graph); + _map.insert(_map.end(), rng.first, rng.second); + } + + // Construct a graph over n vertices, each of which receives a label from + // the range [l, l + n). Note that the graph is not directly constructed + // over the n vertices, but added sequentially. This constructor is + // necessarily slower than the underlying counterpart. + template < typename LabelIter > + labeled_graph(vertices_size_type n, LabelIter l, + graph_property_type const& gp = graph_property_type()) + : _graph(gp) + { + while (n-- > 0) + add_vertex(*l++); + } + + // Construct the graph over n vertices each of which has a label in the + // range [l, l + n) and a property in the range [p, p + n). + template < typename LabelIter, typename PropIter > + labeled_graph(vertices_size_type n, LabelIter l, PropIter p, + graph_property_type const& gp = graph_property_type()) + : _graph(gp) + { + while (n-- > 0) + add_vertex(*l++, *p++); + } + + labeled_graph& operator=(labeled_graph const& x) + { + _graph = x._graph; + _map = x._map; + return *this; + } + + /** @name Graph Accessors */ + //@{ + graph_type& graph() { return _graph; } + graph_type const& graph() const { return _graph; } + //@} + + /** + * Create a new label for the given vertex, returning false, if the label + * cannot be created. + */ + bool label_vertex(vertex_descriptor v, Label const& l) + { + return graph_detail::put_vertex_label(_map, _graph, l, v); + } + + /** @name Add Vertex + * Add a vertex to the graph, returning the descriptor. If the vertices + * are uniquely labeled and the label already exists within the graph, + * then no vertex is added, and the returned descriptor refers to the + * existing vertex. A vertex property can be given as a parameter, if + * needed. + */ + //@{ + vertex_descriptor add_vertex(Label const& l) + { + return graph_detail::insert_labeled_vertex( + _map, _graph, l, vertex_property_type()) + .first; + } + + vertex_descriptor add_vertex(Label const& l, vertex_property_type const& p) + { + return graph_detail::insert_labeled_vertex(_map, _graph, l, p).first; + } + //@} + + /** @name Insert Vertex + * Insert a vertex into the graph, returning a pair containing the + * descriptor of a vertex and a boolean value that describes whether or not + * a new vertex was inserted. If vertices are not uniquely labeled, then + * insertion will always succeed. + */ + //@{ + std::pair< vertex_descriptor, bool > insert_vertex(Label const& l) + { + return graph_detail::insert_labeled_vertex( + _map, _graph, l, vertex_property_type()); + } + + std::pair< vertex_descriptor, bool > insert_vertex( + Label const& l, vertex_property_type const& p) + { + return graph_detail::insert_labeled_vertex(_map, _graph, l, p); + } + //@} + + /** Remove the vertex with the given label. */ + void remove_vertex(Label const& l) + { + return graph_detail::remove_labeled_vertex(_map, _graph, l); + } + + /** Return a descriptor for the given label. */ + vertex_descriptor vertex(Label const& l) const + { + return graph_detail::find_labeled_vertex(_map, _graph, l); + } + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + /** @name Bundled Properties */ + //@{ + // Lookup the requested vertex and return the bundle. + vertex_bundled& operator[](Label const& l) { return _graph[vertex(l)]; } + + vertex_bundled const& operator[](Label const& l) const + { + return _graph[vertex(l)]; + } + + // Delegate edge lookup to the underlying graph. + edge_bundled& operator[](edge_descriptor e) { return _graph[e]; } + + edge_bundled const& operator[](edge_descriptor e) const + { + return _graph[e]; + } + //@} +#endif + + /** Return a null descriptor */ + static vertex_descriptor null_vertex() + { + return graph_traits< graph_type >::null_vertex(); + } + +private: + graph_type _graph; + map_type _map; +}; + +/** + * The partial specialization over graph pointers allows the construction + * of temporary labeled graph objects. In this case, the labels are destructed + * when the wrapper goes out of scope. + */ +template < typename Graph, typename Label, typename Selector > +class labeled_graph< Graph*, Label, Selector > +: protected labeled_graph_types< Graph, Label, Selector > +{ + typedef labeled_graph_types< Graph, Label, Selector > Base; + +public: + typedef labeled_graph_class_tag graph_tag; + + typedef typename Base::graph_type graph_type; + typedef typename graph_traits< graph_type >::vertex_descriptor + vertex_descriptor; + typedef + typename graph_traits< graph_type >::edge_descriptor edge_descriptor; + typedef typename graph_traits< graph_type >::directed_category + directed_category; + typedef typename graph_traits< graph_type >::edge_parallel_category + edge_parallel_category; + typedef typename graph_traits< graph_type >::traversal_category + traversal_category; + + typedef typename graph_traits< graph_type >::out_edge_iterator + out_edge_iterator; + typedef + typename graph_traits< graph_type >::in_edge_iterator in_edge_iterator; + typedef typename graph_traits< graph_type >::adjacency_iterator + adjacency_iterator; + typedef + typename graph_traits< graph_type >::degree_size_type degree_size_type; + + typedef + typename graph_traits< graph_type >::vertex_iterator vertex_iterator; + typedef typename graph_traits< graph_type >::vertices_size_type + vertices_size_type; + typedef typename graph_traits< graph_type >::edge_iterator edge_iterator; + typedef + typename graph_traits< graph_type >::edges_size_type edges_size_type; + + typedef typename graph_type::vertex_property_type vertex_property_type; + typedef typename graph_type::edge_property_type edge_property_type; + typedef typename graph_type::graph_property_type graph_property_type; + typedef typename graph_type::vertex_bundled vertex_bundled; + typedef typename graph_type::edge_bundled edge_bundled; + + typedef typename Base::label_type label_type; + typedef typename Base::map_type map_type; + + labeled_graph(graph_type* g) : _graph(g) {} + + /** @name Graph Access */ + //@{ + graph_type& graph() { return *_graph; } + graph_type const& graph() const { return *_graph; } + //@} + + /** + * Create a new label for the given vertex, returning false, if the label + * cannot be created. + */ + bool label_vertex(vertex_descriptor v, Label const& l) + { + return graph_detail::put_vertex_label(_map, *_graph, l, v); + } + + /** @name Add Vertex */ + //@{ + vertex_descriptor add_vertex(Label const& l) + { + return graph_detail::insert_labeled_vertex( + _map, *_graph, l, vertex_property_type()) + .first; + } + + vertex_descriptor add_vertex(Label const& l, vertex_property_type const& p) + { + return graph_detail::insert_labeled_vertex(_map, *_graph, l, p).first; + } + + std::pair< vertex_descriptor, bool > insert_vertex(Label const& l) + { + return graph_detail::insert_labeled_vertex( + _map, *_graph, l, vertex_property_type()); + } + //@} + + /** Try to insert a vertex with the given label. */ + std::pair< vertex_descriptor, bool > insert_vertex( + Label const& l, vertex_property_type const& p) + { + return graph_detail::insert_labeled_vertex(_map, *_graph, l, p); + } + + /** Remove the vertex with the given label. */ + void remove_vertex(Label const& l) + { + return boost::remove_vertex(vertex(l), *_graph); + } + + /** Return a descriptor for the given label. */ + vertex_descriptor vertex(Label const& l) const + { + return graph_detail::find_labeled_vertex(_map, *_graph, l); + } + +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + /** @name Bundled Properties */ + //@{ + // Lookup the requested vertex and return the bundle. + vertex_bundled& operator[](Label const& l) { return (*_graph)[vertex(l)]; } + + vertex_bundled const& operator[](Label const& l) const + { + return (*_graph)[vertex(l)]; + } + + // Delegate edge lookup to the underlying graph. + edge_bundled& operator[](edge_descriptor e) { return (*_graph)[e]; } + + edge_bundled const& operator[](edge_descriptor e) const + { + return (*_graph)[e]; + } + //@} +#endif + + static vertex_descriptor null_vertex() + { + return graph_traits< graph_type >::null_vertex(); + } + +private: + graph_type* _graph; + map_type _map; +}; + +#define LABELED_GRAPH_PARAMS typename G, typename L, typename S +#define LABELED_GRAPH labeled_graph< G, L, S > + +/** @name Labeled Graph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline bool label_vertex(typename LABELED_GRAPH::vertex_descriptor v, + typename LABELED_GRAPH::label_type const l, LABELED_GRAPH& g) +{ + return g.label_vertex(v, l); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::vertex_descriptor vertex_by_label( + typename LABELED_GRAPH::label_type const l, LABELED_GRAPH& g) +{ + return g.vertex(l); +} +//@} + +/** @name Graph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > edge( + typename LABELED_GRAPH::vertex_descriptor const& u, + typename LABELED_GRAPH::vertex_descriptor const& v, LABELED_GRAPH const& g) +{ + return edge(u, v, g.graph()); +} + +// Labeled Extensions +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > edge_by_label( + typename LABELED_GRAPH::label_type const& u, + typename LABELED_GRAPH::label_type const& v, LABELED_GRAPH const& g) +{ + return edge(g.vertex(u), g.vertex(v), g); +} +//@} + +/** @name Incidence Graph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::out_edge_iterator, + typename LABELED_GRAPH::out_edge_iterator > +out_edges(typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) +{ + return out_edges(v, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::degree_size_type out_degree( + typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) +{ + return out_degree(v, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::vertex_descriptor source( + typename LABELED_GRAPH::edge_descriptor e, LABELED_GRAPH const& g) +{ + return source(e, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::vertex_descriptor target( + typename LABELED_GRAPH::edge_descriptor e, LABELED_GRAPH const& g) +{ + return target(e, g.graph()); +} +//@} + +/** @name Bidirectional Graph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::in_edge_iterator, + typename LABELED_GRAPH::in_edge_iterator > +in_edges(typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) +{ + return in_edges(v, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::degree_size_type in_degree( + typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) +{ + return in_degree(v, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::degree_size_type degree( + typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) +{ + return degree(v, g.graph()); +} +//@} + +/** @name Adjacency Graph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::adjacency_iterator, + typename LABELED_GRAPH::adjacency_iterator > +adjacent_vertices( + typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g) +{ + return adjacent_vertices(v, g.graph()); +} +//@} + +/** @name VertexListGraph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::vertex_iterator, + typename LABELED_GRAPH::vertex_iterator > +vertices(LABELED_GRAPH const& g) +{ + return vertices(g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::vertices_size_type num_vertices( + LABELED_GRAPH const& g) +{ + return num_vertices(g.graph()); +} +//@} + +/** @name EdgeListGraph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::edge_iterator, + typename LABELED_GRAPH::edge_iterator > +edges(LABELED_GRAPH const& g) +{ + return edges(g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::edges_size_type num_edges(LABELED_GRAPH const& g) +{ + return num_edges(g.graph()); +} +//@} + +/** @internal @name Property Lookup */ +//@{ +namespace graph_detail +{ + struct labeled_graph_vertex_property_selector + { + template < class LabeledGraph, class Property, class Tag > struct bind_ + { + typedef typename LabeledGraph::graph_type Graph; + typedef property_map< Graph, Tag > PropertyMap; + typedef typename PropertyMap::type type; + typedef typename PropertyMap::const_type const_type; + }; + }; + + struct labeled_graph_edge_property_selector + { + template < class LabeledGraph, class Property, class Tag > struct bind_ + { + typedef typename LabeledGraph::graph_type Graph; + typedef property_map< Graph, Tag > PropertyMap; + typedef typename PropertyMap::type type; + typedef typename PropertyMap::const_type const_type; + }; + }; +} + +template <> struct vertex_property_selector< labeled_graph_class_tag > +{ + typedef graph_detail::labeled_graph_vertex_property_selector type; +}; + +template <> struct edge_property_selector< labeled_graph_class_tag > +{ + typedef graph_detail::labeled_graph_edge_property_selector type; +}; +//@} + +/** @name Property Graph */ +//@{ +template < LABELED_GRAPH_PARAMS, typename Prop > +inline typename property_map< LABELED_GRAPH, Prop >::type get( + Prop p, LABELED_GRAPH& g) +{ + return get(p, g.graph()); +} + +template < LABELED_GRAPH_PARAMS, typename Prop > +inline typename property_map< LABELED_GRAPH, Prop >::const_type get( + Prop p, LABELED_GRAPH const& g) +{ + return get(p, g.graph()); +} + +template < LABELED_GRAPH_PARAMS, typename Prop, typename Key > +inline typename property_traits< typename property_map< + typename LABELED_GRAPH::graph_type, Prop >::const_type >::value_type +get(Prop p, LABELED_GRAPH const& g, const Key& k) +{ + return get(p, g.graph(), k); +} + +template < LABELED_GRAPH_PARAMS, typename Prop, typename Key, typename Value > +inline void put(Prop p, LABELED_GRAPH& g, Key const& k, Value const& v) +{ + put(p, g.graph(), k, v); +} +//@} + +/** @name Mutable Graph */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > add_edge( + typename LABELED_GRAPH::vertex_descriptor const& u, + typename LABELED_GRAPH::vertex_descriptor const& v, LABELED_GRAPH& g) +{ + return add_edge(u, v, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > add_edge( + typename LABELED_GRAPH::vertex_descriptor const& u, + typename LABELED_GRAPH::vertex_descriptor const& v, + typename LABELED_GRAPH::edge_property_type const& p, LABELED_GRAPH& g) +{ + return add_edge(u, v, p, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline void clear_vertex( + typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH& g) +{ + return clear_vertex(v, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline void remove_edge( + typename LABELED_GRAPH::edge_descriptor e, LABELED_GRAPH& g) +{ + return remove_edge(e, g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline void remove_edge(typename LABELED_GRAPH::vertex_descriptor u, + typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH& g) +{ + return remove_edge(u, v, g.graph()); +} + +// Labeled extensions +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > +add_edge_by_label(typename LABELED_GRAPH::label_type const& u, + typename LABELED_GRAPH::label_type const& v, LABELED_GRAPH& g) +{ + return add_edge(g.vertex(u), g.vertex(v), g); +} + +template < LABELED_GRAPH_PARAMS > +inline std::pair< typename LABELED_GRAPH::edge_descriptor, bool > +add_edge_by_label(typename LABELED_GRAPH::label_type const& u, + typename LABELED_GRAPH::label_type const& v, + typename LABELED_GRAPH::edge_property_type const& p, LABELED_GRAPH& g) +{ + return add_edge(g.vertex(u), g.vertex(v), p, g); +} + +template < LABELED_GRAPH_PARAMS > +inline void clear_vertex_by_label( + typename LABELED_GRAPH::label_type const& l, LABELED_GRAPH& g) +{ + clear_vertex(g.vertex(l), g.graph()); +} + +template < LABELED_GRAPH_PARAMS > +inline void remove_edge_by_label(typename LABELED_GRAPH::label_type const& u, + typename LABELED_GRAPH::label_type const& v, LABELED_GRAPH& g) +{ + remove_edge(g.vertex(u), g.vertex(v), g.graph()); +} +//@} + +/** @name Labeled Mutable Graph + * The labeled mutable graph hides the add_ and remove_ vertex functions from + * the mutable graph concept. Note that the remove_vertex is hidden because + * removing the vertex without its key could leave a dangling reference in + * the map. + */ +//@{ +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::vertex_descriptor add_vertex( + typename LABELED_GRAPH::label_type const& l, LABELED_GRAPH& g) +{ + return g.add_vertex(l); +} + +// MutableLabeledPropertyGraph::add_vertex(l, vp, g) +template < LABELED_GRAPH_PARAMS > +inline typename LABELED_GRAPH::vertex_descriptor add_vertex( + typename LABELED_GRAPH::label_type const& l, + typename LABELED_GRAPH::vertex_property_type const& p, LABELED_GRAPH& g) +{ + return g.add_vertex(l, p); +} + +template < LABELED_GRAPH_PARAMS > +inline void remove_vertex( + typename LABELED_GRAPH::label_type const& l, LABELED_GRAPH& g) +{ + g.remove_vertex(l); +} +//@} + +#undef LABELED_GRAPH_PARAMS +#undef LABELED_GRAPH + +} // namespace boost + +// Pull the labeled graph traits +#include <boost/graph/detail/labeled_graph_traits.hpp> + +#endif // BOOST_GRAPH_LABELED_GRAPH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/leda_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/leda_graph.hpp new file mode 100644 index 0000000000..7d58518a7d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/leda_graph.hpp @@ -0,0 +1,942 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004 The Trustees of Indiana University. +// Copyright 2007 University of Karlsruhe +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor, +// Jens Mueller +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_LEDA_HPP +#define BOOST_GRAPH_LEDA_HPP + +#include <boost/config.hpp> +#include <boost/iterator/iterator_facade.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> + +#include <LEDA/graph/graph.h> +#include <LEDA/graph/node_array.h> +#include <LEDA/graph/node_map.h> + +// The functions and classes in this file allows the user to +// treat a LEDA GRAPH object as a boost graph "as is". No +// wrapper is needed for the GRAPH object. + +// Warning: this implementation relies on partial specialization +// for the graph_traits class (so it won't compile with Visual C++) + +// Warning: this implementation is in alpha and has not been tested + +namespace boost +{ + +struct leda_graph_traversal_category : public virtual bidirectional_graph_tag, + public virtual adjacency_graph_tag, + public virtual vertex_list_graph_tag +{ +}; + +template < class vtype, class etype > +struct graph_traits< leda::GRAPH< vtype, etype > > +{ + typedef leda::node vertex_descriptor; + typedef leda::edge edge_descriptor; + + class adjacency_iterator + : public iterator_facade< adjacency_iterator, leda::node, + bidirectional_traversal_tag, leda::node, const leda::node* > + { + public: + adjacency_iterator( + leda::node node = 0, const leda::GRAPH< vtype, etype >* g = 0) + : base(node), g(g) + { + } + + private: + leda::node dereference() const { return leda::target(base); } + + bool equal(const adjacency_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::GRAPH< vtype, etype >* g; + + friend class iterator_core_access; + }; + + class out_edge_iterator + : public iterator_facade< out_edge_iterator, leda::edge, + bidirectional_traversal_tag, const leda::edge&, const leda::edge* > + { + public: + out_edge_iterator( + leda::node node = 0, const leda::GRAPH< vtype, etype >* g = 0) + : base(node), g(g) + { + } + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const out_edge_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::GRAPH< vtype, etype >* g; + + friend class iterator_core_access; + }; + + class in_edge_iterator + : public iterator_facade< in_edge_iterator, leda::edge, + bidirectional_traversal_tag, const leda::edge&, const leda::edge* > + { + public: + in_edge_iterator( + leda::node node = 0, const leda::GRAPH< vtype, etype >* g = 0) + : base(node), g(g) + { + } + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const in_edge_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->in_succ(base); } + void decrement() { base = g->in_pred(base); } + + leda::edge base; + const leda::GRAPH< vtype, etype >* g; + + friend class iterator_core_access; + }; + + class vertex_iterator + : public iterator_facade< vertex_iterator, leda::node, + bidirectional_traversal_tag, const leda::node&, const leda::node* > + { + public: + vertex_iterator( + leda::node node = 0, const leda::GRAPH< vtype, etype >* g = 0) + : base(node), g(g) + { + } + + private: + const leda::node& dereference() const { return base; } + + bool equal(const vertex_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->succ_node(base); } + void decrement() { base = g->pred_node(base); } + + leda::node base; + const leda::GRAPH< vtype, etype >* g; + + friend class iterator_core_access; + }; + + class edge_iterator + : public iterator_facade< edge_iterator, leda::edge, + bidirectional_traversal_tag, const leda::edge&, const leda::edge* > + { + public: + edge_iterator( + leda::edge edge = 0, const leda::GRAPH< vtype, etype >* g = 0) + : base(edge), g(g) + { + } + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const edge_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->succ_edge(base); } + void decrement() { base = g->pred_edge(base); } + + leda::node base; + const leda::GRAPH< vtype, etype >* g; + + friend class iterator_core_access; + }; + + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; // not sure here + typedef leda_graph_traversal_category traversal_category; + typedef int vertices_size_type; + typedef int edges_size_type; + typedef int degree_size_type; +}; + +template <> struct graph_traits< leda::graph > +{ + typedef leda::node vertex_descriptor; + typedef leda::edge edge_descriptor; + + class adjacency_iterator + : public iterator_facade< adjacency_iterator, leda::node, + bidirectional_traversal_tag, leda::node, const leda::node* > + { + public: + adjacency_iterator(leda::edge edge = 0, const leda::graph* g = 0) + : base(edge), g(g) + { + } + + private: + leda::node dereference() const { return leda::target(base); } + + bool equal(const adjacency_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class out_edge_iterator + : public iterator_facade< out_edge_iterator, leda::edge, + bidirectional_traversal_tag, const leda::edge&, const leda::edge* > + { + public: + out_edge_iterator(leda::edge edge = 0, const leda::graph* g = 0) + : base(edge), g(g) + { + } + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const out_edge_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->adj_succ(base); } + void decrement() { base = g->adj_pred(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class in_edge_iterator + : public iterator_facade< in_edge_iterator, leda::edge, + bidirectional_traversal_tag, const leda::edge&, const leda::edge* > + { + public: + in_edge_iterator(leda::edge edge = 0, const leda::graph* g = 0) + : base(edge), g(g) + { + } + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const in_edge_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->in_succ(base); } + void decrement() { base = g->in_pred(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class vertex_iterator + : public iterator_facade< vertex_iterator, leda::node, + bidirectional_traversal_tag, const leda::node&, const leda::node* > + { + public: + vertex_iterator(leda::node node = 0, const leda::graph* g = 0) + : base(node), g(g) + { + } + + private: + const leda::node& dereference() const { return base; } + + bool equal(const vertex_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->succ_node(base); } + void decrement() { base = g->pred_node(base); } + + leda::node base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + class edge_iterator + : public iterator_facade< edge_iterator, leda::edge, + bidirectional_traversal_tag, const leda::edge&, const leda::edge* > + { + public: + edge_iterator(leda::edge edge = 0, const leda::graph* g = 0) + : base(edge), g(g) + { + } + + private: + const leda::edge& dereference() const { return base; } + + bool equal(const edge_iterator& other) const + { + return base == other.base; + } + + void increment() { base = g->succ_edge(base); } + void decrement() { base = g->pred_edge(base); } + + leda::edge base; + const leda::graph* g; + + friend class iterator_core_access; + }; + + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; // not sure here + typedef leda_graph_traversal_category traversal_category; + typedef int vertices_size_type; + typedef int edges_size_type; + typedef int degree_size_type; +}; + +} // namespace boost + +namespace boost +{ + +//=========================================================================== +// functions for GRAPH<vtype,etype> + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor source( + typename graph_traits< leda::GRAPH< vtype, etype > >::edge_descriptor e, + const leda::GRAPH< vtype, etype >& g) +{ + return source(e); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor target( + typename graph_traits< leda::GRAPH< vtype, etype > >::edge_descriptor e, + const leda::GRAPH< vtype, etype >& g) +{ + return target(e); +} + +template < class vtype, class etype > +inline std::pair< + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_iterator, + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_iterator > +vertices(const leda::GRAPH< vtype, etype >& g) +{ + typedef + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_iterator + Iter; + return std::make_pair(Iter(g.first_node(), &g), Iter(0, &g)); +} + +template < class vtype, class etype > +inline std::pair< + typename graph_traits< leda::GRAPH< vtype, etype > >::edge_iterator, + typename graph_traits< leda::GRAPH< vtype, etype > >::edge_iterator > +edges(const leda::GRAPH< vtype, etype >& g) +{ + typedef typename graph_traits< leda::GRAPH< vtype, etype > >::edge_iterator + Iter; + return std::make_pair(Iter(g.first_edge(), &g), Iter(0, &g)); +} + +template < class vtype, class etype > +inline std::pair< + typename graph_traits< leda::GRAPH< vtype, etype > >::out_edge_iterator, + typename graph_traits< leda::GRAPH< vtype, etype > >::out_edge_iterator > +out_edges( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + const leda::GRAPH< vtype, etype >& g) +{ + typedef + typename graph_traits< leda::GRAPH< vtype, etype > >::out_edge_iterator + Iter; + return std::make_pair(Iter(g.first_adj_edge(u, 0), &g), Iter(0, &g)); +} + +template < class vtype, class etype > +inline std::pair< + typename graph_traits< leda::GRAPH< vtype, etype > >::in_edge_iterator, + typename graph_traits< leda::GRAPH< vtype, etype > >::in_edge_iterator > +in_edges( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + const leda::GRAPH< vtype, etype >& g) +{ + typedef + typename graph_traits< leda::GRAPH< vtype, etype > >::in_edge_iterator + Iter; + return std::make_pair(Iter(g.first_adj_edge(u, 1), &g), Iter(0, &g)); +} + +template < class vtype, class etype > +inline std::pair< + typename graph_traits< leda::GRAPH< vtype, etype > >::adjacency_iterator, + typename graph_traits< leda::GRAPH< vtype, etype > >::adjacency_iterator > +adjacent_vertices( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + const leda::GRAPH< vtype, etype >& g) +{ + typedef + typename graph_traits< leda::GRAPH< vtype, etype > >::adjacency_iterator + Iter; + return std::make_pair(Iter(g.first_adj_edge(u, 0), &g), Iter(0, &g)); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::vertices_size_type +num_vertices(const leda::GRAPH< vtype, etype >& g) +{ + return g.number_of_nodes(); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::edges_size_type num_edges( + const leda::GRAPH< vtype, etype >& g) +{ + return g.number_of_edges(); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::degree_size_type +out_degree( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + const leda::GRAPH< vtype, etype >& g) +{ + return g.outdeg(u); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::degree_size_type +in_degree( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + const leda::GRAPH< vtype, etype >& g) +{ + return g.indeg(u); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::degree_size_type degree( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + const leda::GRAPH< vtype, etype >& g) +{ + return g.outdeg(u) + g.indeg(u); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor +add_vertex(leda::GRAPH< vtype, etype >& g) +{ + return g.new_node(); +} + +template < class vtype, class etype > +typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor +add_vertex(const vtype& vp, leda::GRAPH< vtype, etype >& g) +{ + return g.new_node(vp); +} + +template < class vtype, class etype > +void clear_vertex( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + leda::GRAPH< vtype, etype >& g) +{ + typename graph_traits< leda::GRAPH< vtype, etype > >::out_edge_iterator ei, + ei_end; + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ei++) + remove_edge(*ei); + + typename graph_traits< leda::GRAPH< vtype, etype > >::in_edge_iterator iei, + iei_end; + for (boost::tie(iei, iei_end) = in_edges(u, g); iei != iei_end; iei++) + remove_edge(*iei); +} + +template < class vtype, class etype > +void remove_vertex( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + leda::GRAPH< vtype, etype >& g) +{ + g.del_node(u); +} + +template < class vtype, class etype > +std::pair< + typename graph_traits< leda::GRAPH< vtype, etype > >::edge_descriptor, + bool > +add_edge( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor v, + leda::GRAPH< vtype, etype >& g) +{ + return std::make_pair(g.new_edge(u, v), true); +} + +template < class vtype, class etype > +std::pair< + typename graph_traits< leda::GRAPH< vtype, etype > >::edge_descriptor, + bool > +add_edge( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor v, + const etype& et, leda::GRAPH< vtype, etype >& g) +{ + return std::make_pair(g.new_edge(u, v, et), true); +} + +template < class vtype, class etype > +void remove_edge( + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor u, + typename graph_traits< leda::GRAPH< vtype, etype > >::vertex_descriptor v, + leda::GRAPH< vtype, etype >& g) +{ + typename graph_traits< leda::GRAPH< vtype, etype > >::out_edge_iterator i, + iend; + for (boost::tie(i, iend) = out_edges(u, g); i != iend; ++i) + if (target(*i, g) == v) + g.del_edge(*i); +} + +template < class vtype, class etype > +void remove_edge( + typename graph_traits< leda::GRAPH< vtype, etype > >::edge_descriptor e, + leda::GRAPH< vtype, etype >& g) +{ + g.del_edge(e); +} + +//=========================================================================== +// functions for graph (non-templated version) + +graph_traits< leda::graph >::vertex_descriptor source( + graph_traits< leda::graph >::edge_descriptor e, const leda::graph& g) +{ + return source(e); +} + +graph_traits< leda::graph >::vertex_descriptor target( + graph_traits< leda::graph >::edge_descriptor e, const leda::graph& g) +{ + return target(e); +} + +inline std::pair< graph_traits< leda::graph >::vertex_iterator, + graph_traits< leda::graph >::vertex_iterator > +vertices(const leda::graph& g) +{ + typedef graph_traits< leda::graph >::vertex_iterator Iter; + return std::make_pair(Iter(g.first_node(), &g), Iter(0, &g)); +} + +inline std::pair< graph_traits< leda::graph >::edge_iterator, + graph_traits< leda::graph >::edge_iterator > +edges(const leda::graph& g) +{ + typedef graph_traits< leda::graph >::edge_iterator Iter; + return std::make_pair(Iter(g.first_edge(), &g), Iter(0, &g)); +} + +inline std::pair< graph_traits< leda::graph >::out_edge_iterator, + graph_traits< leda::graph >::out_edge_iterator > +out_edges( + graph_traits< leda::graph >::vertex_descriptor u, const leda::graph& g) +{ + typedef graph_traits< leda::graph >::out_edge_iterator Iter; + return std::make_pair(Iter(g.first_adj_edge(u), &g), Iter(0, &g)); +} + +inline std::pair< graph_traits< leda::graph >::in_edge_iterator, + graph_traits< leda::graph >::in_edge_iterator > +in_edges(graph_traits< leda::graph >::vertex_descriptor u, const leda::graph& g) +{ + typedef graph_traits< leda::graph >::in_edge_iterator Iter; + return std::make_pair(Iter(g.first_in_edge(u), &g), Iter(0, &g)); +} + +inline std::pair< graph_traits< leda::graph >::adjacency_iterator, + graph_traits< leda::graph >::adjacency_iterator > +adjacent_vertices( + graph_traits< leda::graph >::vertex_descriptor u, const leda::graph& g) +{ + typedef graph_traits< leda::graph >::adjacency_iterator Iter; + return std::make_pair(Iter(g.first_adj_edge(u), &g), Iter(0, &g)); +} + +graph_traits< leda::graph >::vertices_size_type num_vertices( + const leda::graph& g) +{ + return g.number_of_nodes(); +} + +graph_traits< leda::graph >::edges_size_type num_edges(const leda::graph& g) +{ + return g.number_of_edges(); +} + +graph_traits< leda::graph >::degree_size_type out_degree( + graph_traits< leda::graph >::vertex_descriptor u, const leda::graph& g) +{ + return g.outdeg(u); +} + +graph_traits< leda::graph >::degree_size_type in_degree( + graph_traits< leda::graph >::vertex_descriptor u, const leda::graph& g) +{ + return g.indeg(u); +} + +graph_traits< leda::graph >::degree_size_type degree( + graph_traits< leda::graph >::vertex_descriptor u, const leda::graph& g) +{ + return g.outdeg(u) + g.indeg(u); +} + +graph_traits< leda::graph >::vertex_descriptor add_vertex(leda::graph& g) +{ + return g.new_node(); +} + +void remove_edge(graph_traits< leda::graph >::vertex_descriptor u, + graph_traits< leda::graph >::vertex_descriptor v, leda::graph& g) +{ + graph_traits< leda::graph >::out_edge_iterator i, iend; + for (boost::tie(i, iend) = out_edges(u, g); i != iend; ++i) + if (target(*i, g) == v) + g.del_edge(*i); +} + +void remove_edge(graph_traits< leda::graph >::edge_descriptor e, leda::graph& g) +{ + g.del_edge(e); +} + +void clear_vertex( + graph_traits< leda::graph >::vertex_descriptor u, leda::graph& g) +{ + graph_traits< leda::graph >::out_edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ei++) + remove_edge(*ei, g); + + graph_traits< leda::graph >::in_edge_iterator iei, iei_end; + for (boost::tie(iei, iei_end) = in_edges(u, g); iei != iei_end; iei++) + remove_edge(*iei, g); +} + +void remove_vertex( + graph_traits< leda::graph >::vertex_descriptor u, leda::graph& g) +{ + g.del_node(u); +} + +std::pair< graph_traits< leda::graph >::edge_descriptor, bool > add_edge( + graph_traits< leda::graph >::vertex_descriptor u, + graph_traits< leda::graph >::vertex_descriptor v, leda::graph& g) +{ + return std::make_pair(g.new_edge(u, v), true); +} + +//=========================================================================== +// property maps for GRAPH<vtype,etype> + +class leda_graph_id_map : public put_get_helper< int, leda_graph_id_map > +{ +public: + typedef readable_property_map_tag category; + typedef int value_type; + typedef int reference; + typedef leda::node key_type; + leda_graph_id_map() {} + template < class T > long operator[](T x) const { return x->id(); } +}; +template < class vtype, class etype > +inline leda_graph_id_map get( + vertex_index_t, const leda::GRAPH< vtype, etype >& g) +{ + return leda_graph_id_map(); +} +template < class vtype, class etype > +inline leda_graph_id_map get(edge_index_t, const leda::GRAPH< vtype, etype >& g) +{ + return leda_graph_id_map(); +} + +template < class Tag > struct leda_property_map +{ +}; + +template <> struct leda_property_map< vertex_index_t > +{ + template < class vtype, class etype > struct bind_ + { + typedef leda_graph_id_map type; + typedef leda_graph_id_map const_type; + }; +}; +template <> struct leda_property_map< edge_index_t > +{ + template < class vtype, class etype > struct bind_ + { + typedef leda_graph_id_map type; + typedef leda_graph_id_map const_type; + }; +}; + +template < class Data, class DataRef, class GraphPtr > +class leda_graph_data_map : public put_get_helper< DataRef, + leda_graph_data_map< Data, DataRef, GraphPtr > > +{ +public: + typedef Data value_type; + typedef DataRef reference; + typedef void key_type; + typedef lvalue_property_map_tag category; + leda_graph_data_map(GraphPtr g) : m_g(g) {} + template < class NodeOrEdge > DataRef operator[](NodeOrEdge x) const + { + return (*m_g)[x]; + } + +protected: + GraphPtr m_g; +}; + +template <> struct leda_property_map< vertex_all_t > +{ + template < class vtype, class etype > struct bind_ + { + typedef leda_graph_data_map< vtype, vtype&, + leda::GRAPH< vtype, etype >* > + type; + typedef leda_graph_data_map< vtype, const vtype&, + const leda::GRAPH< vtype, etype >* > + const_type; + }; +}; +template < class vtype, class etype > +inline typename property_map< leda::GRAPH< vtype, etype >, vertex_all_t >::type +get(vertex_all_t, leda::GRAPH< vtype, etype >& g) +{ + typedef + typename property_map< leda::GRAPH< vtype, etype >, vertex_all_t >::type + pmap_type; + return pmap_type(&g); +} +template < class vtype, class etype > +inline typename property_map< leda::GRAPH< vtype, etype >, + vertex_all_t >::const_type +get(vertex_all_t, const leda::GRAPH< vtype, etype >& g) +{ + typedef typename property_map< leda::GRAPH< vtype, etype >, + vertex_all_t >::const_type pmap_type; + return pmap_type(&g); +} + +template <> struct leda_property_map< edge_all_t > +{ + template < class vtype, class etype > struct bind_ + { + typedef leda_graph_data_map< etype, etype&, + leda::GRAPH< vtype, etype >* > + type; + typedef leda_graph_data_map< etype, const etype&, + const leda::GRAPH< vtype, etype >* > + const_type; + }; +}; +template < class vtype, class etype > +inline typename property_map< leda::GRAPH< vtype, etype >, edge_all_t >::type +get(edge_all_t, leda::GRAPH< vtype, etype >& g) +{ + typedef + typename property_map< leda::GRAPH< vtype, etype >, edge_all_t >::type + pmap_type; + return pmap_type(&g); +} +template < class vtype, class etype > +inline + typename property_map< leda::GRAPH< vtype, etype >, edge_all_t >::const_type + get(edge_all_t, const leda::GRAPH< vtype, etype >& g) +{ + typedef typename property_map< leda::GRAPH< vtype, etype >, + edge_all_t >::const_type pmap_type; + return pmap_type(&g); +} + +// property map interface to the LEDA node_array class + +template < class E, class ERef, class NodeMapPtr > +class leda_node_property_map +: public put_get_helper< ERef, leda_node_property_map< E, ERef, NodeMapPtr > > +{ +public: + typedef E value_type; + typedef ERef reference; + typedef leda::node key_type; + typedef lvalue_property_map_tag category; + leda_node_property_map(NodeMapPtr a) : m_array(a) {} + ERef operator[](leda::node n) const { return (*m_array)[n]; } + +protected: + NodeMapPtr m_array; +}; +template < class E > +leda_node_property_map< E, const E&, const leda::node_array< E >* > +make_leda_node_property_map(const leda::node_array< E >& a) +{ + typedef leda_node_property_map< E, const E&, const leda::node_array< E >* > + pmap_type; + return pmap_type(&a); +} +template < class E > +leda_node_property_map< E, E&, leda::node_array< E >* > +make_leda_node_property_map(leda::node_array< E >& a) +{ + typedef leda_node_property_map< E, E&, leda::node_array< E >* > pmap_type; + return pmap_type(&a); +} + +template < class E > +leda_node_property_map< E, const E&, const leda::node_map< E >* > +make_leda_node_property_map(const leda::node_map< E >& a) +{ + typedef leda_node_property_map< E, const E&, const leda::node_map< E >* > + pmap_type; + return pmap_type(&a); +} +template < class E > +leda_node_property_map< E, E&, leda::node_map< E >* > +make_leda_node_property_map(leda::node_map< E >& a) +{ + typedef leda_node_property_map< E, E&, leda::node_map< E >* > pmap_type; + return pmap_type(&a); +} + +// g++ 'enumeral_type' in template unification not implemented workaround +template < class vtype, class etype, class Tag > +struct property_map< leda::GRAPH< vtype, etype >, Tag > +{ + typedef typename leda_property_map< Tag >::template bind_< vtype, etype > + map_gen; + typedef typename map_gen::type type; + typedef typename map_gen::const_type const_type; +}; + +template < class vtype, class etype, class PropertyTag, class Key > +inline typename boost::property_traits< typename boost::property_map< + leda::GRAPH< vtype, etype >, PropertyTag >::const_type >::value_type +get(PropertyTag p, const leda::GRAPH< vtype, etype >& g, const Key& key) +{ + return get(get(p, g), key); +} + +template < class vtype, class etype, class PropertyTag, class Key, class Value > +inline void put(PropertyTag p, leda::GRAPH< vtype, etype >& g, const Key& key, + const Value& value) +{ + typedef + typename property_map< leda::GRAPH< vtype, etype >, PropertyTag >::type + Map; + Map pmap = get(p, g); + put(pmap, key, value); +} + +// property map interface to the LEDA edge_array class + +template < class E, class ERef, class EdgeMapPtr > +class leda_edge_property_map +: public put_get_helper< ERef, leda_edge_property_map< E, ERef, EdgeMapPtr > > +{ +public: + typedef E value_type; + typedef ERef reference; + typedef leda::edge key_type; + typedef lvalue_property_map_tag category; + leda_edge_property_map(EdgeMapPtr a) : m_array(a) {} + ERef operator[](leda::edge n) const { return (*m_array)[n]; } + +protected: + EdgeMapPtr m_array; +}; +template < class E > +leda_edge_property_map< E, const E&, const leda::edge_array< E >* > +make_leda_node_property_map(const leda::node_array< E >& a) +{ + typedef leda_edge_property_map< E, const E&, const leda::node_array< E >* > + pmap_type; + return pmap_type(&a); +} +template < class E > +leda_edge_property_map< E, E&, leda::edge_array< E >* > +make_leda_edge_property_map(leda::edge_array< E >& a) +{ + typedef leda_edge_property_map< E, E&, leda::edge_array< E >* > pmap_type; + return pmap_type(&a); +} + +template < class E > +leda_edge_property_map< E, const E&, const leda::edge_map< E >* > +make_leda_edge_property_map(const leda::edge_map< E >& a) +{ + typedef leda_edge_property_map< E, const E&, const leda::edge_map< E >* > + pmap_type; + return pmap_type(&a); +} +template < class E > +leda_edge_property_map< E, E&, leda::edge_map< E >* > +make_leda_edge_property_map(leda::edge_map< E >& a) +{ + typedef leda_edge_property_map< E, E&, leda::edge_map< E >* > pmap_type; + return pmap_type(&a); +} + +} // namespace boost + +#endif // BOOST_GRAPH_LEDA_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/loop_erased_random_walk.hpp b/contrib/restricted/boost/graph/include/boost/graph/loop_erased_random_walk.hpp new file mode 100644 index 0000000000..432d515940 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/loop_erased_random_walk.hpp @@ -0,0 +1,141 @@ +// Copyright 2010 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Andrew Lumsdaine + +#ifndef BOOST_GRAPH_LOOP_ERASED_RANDOM_WALK_HPP +#define BOOST_GRAPH_LOOP_ERASED_RANDOM_WALK_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/random.hpp> +#include <boost/next_prior.hpp> +#include <vector> +#include <boost/assert.hpp> + +namespace boost +{ + +struct BOOST_SYMBOL_VISIBLE loop_erased_random_walk_stuck +: public std::exception +{ + ~loop_erased_random_walk_stuck() BOOST_OVERRIDE {} + const char* what() const noexcept BOOST_OVERRIDE + { + return "Loop-erased random walk found a vertex with no out-edges"; + } +}; + +// Do a loop-erased random walk from vertex s to any vertex colored black (or +// actually any color other than white or gray) in the color map. The color +// white is for vertices that are not part of the path, while gray is for +// those that are on the path (for cycle detection). The vector path is used +// for temporary storage and as the result of the algorithm; while all +// elements of the path except the last have their colors set to gray upon +// return. Vertex s must start off colored white. +// +// Useful references: +// http://everything2.com/title/loop-erased+random+walk +// Wikipedia page on "Loop-Erased Random Walk" + +template < typename Graph, typename ColorMap, typename NextEdge > +void loop_erased_random_walk(const Graph& g, + typename boost::graph_traits< Graph >::vertex_descriptor s, + NextEdge next_edge, ColorMap color, + std::vector< typename boost::graph_traits< Graph >::vertex_descriptor >& + path) +{ + typedef typename boost::graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + typedef + typename boost::graph_traits< Graph >::edge_descriptor edge_descriptor; + typedef typename boost::property_traits< ColorMap >::value_type color_t; + typedef boost::color_traits< color_t > color_gen; + + BOOST_ASSERT(get(color, s) == color_gen::white()); + path.clear(); + path.push_back(s); + put(color, s, color_gen::gray()); + while (true) + { + edge_descriptor e = next_edge(s, g); + vertex_descriptor t = target(e, g); + color_t t_color = get(color, t); + if (t_color == color_gen::white()) + { + path.push_back(t); + put(color, t, color_gen::gray()); + s = t; + } + else if (t_color == color_gen::gray()) + { + // Found a loop; delete from path from the first occurrence of t to + // the end, coloring vertices white. + typename std::vector< vertex_descriptor >::iterator it + = std::find(path.begin(), path.end(), t); + BOOST_ASSERT(it != path.end()); + ++it; + for (typename std::vector< vertex_descriptor >::iterator j = it; + j != path.end(); ++j) + { + put(color, *j, color_gen::white()); + } + path.erase(it, path.end()); + s = t; + } + else + { + // Done + path.push_back(t); + break; + } + } +} + +template < typename Graph, typename Gen > class unweighted_random_out_edge_gen +{ + Gen& gen; + + typedef boost::graph_traits< Graph > gt; + +public: + unweighted_random_out_edge_gen(Gen& gen) : gen(gen) {} + + typename gt::edge_descriptor operator()( + typename gt::vertex_descriptor src, const Graph& g) const + { + if (out_degree(src, g) == 0) + throw loop_erased_random_walk_stuck(); + return boost::random_out_edge(g, src, gen); + } +}; + +template < typename Graph, typename WeightMap, typename Gen > +class weighted_random_out_edge_gen +{ + WeightMap weight; + Gen& gen; + + typedef boost::graph_traits< Graph > gt; + +public: + weighted_random_out_edge_gen(const WeightMap& weight, Gen& gen) + : weight(weight), gen(gen) + { + } + + typename gt::edge_descriptor operator()( + typename gt::vertex_descriptor src, const Graph& g) const + { + if (out_degree(src, g) == 0) + throw loop_erased_random_walk_stuck(); + return boost::weighted_random_out_edge(g, src, weight, gen); + } +}; +} + +#endif // BOOST_GRAPH_LOOP_ERASED_RANDOM_WALK_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/make_biconnected_planar.hpp b/contrib/restricted/boost/graph/include/boost/graph/make_biconnected_planar.hpp new file mode 100644 index 0000000000..60f40772a8 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/make_biconnected_planar.hpp @@ -0,0 +1,96 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __MAKE_BICONNECTED_PLANAR_HPP__ +#define __MAKE_BICONNECTED_PLANAR_HPP__ + +#include <boost/config.hpp> +#include <boost/tuple/tuple.hpp> //for tie +#include <boost/graph/biconnected_components.hpp> +#include <boost/property_map/property_map.hpp> +#include <vector> +#include <iterator> +#include <algorithm> + +#include <boost/graph/planar_detail/add_edge_visitors.hpp> + +namespace boost +{ + +template < typename Graph, typename PlanarEmbedding, typename EdgeIndexMap, + typename AddEdgeVisitor > +void make_biconnected_planar( + Graph& g, PlanarEmbedding embedding, EdgeIndexMap em, AddEdgeVisitor& vis) +{ + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef typename graph_traits< Graph >::edges_size_type edge_size_t; + typedef typename property_traits< PlanarEmbedding >::value_type + embedding_value_t; + typedef typename embedding_value_t::const_iterator embedding_iterator_t; + typedef iterator_property_map< std::vector< std::size_t >::iterator, + EdgeIndexMap > + component_map_t; + + edge_size_t n_edges(num_edges(g)); + std::vector< vertex_t > articulation_points; + std::vector< edge_size_t > component_vector(n_edges); + component_map_t component_map(component_vector.begin(), em); + + biconnected_components( + g, component_map, std::back_inserter(articulation_points)); + + typename std::vector< vertex_t >::iterator ap, ap_end; + ap_end = articulation_points.end(); + for (ap = articulation_points.begin(); ap != ap_end; ++ap) + { + vertex_t v(*ap); + embedding_iterator_t pi = embedding[v].begin(); + embedding_iterator_t pi_end = embedding[v].end(); + edge_size_t previous_component(n_edges + 1); + vertex_t previous_vertex = graph_traits< Graph >::null_vertex(); + + for (; pi != pi_end; ++pi) + { + edge_t e(*pi); + vertex_t e_source(source(e, g)); + vertex_t e_target(target(e, g)); + + // Skip self-loops and parallel edges + if (e_source == e_target || previous_vertex == e_target) + continue; + + vertex_t current_vertex = e_source == v ? e_target : e_source; + edge_size_t current_component = component_map[e]; + if (previous_vertex != graph_traits< Graph >::null_vertex() + && current_component != previous_component) + { + vis.visit_vertex_pair(current_vertex, previous_vertex, g); + } + previous_vertex = current_vertex; + previous_component = current_component; + } + } +} + +template < typename Graph, typename PlanarEmbedding, typename EdgeIndexMap > +inline void make_biconnected_planar( + Graph& g, PlanarEmbedding embedding, EdgeIndexMap em) +{ + default_add_edge_visitor vis; + make_biconnected_planar(g, embedding, em, vis); +} + +template < typename Graph, typename PlanarEmbedding > +inline void make_biconnected_planar(Graph& g, PlanarEmbedding embedding) +{ + make_biconnected_planar(g, embedding, get(edge_index, g)); +} + +} // namespace boost + +#endif //__MAKE_BICONNECTED_PLANAR_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/make_connected.hpp b/contrib/restricted/boost/graph/include/boost/graph/make_connected.hpp new file mode 100644 index 0000000000..de36590673 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/make_connected.hpp @@ -0,0 +1,79 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __MAKE_CONNECTED_HPP__ +#define __MAKE_CONNECTED_HPP__ + +#include <boost/config.hpp> +#include <boost/next_prior.hpp> +#include <boost/tuple/tuple.hpp> //for tie +#include <boost/graph/connected_components.hpp> +#include <boost/property_map/property_map.hpp> +#include <vector> + +#include <boost/graph/planar_detail/add_edge_visitors.hpp> +#include <boost/graph/planar_detail/bucket_sort.hpp> + +namespace boost +{ + +template < typename Graph, typename VertexIndexMap, typename AddEdgeVisitor > +void make_connected(Graph& g, VertexIndexMap vm, AddEdgeVisitor& vis) +{ + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + typedef iterator_property_map< typename std::vector< v_size_t >::iterator, + VertexIndexMap > + vertex_to_v_size_map_t; + + std::vector< v_size_t > component_vector(num_vertices(g)); + vertex_to_v_size_map_t component(component_vector.begin(), vm); + std::vector< vertex_t > vertices_by_component(num_vertices(g)); + + v_size_t num_components = connected_components(g, component); + + if (num_components < 2) + return; + + vertex_iterator_t vi, vi_end; + boost::tie(vi, vi_end) = vertices(g); + std::copy(vi, vi_end, vertices_by_component.begin()); + + bucket_sort(vertices_by_component.begin(), vertices_by_component.end(), + component, num_components); + + typedef typename std::vector< vertex_t >::iterator vec_of_vertices_itr_t; + + vec_of_vertices_itr_t ci_end = vertices_by_component.end(); + vec_of_vertices_itr_t ci_prev = vertices_by_component.begin(); + if (ci_prev == ci_end) + return; + + for (vec_of_vertices_itr_t ci = boost::next(ci_prev); ci != ci_end; + ci_prev = ci, ++ci) + { + if (component[*ci_prev] != component[*ci]) + vis.visit_vertex_pair(*ci_prev, *ci, g); + } +} + +template < typename Graph, typename VertexIndexMap > +inline void make_connected(Graph& g, VertexIndexMap vm) +{ + default_add_edge_visitor vis; + make_connected(g, vm, vis); +} + +template < typename Graph > inline void make_connected(Graph& g) +{ + make_connected(g, get(vertex_index, g)); +} + +} // namespace boost + +#endif //__MAKE_CONNECTED_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/make_maximal_planar.hpp b/contrib/restricted/boost/graph/include/boost/graph/make_maximal_planar.hpp new file mode 100644 index 0000000000..4f19b8a6fc --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/make_maximal_planar.hpp @@ -0,0 +1,213 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __MAKE_MAXIMAL_PLANAR_HPP__ +#define __MAKE_MAXIMAL_PLANAR_HPP__ + +#include <boost/config.hpp> +#include <boost/tuple/tuple.hpp> //for tie +#include <boost/graph/biconnected_components.hpp> +#include <boost/property_map/property_map.hpp> +#include <vector> +#include <iterator> +#include <algorithm> + +#include <boost/graph/planar_face_traversal.hpp> +#include <boost/graph/planar_detail/add_edge_visitors.hpp> + +namespace boost +{ + +template < typename Graph, typename VertexIndexMap, typename AddEdgeVisitor > +struct triangulation_visitor : public planar_face_traversal_visitor +{ + + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + typedef typename graph_traits< Graph >::degree_size_type degree_size_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef + typename graph_traits< Graph >::adjacency_iterator adjacency_iterator_t; + typedef typename std::vector< vertex_t > vertex_vector_t; + typedef typename std::vector< v_size_t > v_size_vector_t; + typedef typename std::vector< degree_size_t > degree_size_vector_t; + typedef iterator_property_map< typename v_size_vector_t::iterator, + VertexIndexMap > + vertex_to_v_size_map_t; + typedef iterator_property_map< typename degree_size_vector_t::iterator, + VertexIndexMap > + vertex_to_degree_size_map_t; + typedef typename vertex_vector_t::iterator face_iterator; + + triangulation_visitor(Graph& arg_g, VertexIndexMap arg_vm, + AddEdgeVisitor arg_add_edge_visitor) + : g(arg_g) + , vm(arg_vm) + , add_edge_visitor(arg_add_edge_visitor) + , timestamp(0) + , marked_vector(num_vertices(g), timestamp) + , degree_vector(num_vertices(g), 0) + , marked(marked_vector.begin(), vm) + , degree(degree_vector.begin(), vm) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(degree, *vi, out_degree(*vi, g)); + } + + template < typename Vertex > void next_vertex(Vertex v) + { + // Self-loops will appear as consecutive vertices in the list of + // vertices on a face. We want to skip these. + if (!vertices_on_face.empty() + && (vertices_on_face.back() == v || vertices_on_face.front() == v)) + return; + + vertices_on_face.push_back(v); + } + + void end_face() + { + ++timestamp; + + if (vertices_on_face.size() <= 3) + { + // At most three vertices on this face - don't need to triangulate + vertices_on_face.clear(); + return; + } + + // Find vertex on face of minimum degree + degree_size_t min_degree = num_vertices(g); + typename vertex_vector_t::iterator min_degree_vertex_itr; + face_iterator fi_end = vertices_on_face.end(); + for (face_iterator fi = vertices_on_face.begin(); fi != fi_end; ++fi) + { + degree_size_t deg = get(degree, *fi); + if (deg < min_degree) + { + min_degree_vertex_itr = fi; + min_degree = deg; + } + } + + // To simplify some of the manipulations, we'll re-arrange + // vertices_on_face so that it still contains the same + // (counter-clockwise) order of the vertices on this face, but now the + // min_degree_vertex is the first element in vertices_on_face. + vertex_vector_t temp_vector; + std::copy(min_degree_vertex_itr, vertices_on_face.end(), + std::back_inserter(temp_vector)); + std::copy(vertices_on_face.begin(), min_degree_vertex_itr, + std::back_inserter(temp_vector)); + vertices_on_face.swap(temp_vector); + + // Mark all of the min degree vertex's neighbors + adjacency_iterator_t ai, ai_end; + for (boost::tie(ai, ai_end) + = adjacent_vertices(vertices_on_face.front(), g); + ai != ai_end; ++ai) + { + put(marked, *ai, timestamp); + } + + typename vertex_vector_t::iterator marked_neighbor + = vertices_on_face.end(); + + // The iterator manipulations on the next two lines are safe because + // vertices_on_face.size() > 3 (from the first test in this function) + fi_end = prior(vertices_on_face.end()); + for (face_iterator fi + = boost::next(boost::next(vertices_on_face.begin())); + fi != fi_end; ++fi) + { + if (get(marked, *fi) == timestamp) + { + marked_neighbor = fi; + break; + } + } + + if (marked_neighbor == vertices_on_face.end()) + { + add_edge_range(vertices_on_face[0], + boost::next(boost::next(vertices_on_face.begin())), + prior(vertices_on_face.end())); + } + else + { + add_edge_range(vertices_on_face[1], boost::next(marked_neighbor), + vertices_on_face.end()); + + add_edge_range(*boost::next(marked_neighbor), + boost::next(boost::next(vertices_on_face.begin())), + marked_neighbor); + } + + // reset for the next face + vertices_on_face.clear(); + } + +private: + void add_edge_range(vertex_t anchor, face_iterator fi, face_iterator fi_end) + { + for (; fi != fi_end; ++fi) + { + vertex_t v(*fi); + add_edge_visitor.visit_vertex_pair(anchor, v, g); + put(degree, anchor, get(degree, anchor) + 1); + put(degree, v, get(degree, v) + 1); + } + } + + Graph& g; + VertexIndexMap vm; + AddEdgeVisitor add_edge_visitor; + v_size_t timestamp; + vertex_vector_t vertices_on_face; + v_size_vector_t marked_vector; + degree_size_vector_t degree_vector; + vertex_to_v_size_map_t marked; + vertex_to_degree_size_map_t degree; +}; + +template < typename Graph, typename PlanarEmbedding, typename VertexIndexMap, + typename EdgeIndexMap, typename AddEdgeVisitor > +void make_maximal_planar(Graph& g, PlanarEmbedding embedding, VertexIndexMap vm, + EdgeIndexMap em, AddEdgeVisitor& vis) +{ + triangulation_visitor< Graph, VertexIndexMap, AddEdgeVisitor > visitor( + g, vm, vis); + planar_face_traversal(g, embedding, visitor, em); +} + +template < typename Graph, typename PlanarEmbedding, typename VertexIndexMap, + typename EdgeIndexMap > +void make_maximal_planar( + Graph& g, PlanarEmbedding embedding, VertexIndexMap vm, EdgeIndexMap em) +{ + default_add_edge_visitor vis; + make_maximal_planar(g, embedding, vm, em, vis); +} + +template < typename Graph, typename PlanarEmbedding, typename VertexIndexMap > +void make_maximal_planar(Graph& g, PlanarEmbedding embedding, VertexIndexMap vm) +{ + make_maximal_planar(g, embedding, vm, get(edge_index, g)); +} + +template < typename Graph, typename PlanarEmbedding > +void make_maximal_planar(Graph& g, PlanarEmbedding embedding) +{ + make_maximal_planar(g, embedding, get(vertex_index, g)); +} + +} // namespace boost + +#endif //__MAKE_MAXIMAL_PLANAR_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/matrix_as_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/matrix_as_graph.hpp new file mode 100644 index 0000000000..b5df6cd9fe --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/matrix_as_graph.hpp @@ -0,0 +1,167 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_MATRIX2GRAPH_HPP +#define BOOST_GRAPH_MATRIX2GRAPH_HPP + +#include <utility> +#include <cstddef> +#include <iterator> +#include <boost/config.hpp> +#include <boost/operators.hpp> +#include <boost/pending/detail/int_iterator.hpp> +#include <boost/graph/graph_traits.hpp> + +namespace boost +{ + +template < class Iter, class Vertex > class matrix_adj_iterator; + +template < class Iter, class Vertex > class matrix_incidence_iterator; + +} + +#define BOOST_GRAPH_ADAPT_MATRIX_TO_GRAPH(Matrix) \ + namespace boost \ + { \ + template <> struct graph_traits< Matrix > \ + { \ + typedef Matrix::OneD::const_iterator Iter; \ + typedef Matrix::size_type V; \ + typedef V vertex_descriptor; \ + typedef Iter E; \ + typedef E edge_descriptor; \ + typedef boost::matrix_incidence_iterator< Iter, V > \ + out_edge_iterator; \ + typedef boost::matrix_adj_iterator< Iter, V > adjacency_iterator; \ + typedef Matrix::size_type size_type; \ + typedef boost::int_iterator< size_type > vertex_iterator; \ + \ + friend std::pair< vertex_iterator, vertex_iterator > vertices( \ + const Matrix& g) \ + { \ + typedef vertex_iterator VIter; \ + return std::make_pair(VIter(0), VIter(g.nrows())); \ + } \ + \ + friend std::pair< out_edge_iterator, out_edge_iterator > \ + out_edges(V v, const Matrix& g) \ + { \ + typedef out_edge_iterator IncIter; \ + return std::make_pair( \ + IncIter(g[v].begin()), IncIter(g[v].end())); \ + } \ + friend std::pair< adjacency_iterator, adjacency_iterator > \ + adjacent_vertices(V v, const Matrix& g) \ + { \ + typedef adjacency_iterator AdjIter; \ + return std::make_pair( \ + AdjIter(g[v].begin()), AdjIter(g[v].end())); \ + } \ + friend vertex_descriptor source(E e, const Matrix& g) \ + { \ + return e.row(); \ + } \ + friend vertex_descriptor target(E e, const Matrix& g) \ + { \ + return e.column(); \ + } \ + friend size_type num_vertices(const Matrix& g) \ + { \ + return g.nrows(); \ + } \ + friend size_type num_edges(const Matrix& g) { return g.nnz(); } \ + friend size_type out_degree(V i, const Matrix& g) \ + { \ + return g[i].nnz(); \ + } \ + }; \ + } + +namespace boost +{ + +template < class Iter, class Vertex > class matrix_adj_iterator +{ + typedef matrix_adj_iterator self; + +public: + typedef std::input_iterator_tag iterator_category; + typedef Vertex value_type; + typedef std::ptrdiff_t difference_type; + typedef Vertex* pointer; + typedef Vertex& reference; + matrix_adj_iterator() {} + matrix_adj_iterator(Iter i) : _iter(i) {} + matrix_adj_iterator(const self& x) : _iter(x._iter) {} + self& operator=(const self& x) + { + _iter = x._iter; + return *this; + } + Vertex operator*() { return _iter.column(); } + self& operator++() + { + ++_iter; + return *this; + } + self operator++(int) + { + self t = *this; + ++_iter; + return t; + } + bool operator==(const self& x) const { return _iter == x._iter; } + bool operator!=(const self& x) const { return _iter != x._iter; } + +protected: + Iter _iter; +}; + +template < class Iter, class Vertex > class matrix_incidence_iterator +{ + typedef matrix_incidence_iterator self; + +public: + typedef std::input_iterator_tag iterator_category; + typedef Iter value_type; + typedef std::ptrdiff_t difference_type; + typedef Iter* pointer; + typedef Iter& reference; + matrix_incidence_iterator() {} + matrix_incidence_iterator(Iter i) : _iter(i) {} + matrix_incidence_iterator(const self& x) : _iter(x._iter) {} + self& operator=(const self& x) + { + _iter = x._iter; + return *this; + } + Iter operator*() { return _iter; } + self& operator++() + { + ++_iter; + return *this; + } + self operator++(int) + { + self t = *this; + ++_iter; + return t; + } + bool operator==(const self& x) const { return _iter == x._iter; } + bool operator!=(const self& x) const { return _iter != x._iter; } + +protected: + Iter _iter; +}; + +} /* namespace boost */ + +#endif /* BOOST_GRAPH_MATRIX2GRAPH_HPP*/ diff --git a/contrib/restricted/boost/graph/include/boost/graph/max_cardinality_matching.hpp b/contrib/restricted/boost/graph/include/boost/graph/max_cardinality_matching.hpp new file mode 100644 index 0000000000..082c2bd38a --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/max_cardinality_matching.hpp @@ -0,0 +1,844 @@ +//======================================================================= +// Copyright (c) 2005 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +//======================================================================= + +#ifndef BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP +#define BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP + +#include <vector> +#include <list> +#include <deque> +#include <algorithm> // for std::sort and std::stable_sort +#include <utility> // for std::pair +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/visitors.hpp> +#include <boost/graph/depth_first_search.hpp> +#include <boost/graph/filtered_graph.hpp> +#include <boost/pending/disjoint_sets.hpp> +#include <boost/assert.hpp> + +namespace boost +{ +namespace graph +{ + namespace detail + { + enum VERTEX_STATE + { + V_EVEN, + V_ODD, + V_UNREACHED + }; + } +} // end namespace graph::detail + +template < typename Graph, typename MateMap, typename VertexIndexMap > +typename graph_traits< Graph >::vertices_size_type matching_size( + const Graph& g, MateMap mate, VertexIndexMap vm) +{ + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + + v_size_t size_of_matching = 0; + vertex_iterator_t vi, vi_end; + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v = *vi; + if (get(mate, v) != graph_traits< Graph >::null_vertex() + && get(vm, v) < get(vm, get(mate, v))) + ++size_of_matching; + } + return size_of_matching; +} + +template < typename Graph, typename MateMap > +inline typename graph_traits< Graph >::vertices_size_type matching_size( + const Graph& g, MateMap mate) +{ + return matching_size(g, mate, get(vertex_index, g)); +} + +template < typename Graph, typename MateMap, typename VertexIndexMap > +bool is_a_matching(const Graph& g, MateMap mate, VertexIndexMap) +{ + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v = *vi; + if (get(mate, v) != graph_traits< Graph >::null_vertex() + && v != get(mate, get(mate, v))) + return false; + } + return true; +} + +template < typename Graph, typename MateMap > +inline bool is_a_matching(const Graph& g, MateMap mate) +{ + return is_a_matching(g, mate, get(vertex_index, g)); +} + +//*************************************************************************** +//*************************************************************************** +// Maximum Cardinality Matching Functors +//*************************************************************************** +//*************************************************************************** + +template < typename Graph, typename MateMap, + typename VertexIndexMap = dummy_property_map > +struct no_augmenting_path_finder +{ + no_augmenting_path_finder(const Graph&, MateMap, VertexIndexMap) {} + + inline bool augment_matching() { return false; } + + template < typename PropertyMap > void get_current_matching(PropertyMap) {} +}; + +template < typename Graph, typename MateMap, typename VertexIndexMap > +class edmonds_augmenting_path_finder +{ + // This implementation of Edmonds' matching algorithm closely + // follows Tarjan's description of the algorithm in "Data + // Structures and Network Algorithms." + +public: + // generates the type of an iterator property map from vertices to type X + template < typename X > struct map_vertex_to_ + { + typedef boost::iterator_property_map< + typename std::vector< X >::iterator, VertexIndexMap > + type; + }; + + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename std::pair< vertex_descriptor_t, vertex_descriptor_t > + vertex_pair_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + typedef typename graph_traits< Graph >::edges_size_type e_size_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef + typename graph_traits< Graph >::out_edge_iterator out_edge_iterator_t; + typedef typename std::deque< vertex_descriptor_t > vertex_list_t; + typedef typename std::vector< edge_descriptor_t > edge_list_t; + typedef typename map_vertex_to_< vertex_descriptor_t >::type + vertex_to_vertex_map_t; + typedef typename map_vertex_to_< int >::type vertex_to_int_map_t; + typedef typename map_vertex_to_< vertex_pair_t >::type + vertex_to_vertex_pair_map_t; + typedef typename map_vertex_to_< v_size_t >::type vertex_to_vsize_map_t; + typedef typename map_vertex_to_< e_size_t >::type vertex_to_esize_map_t; + + edmonds_augmenting_path_finder( + const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm) + : g(arg_g) + , vm(arg_vm) + , n_vertices(num_vertices(arg_g)) + , + + mate_vector(n_vertices) + , ancestor_of_v_vector(n_vertices) + , ancestor_of_w_vector(n_vertices) + , vertex_state_vector(n_vertices) + , origin_vector(n_vertices) + , pred_vector(n_vertices) + , bridge_vector(n_vertices) + , ds_parent_vector(n_vertices) + , ds_rank_vector(n_vertices) + , + + mate(mate_vector.begin(), vm) + , ancestor_of_v(ancestor_of_v_vector.begin(), vm) + , ancestor_of_w(ancestor_of_w_vector.begin(), vm) + , vertex_state(vertex_state_vector.begin(), vm) + , origin(origin_vector.begin(), vm) + , pred(pred_vector.begin(), vm) + , bridge(bridge_vector.begin(), vm) + , ds_parent_map(ds_parent_vector.begin(), vm) + , ds_rank_map(ds_rank_vector.begin(), vm) + , + + ds(ds_rank_map, ds_parent_map) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + mate[*vi] = get(arg_mate, *vi); + } + + bool augment_matching() + { + // As an optimization, some of these values can be saved from one + // iteration to the next instead of being re-initialized each + // iteration, allowing for "lazy blossom expansion." This is not + // currently implemented. + + e_size_t timestamp = 0; + even_edges.clear(); + + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t u = *vi; + + origin[u] = u; + pred[u] = u; + ancestor_of_v[u] = 0; + ancestor_of_w[u] = 0; + ds.make_set(u); + + if (mate[u] == graph_traits< Graph >::null_vertex()) + { + vertex_state[u] = graph::detail::V_EVEN; + out_edge_iterator_t ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; + ++ei) + { + if (target(*ei, g) != u) + { + even_edges.push_back(*ei); + } + } + } + else + vertex_state[u] = graph::detail::V_UNREACHED; + } + + // end initializations + + vertex_descriptor_t v, w, w_free_ancestor, v_free_ancestor; + w_free_ancestor = graph_traits< Graph >::null_vertex(); + v_free_ancestor = graph_traits< Graph >::null_vertex(); + bool found_alternating_path = false; + + while (!even_edges.empty() && !found_alternating_path) + { + // since we push even edges onto the back of the list as + // they're discovered, taking them off the back will search + // for augmenting paths depth-first. + edge_descriptor_t current_edge = even_edges.back(); + even_edges.pop_back(); + + v = source(current_edge, g); + w = target(current_edge, g); + + vertex_descriptor_t v_prime = origin[ds.find_set(v)]; + vertex_descriptor_t w_prime = origin[ds.find_set(w)]; + + // because of the way we put all of the edges on the queue, + // v_prime should be labeled V_EVEN; the following is a + // little paranoid but it could happen... + if (vertex_state[v_prime] != graph::detail::V_EVEN) + { + std::swap(v_prime, w_prime); + std::swap(v, w); + } + + if (vertex_state[w_prime] == graph::detail::V_UNREACHED) + { + vertex_state[w_prime] = graph::detail::V_ODD; + vertex_descriptor_t w_prime_mate = mate[w_prime]; + vertex_state[w_prime_mate] = graph::detail::V_EVEN; + out_edge_iterator_t ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(w_prime_mate, g); + ei != ei_end; ++ei) + { + if (target(*ei, g) != w_prime_mate) + { + even_edges.push_back(*ei); + } + } + pred[w_prime] = v; + } + + // w_prime == v_prime can happen below if we get an edge that has + // been shrunk into a blossom + else if (vertex_state[w_prime] == graph::detail::V_EVEN + && w_prime != v_prime) + { + vertex_descriptor_t w_up = w_prime; + vertex_descriptor_t v_up = v_prime; + vertex_descriptor_t nearest_common_ancestor + = graph_traits< Graph >::null_vertex(); + w_free_ancestor = graph_traits< Graph >::null_vertex(); + v_free_ancestor = graph_traits< Graph >::null_vertex(); + + // We now need to distinguish between the case that + // w_prime and v_prime share an ancestor under the + // "parent" relation, in which case we've found a + // blossom and should shrink it, or the case that + // w_prime and v_prime both have distinct ancestors that + // are free, in which case we've found an alternating + // path between those two ancestors. + + ++timestamp; + + while (nearest_common_ancestor + == graph_traits< Graph >::null_vertex() + && (v_free_ancestor == graph_traits< Graph >::null_vertex() + || w_free_ancestor + == graph_traits< Graph >::null_vertex())) + { + ancestor_of_w[w_up] = timestamp; + ancestor_of_v[v_up] = timestamp; + + if (w_free_ancestor == graph_traits< Graph >::null_vertex()) + w_up = parent(w_up); + if (v_free_ancestor == graph_traits< Graph >::null_vertex()) + v_up = parent(v_up); + + if (mate[v_up] == graph_traits< Graph >::null_vertex()) + v_free_ancestor = v_up; + if (mate[w_up] == graph_traits< Graph >::null_vertex()) + w_free_ancestor = w_up; + + if (ancestor_of_w[v_up] == timestamp) + nearest_common_ancestor = v_up; + else if (ancestor_of_v[w_up] == timestamp) + nearest_common_ancestor = w_up; + else if (v_free_ancestor == w_free_ancestor + && v_free_ancestor + != graph_traits< Graph >::null_vertex()) + nearest_common_ancestor = v_up; + } + + if (nearest_common_ancestor + == graph_traits< Graph >::null_vertex()) + found_alternating_path = true; // to break out of the loop + else + { + // shrink the blossom + link_and_set_bridges( + w_prime, nearest_common_ancestor, std::make_pair(w, v)); + link_and_set_bridges( + v_prime, nearest_common_ancestor, std::make_pair(v, w)); + } + } + } + + if (!found_alternating_path) + return false; + + // retrieve the augmenting path and put it in aug_path + reversed_retrieve_augmenting_path(v, v_free_ancestor); + retrieve_augmenting_path(w, w_free_ancestor); + + // augment the matching along aug_path + vertex_descriptor_t a, b; + while (!aug_path.empty()) + { + a = aug_path.front(); + aug_path.pop_front(); + b = aug_path.front(); + aug_path.pop_front(); + mate[a] = b; + mate[b] = a; + } + + return true; + } + + template < typename PropertyMap > void get_current_matching(PropertyMap pm) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(pm, *vi, mate[*vi]); + } + + template < typename PropertyMap > void get_vertex_state_map(PropertyMap pm) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(pm, *vi, vertex_state[origin[ds.find_set(*vi)]]); + } + +private: + vertex_descriptor_t parent(vertex_descriptor_t x) + { + if (vertex_state[x] == graph::detail::V_EVEN + && mate[x] != graph_traits< Graph >::null_vertex()) + return mate[x]; + else if (vertex_state[x] == graph::detail::V_ODD) + return origin[ds.find_set(pred[x])]; + else + return x; + } + + void link_and_set_bridges(vertex_descriptor_t x, + vertex_descriptor_t stop_vertex, vertex_pair_t the_bridge) + { + for (vertex_descriptor_t v = x; v != stop_vertex; v = parent(v)) + { + ds.union_set(v, stop_vertex); + origin[ds.find_set(stop_vertex)] = stop_vertex; + + if (vertex_state[v] == graph::detail::V_ODD) + { + bridge[v] = the_bridge; + out_edge_iterator_t oei, oei_end; + for (boost::tie(oei, oei_end) = out_edges(v, g); oei != oei_end; + ++oei) + { + if (target(*oei, g) != v) + { + even_edges.push_back(*oei); + } + } + } + } + } + + // Since none of the STL containers support both constant-time + // concatenation and reversal, the process of expanding an + // augmenting path once we know one exists is a little more + // complicated than it has to be. If we know the path is from v to + // w, then the augmenting path is recursively defined as: + // + // path(v,w) = [v], if v = w + // = concat([v, mate[v]], path(pred[mate[v]], w), + // if v != w and vertex_state[v] == graph::detail::V_EVEN + // = concat([v], reverse(path(x,mate[v])), path(y,w)), + // if v != w, vertex_state[v] == graph::detail::V_ODD, and + // bridge[v] = (x,y) + // + // These next two mutually recursive functions implement this definition. + + void retrieve_augmenting_path(vertex_descriptor_t v, vertex_descriptor_t w) + { + if (v == w) + aug_path.push_back(v); + else if (vertex_state[v] == graph::detail::V_EVEN) + { + aug_path.push_back(v); + aug_path.push_back(mate[v]); + retrieve_augmenting_path(pred[mate[v]], w); + } + else // vertex_state[v] == graph::detail::V_ODD + { + aug_path.push_back(v); + reversed_retrieve_augmenting_path(bridge[v].first, mate[v]); + retrieve_augmenting_path(bridge[v].second, w); + } + } + + void reversed_retrieve_augmenting_path( + vertex_descriptor_t v, vertex_descriptor_t w) + { + + if (v == w) + aug_path.push_back(v); + else if (vertex_state[v] == graph::detail::V_EVEN) + { + reversed_retrieve_augmenting_path(pred[mate[v]], w); + aug_path.push_back(mate[v]); + aug_path.push_back(v); + } + else // vertex_state[v] == graph::detail::V_ODD + { + reversed_retrieve_augmenting_path(bridge[v].second, w); + retrieve_augmenting_path(bridge[v].first, mate[v]); + aug_path.push_back(v); + } + } + + // private data members + + const Graph& g; + VertexIndexMap vm; + v_size_t n_vertices; + + // storage for the property maps below + std::vector< vertex_descriptor_t > mate_vector; + std::vector< e_size_t > ancestor_of_v_vector; + std::vector< e_size_t > ancestor_of_w_vector; + std::vector< int > vertex_state_vector; + std::vector< vertex_descriptor_t > origin_vector; + std::vector< vertex_descriptor_t > pred_vector; + std::vector< vertex_pair_t > bridge_vector; + std::vector< vertex_descriptor_t > ds_parent_vector; + std::vector< v_size_t > ds_rank_vector; + + // iterator property maps + vertex_to_vertex_map_t mate; + vertex_to_esize_map_t ancestor_of_v; + vertex_to_esize_map_t ancestor_of_w; + vertex_to_int_map_t vertex_state; + vertex_to_vertex_map_t origin; + vertex_to_vertex_map_t pred; + vertex_to_vertex_pair_map_t bridge; + vertex_to_vertex_map_t ds_parent_map; + vertex_to_vsize_map_t ds_rank_map; + + vertex_list_t aug_path; + edge_list_t even_edges; + disjoint_sets< vertex_to_vsize_map_t, vertex_to_vertex_map_t > ds; +}; + +//*************************************************************************** +//*************************************************************************** +// Initial Matching Functors +//*************************************************************************** +//*************************************************************************** + +template < typename Graph, typename MateMap > struct greedy_matching +{ + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + + static void find_matching(const Graph& g, MateMap mate) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(mate, *vi, graph_traits< Graph >::null_vertex()); + + edge_iterator_t ei, ei_end; + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_descriptor_t e = *ei; + vertex_descriptor_t u = source(e, g); + vertex_descriptor_t v = target(e, g); + + if (u != v && get(mate, u) == get(mate, v)) + // only way equality can hold is if + // mate[u] == mate[v] == null_vertex + { + put(mate, u, v); + put(mate, v, u); + } + } + } +}; + +template < typename Graph, typename MateMap > struct extra_greedy_matching +{ + // The "extra greedy matching" is formed by repeating the + // following procedure as many times as possible: Choose the + // unmatched vertex v of minimum non-zero degree. Choose the + // neighbor w of v which is unmatched and has minimum degree over + // all of v's neighbors. Add (u,v) to the matching. Ties for + // either choice are broken arbitrarily. This procedure takes time + // O(m log n), where m is the number of edges in the graph and n + // is the number of vertices. + + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + typedef std::pair< vertex_descriptor_t, vertex_descriptor_t > vertex_pair_t; + + struct select_first + { + inline static vertex_descriptor_t select_vertex(const vertex_pair_t p) + { + return p.first; + } + }; + + struct select_second + { + inline static vertex_descriptor_t select_vertex(const vertex_pair_t p) + { + return p.second; + } + }; + + template < class PairSelector > class less_than_by_degree + { + public: + less_than_by_degree(const Graph& g) : m_g(g) {} + bool operator()(const vertex_pair_t x, const vertex_pair_t y) + { + return out_degree(PairSelector::select_vertex(x), m_g) + < out_degree(PairSelector::select_vertex(y), m_g); + } + + private: + const Graph& m_g; + }; + + static void find_matching(const Graph& g, MateMap mate) + { + typedef std::vector< + std::pair< vertex_descriptor_t, vertex_descriptor_t > > + directed_edges_vector_t; + + directed_edges_vector_t edge_list; + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(mate, *vi, graph_traits< Graph >::null_vertex()); + + edge_iterator_t ei, ei_end; + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_descriptor_t e = *ei; + vertex_descriptor_t u = source(e, g); + vertex_descriptor_t v = target(e, g); + if (u == v) + continue; + edge_list.push_back(std::make_pair(u, v)); + edge_list.push_back(std::make_pair(v, u)); + } + + // sort the edges by the degree of the target, then (using a + // stable sort) by degree of the source + std::sort(edge_list.begin(), edge_list.end(), + less_than_by_degree< select_second >(g)); + std::stable_sort(edge_list.begin(), edge_list.end(), + less_than_by_degree< select_first >(g)); + + // construct the extra greedy matching + for (typename directed_edges_vector_t::const_iterator itr + = edge_list.begin(); + itr != edge_list.end(); ++itr) + { + if (get(mate, itr->first) == get(mate, itr->second)) + // only way equality can hold is if mate[itr->first] == + // mate[itr->second] == null_vertex + { + put(mate, itr->first, itr->second); + put(mate, itr->second, itr->first); + } + } + } +}; + +template < typename Graph, typename MateMap > struct empty_matching +{ + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + + static void find_matching(const Graph& g, MateMap mate) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(mate, *vi, graph_traits< Graph >::null_vertex()); + } +}; + +//*************************************************************************** +//*************************************************************************** +// Matching Verifiers +//*************************************************************************** +//*************************************************************************** + +namespace detail +{ + + template < typename SizeType > + class odd_components_counter : public dfs_visitor<> + // This depth-first search visitor will count the number of connected + // components with an odd number of vertices. It's used by + // maximum_matching_verifier. + { + public: + odd_components_counter(SizeType& c_count) : m_count(c_count) + { + m_count = 0; + } + + template < class Vertex, class Graph > void start_vertex(Vertex, Graph&) + { + m_parity = false; + } + + template < class Vertex, class Graph > + void discover_vertex(Vertex, Graph&) + { + m_parity = !m_parity; + m_parity ? ++m_count : --m_count; + } + + protected: + SizeType& m_count; + + private: + bool m_parity; + }; + +} // namespace detail + +template < typename Graph, typename MateMap, + typename VertexIndexMap = dummy_property_map > +struct no_matching_verifier +{ + inline static bool verify_matching(const Graph&, MateMap, VertexIndexMap) + { + return true; + } +}; + +template < typename Graph, typename MateMap, typename VertexIndexMap > +struct maximum_cardinality_matching_verifier +{ + + template < typename X > struct map_vertex_to_ + { + typedef boost::iterator_property_map< + typename std::vector< X >::iterator, VertexIndexMap > + type; + }; + + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename map_vertex_to_< int >::type vertex_to_int_map_t; + typedef typename map_vertex_to_< vertex_descriptor_t >::type + vertex_to_vertex_map_t; + + template < typename VertexStateMap > struct non_odd_vertex + { + // this predicate is used to create a filtered graph that + // excludes vertices labeled "graph::detail::V_ODD" + non_odd_vertex() : vertex_state(0) {} + + non_odd_vertex(VertexStateMap* arg_vertex_state) + : vertex_state(arg_vertex_state) + { + } + + template < typename Vertex > bool operator()(const Vertex& v) const + { + BOOST_ASSERT(vertex_state); + return get(*vertex_state, v) != graph::detail::V_ODD; + } + + VertexStateMap* vertex_state; + }; + + static bool verify_matching(const Graph& g, MateMap mate, VertexIndexMap vm) + { + // For any graph G, let o(G) be the number of connected + // components in G of odd size. For a subset S of G's vertex set + // V(G), let (G - S) represent the subgraph of G induced by + // removing all vertices in S from G. Let M(G) be the size of the + // maximum cardinality matching in G. Then the Tutte-Berge + // formula guarantees that + // + // 2 * M(G) = min ( |V(G)| + |U| + o(G - U) ) + // + // where the minimum is taken over all subsets U of + // V(G). Edmonds' algorithm finds a set U that achieves the + // minimum in the above formula, namely the vertices labeled + //"ODD." This function runs one iteration of Edmonds' algorithm + // to find U, then verifies that the size of the matching given + // by mate satisfies the Tutte-Berge formula. + + // first, make sure it's a valid matching + if (!is_a_matching(g, mate, vm)) + return false; + + // We'll try to augment the matching once. This serves two + // purposes: first, if we find some augmenting path, the matching + // is obviously non-maximum. Second, running edmonds' algorithm + // on a graph with no augmenting path will create the + // Edmonds-Gallai decomposition that we need as a certificate of + // maximality - we can get it by looking at the vertex_state map + // that results. + edmonds_augmenting_path_finder< Graph, MateMap, VertexIndexMap > + augmentor(g, mate, vm); + if (augmentor.augment_matching()) + return false; + + std::vector< int > vertex_state_vector(num_vertices(g)); + vertex_to_int_map_t vertex_state(vertex_state_vector.begin(), vm); + augmentor.get_vertex_state_map(vertex_state); + + // count the number of graph::detail::V_ODD vertices + v_size_t num_odd_vertices = 0; + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + if (vertex_state[*vi] == graph::detail::V_ODD) + ++num_odd_vertices; + + // count the number of connected components with odd cardinality + // in the graph without graph::detail::V_ODD vertices + non_odd_vertex< vertex_to_int_map_t > filter(&vertex_state); + filtered_graph< Graph, keep_all, non_odd_vertex< vertex_to_int_map_t > > + fg(g, keep_all(), filter); + + v_size_t num_odd_components; + detail::odd_components_counter< v_size_t > occ(num_odd_components); + depth_first_search(fg, visitor(occ).vertex_index_map(vm)); + + if (2 * matching_size(g, mate, vm) + == num_vertices(g) + num_odd_vertices - num_odd_components) + return true; + else + return false; + } +}; + +template < typename Graph, typename MateMap, typename VertexIndexMap, + template < typename, typename, typename > class AugmentingPathFinder, + template < typename, typename > class InitialMatchingFinder, + template < typename, typename, typename > class MatchingVerifier > +bool matching(const Graph& g, MateMap mate, VertexIndexMap vm) +{ + + InitialMatchingFinder< Graph, MateMap >::find_matching(g, mate); + + AugmentingPathFinder< Graph, MateMap, VertexIndexMap > augmentor( + g, mate, vm); + bool not_maximum_yet = true; + while (not_maximum_yet) + { + not_maximum_yet = augmentor.augment_matching(); + } + augmentor.get_current_matching(mate); + + return MatchingVerifier< Graph, MateMap, VertexIndexMap >::verify_matching( + g, mate, vm); +} + +template < typename Graph, typename MateMap, typename VertexIndexMap > +inline bool checked_edmonds_maximum_cardinality_matching( + const Graph& g, MateMap mate, VertexIndexMap vm) +{ + return matching< Graph, MateMap, VertexIndexMap, + edmonds_augmenting_path_finder, extra_greedy_matching, + maximum_cardinality_matching_verifier >(g, mate, vm); +} + +template < typename Graph, typename MateMap > +inline bool checked_edmonds_maximum_cardinality_matching( + const Graph& g, MateMap mate) +{ + return checked_edmonds_maximum_cardinality_matching( + g, mate, get(vertex_index, g)); +} + +template < typename Graph, typename MateMap, typename VertexIndexMap > +inline void edmonds_maximum_cardinality_matching( + const Graph& g, MateMap mate, VertexIndexMap vm) +{ + matching< Graph, MateMap, VertexIndexMap, edmonds_augmenting_path_finder, + extra_greedy_matching, no_matching_verifier >(g, mate, vm); +} + +template < typename Graph, typename MateMap > +inline void edmonds_maximum_cardinality_matching(const Graph& g, MateMap mate) +{ + edmonds_maximum_cardinality_matching(g, mate, get(vertex_index, g)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_MAXIMUM_CARDINALITY_MATCHING_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/maximum_adjacency_search.hpp b/contrib/restricted/boost/graph/include/boost/graph/maximum_adjacency_search.hpp new file mode 100644 index 0000000000..ed4b5578d1 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/maximum_adjacency_search.hpp @@ -0,0 +1,399 @@ +// +//======================================================================= +// Copyright 2012 Fernando Vilas +// 2010 Daniel Trebbien +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +// The maximum adjacency search algorithm was originally part of the +// Stoer-Wagner min cut implementation by Daniel Trebbien. It has been +// broken out into its own file to be a public search algorithm, with +// visitor concepts. +#ifndef BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H +#define BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H + +/** + * This is an implementation of the maximum adjacency search on an + * undirected graph. It allows a visitor object to perform some + * operation on each vertex as that vertex is visited. + * + * The algorithm runs as follows: + * + * Initialize all nodes to be unvisited (reach count = 0) + * and call vis.initialize_vertex + * For i = number of nodes in graph downto 1 + * Select the unvisited node with the highest reach count + * The user provides the starting node to break the first tie, + * but future ties are broken arbitrarily + * Visit the node by calling vis.start_vertex + * Increment the reach count for all unvisited neighbors + * and call vis.examine_edge for each of these edges + * Mark the node as visited and call vis.finish_vertex + * + */ + +#include <boost/concept_check.hpp> +#include <boost/concept/assert.hpp> +#include <boost/graph/buffer_concepts.hpp> +#include <boost/graph/exception.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/graph/visitors.hpp> +#include <boost/tuple/tuple.hpp> + +#include <set> + +namespace boost +{ +template < class Visitor, class Graph > struct MASVisitorConcept +{ + void constraints() + { + boost::function_requires< + boost::CopyConstructibleConcept< Visitor > >(); + vis.initialize_vertex(u, g); + vis.start_vertex(u, g); + vis.examine_edge(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename boost::graph_traits< Graph >::vertex_descriptor u; + typename boost::graph_traits< Graph >::edge_descriptor e; +}; + +template < class Visitors = null_visitor > class mas_visitor +{ +public: + mas_visitor() {} + mas_visitor(Visitors vis) : m_vis(vis) {} + + template < class Vertex, class Graph > + void initialize_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_initialize_vertex()); + } + + template < class Vertex, class Graph > void start_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_start_vertex()); + } + + template < class Edge, class Graph > void examine_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, ::boost::on_examine_edge()); + } + + template < class Vertex, class Graph > + void finish_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, ::boost::on_finish_vertex()); + } + + BOOST_GRAPH_EVENT_STUB(on_initialize_vertex, mas) + BOOST_GRAPH_EVENT_STUB(on_start_vertex, mas) + BOOST_GRAPH_EVENT_STUB(on_examine_edge, mas) + BOOST_GRAPH_EVENT_STUB(on_finish_vertex, mas) + +protected: + Visitors m_vis; +}; +template < class Visitors > +mas_visitor< Visitors > make_mas_visitor(Visitors vis) +{ + return mas_visitor< Visitors >(vis); +} +typedef mas_visitor<> default_mas_visitor; + +namespace detail +{ + template < class Graph, class WeightMap, class MASVisitor, + class VertexAssignmentMap, class KeyedUpdatablePriorityQueue > + void maximum_adjacency_search(const Graph& g, WeightMap weights, + MASVisitor vis, + const typename boost::graph_traits< Graph >::vertex_descriptor start, + VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) + { + typedef typename boost::graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + typedef typename boost::property_traits< WeightMap >::value_type + weight_type; + + std::set< vertex_descriptor > assignedVertices; + + // initialize `assignments` (all vertices are initially + // assigned to themselves) + BGL_FORALL_VERTICES_T(v, g, Graph) { put(assignments, v, v); } + + typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); + + // set number of visited neighbors for all vertices to 0 + BGL_FORALL_VERTICES_T(v, g, Graph) + { + if (v == get(assignments, v)) + { // foreach u \in V do + put(keys, v, weight_type(0)); + vis.initialize_vertex(v, g); + + pq.push(v); + } + } + BOOST_ASSERT(pq.size() >= 2); + + // Give the starting vertex high priority + put(keys, start, get(keys, start) + num_vertices(g) + 1); + pq.update(start); + + // start traversing the graph + // vertex_descriptor s, t; + // weight_type w; + while (!pq.empty()) + { // while PQ \neq {} do + const vertex_descriptor u = pq.top(); // u = extractmax(PQ) + /* weight_type w = */ get(keys, u); + vis.start_vertex(u, g); + pq.pop(); // vis.start_vertex(u, g); + + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) + { // foreach (u, v) \in E do + vis.examine_edge(e, g); + + const vertex_descriptor v = get(assignments, target(e, g)); + + if (pq.contains(v)) + { // if v \in PQ then + put(keys, v, + get(keys, v) + + get(weights, + e)); // increasekey(PQ, v, wA(v) + w(u, v)) + pq.update(v); + } + } + + typename std::set< vertex_descriptor >::const_iterator + assignedVertexIt, + assignedVertexEnd = assignedVertices.end(); + for (assignedVertexIt = assignedVertices.begin(); + assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) + { + const vertex_descriptor uPrime = *assignedVertexIt; + + if (get(assignments, uPrime) == u) + { + BGL_FORALL_OUTEDGES_T(uPrime, e, g, Graph) + { // foreach (u, v) \in E do + vis.examine_edge(e, g); + + const vertex_descriptor v + = get(assignments, target(e, g)); + + if (pq.contains(v)) + { // if v \in PQ then + put(keys, v, + get(keys, v) + + get(weights, e)); // increasekey(PQ, v, + // wA(v) + w(u, v)) + pq.update(v); + } + } + } + } + vis.finish_vertex(u, g); + } + } +} // end namespace detail + +template < class Graph, class WeightMap, class MASVisitor, + class VertexAssignmentMap, class KeyedUpdatablePriorityQueue > +void maximum_adjacency_search(const Graph& g, WeightMap weights, MASVisitor vis, + const typename boost::graph_traits< Graph >::vertex_descriptor start, + VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue pq) +{ + BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept< Graph >)); + typedef typename boost::graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + typedef typename boost::graph_traits< Graph >::vertices_size_type + vertices_size_type; + typedef + typename boost::graph_traits< Graph >::edge_descriptor edge_descriptor; + BOOST_CONCEPT_ASSERT((boost::Convertible< + typename boost::graph_traits< Graph >::directed_category, + boost::undirected_tag >)); + BOOST_CONCEPT_ASSERT( + (boost::ReadablePropertyMapConcept< WeightMap, edge_descriptor >)); + // typedef typename boost::property_traits<WeightMap>::value_type + // weight_type; + boost::function_requires< MASVisitorConcept< MASVisitor, Graph > >(); + BOOST_CONCEPT_ASSERT( + (boost::ReadWritePropertyMapConcept< VertexAssignmentMap, + vertex_descriptor >)); + BOOST_CONCEPT_ASSERT((boost::Convertible< vertex_descriptor, + typename boost::property_traits< VertexAssignmentMap >::value_type >)); + BOOST_CONCEPT_ASSERT( + (boost::KeyedUpdatableQueueConcept< KeyedUpdatablePriorityQueue >)); + + vertices_size_type n = num_vertices(g); + if (n < 2) + throw boost::bad_graph( + "the input graph must have at least two vertices."); + else if (!pq.empty()) + throw std::invalid_argument( + "the max-priority queue must be empty initially."); + + detail::maximum_adjacency_search(g, weights, vis, start, assignments, pq); +} + +namespace graph +{ + namespace detail + { + template < typename WeightMap > struct mas_dispatch + { + typedef void result_type; + template < typename Graph, typename ArgPack > + static result_type apply(const Graph& g, + // const bgl_named_params<P,T,R>& params, + const ArgPack& params, WeightMap w) + { + + using namespace boost::graph::keywords; + typedef typename boost::graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + typedef typename WeightMap::value_type weight_type; + + typedef boost::detail::make_priority_queue_from_arg_pack_gen< + boost::graph::keywords::tag::max_priority_queue, + weight_type, vertex_descriptor, + std::greater< weight_type > > + default_pq_gen_type; + + default_pq_gen_type pq_gen( + choose_param(get_param(params, boost::distance_zero_t()), + weight_type(0))); + + typename boost::result_of< default_pq_gen_type( + const Graph&, const ArgPack&) >::type pq + = pq_gen(g, params); + + boost::null_visitor null_vis; + boost::mas_visitor< boost::null_visitor > default_visitor( + null_vis); + vertex_descriptor v = vertex_descriptor(); + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::vertex_assignment_map, + vertex_descriptor > + map_gen(v); + typename boost::detail::map_maker< Graph, ArgPack, + boost::graph::keywords::tag::vertex_assignment_map, + vertex_descriptor >::map_type default_map + = map_gen(g, params); + boost::maximum_adjacency_search(g, w, + params[_visitor | default_visitor], + params[_root_vertex | *vertices(g).first], + params[_vertex_assignment_map | default_map], pq); + } + }; + + template <> struct mas_dispatch< boost::param_not_found > + { + typedef void result_type; + + template < typename Graph, typename ArgPack > + static result_type apply( + const Graph& g, const ArgPack& params, param_not_found) + { + + using namespace boost::graph::keywords; + typedef typename boost::graph_traits< Graph >::vertex_descriptor + vertex_descriptor; + + // get edge_weight_t as the weight type + typedef typename boost::property_map< Graph, edge_weight_t > + WeightMap; + typedef typename WeightMap::value_type weight_type; + + typedef boost::detail::make_priority_queue_from_arg_pack_gen< + boost::graph::keywords::tag::max_priority_queue, + weight_type, vertex_descriptor, + std::greater< weight_type > > + default_pq_gen_type; + + default_pq_gen_type pq_gen( + choose_param(get_param(params, boost::distance_zero_t()), + weight_type(0))); + + typename boost::result_of< default_pq_gen_type( + const Graph&, const ArgPack&) >::type pq + = pq_gen(g, params); + + boost::null_visitor null_vis; + boost::mas_visitor< boost::null_visitor > default_visitor( + null_vis); + vertex_descriptor v = vertex_descriptor(); + boost::detail::make_property_map_from_arg_pack_gen< + boost::graph::keywords::tag::vertex_assignment_map, + vertex_descriptor > + map_gen(v); + typename boost::detail::map_maker< Graph, ArgPack, + boost::graph::keywords::tag::vertex_assignment_map, + vertex_descriptor >::map_type default_map + = map_gen(g, params); + boost::maximum_adjacency_search(g, get(edge_weight, g), + params[_visitor | default_visitor], + params[_root_vertex | *vertices(g).first], + params[_vertex_assignment_map | default_map], pq); + } + }; + } // end namespace detail +} // end namespace graph + +// Named parameter interface +// BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(maximum_adjacency_search, 1) +template < typename Graph, typename P, typename T, typename R > +void maximum_adjacency_search( + const Graph& g, const bgl_named_params< P, T, R >& params) +{ + + typedef bgl_named_params< P, T, R > params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + + // do the dispatch based on WeightMap + typedef typename get_param_type< edge_weight_t, + bgl_named_params< P, T, R > >::type W; + graph::detail::mas_dispatch< W >::apply( + g, arg_pack, get_param(params, edge_weight)); +} + +namespace graph +{ + namespace detail + { + template < typename Graph > struct maximum_adjacency_search_impl + { + typedef void result_type; + + template < typename ArgPack > + void operator()(const Graph& g, const ArgPack& arg_pack) const + { + // call the function that does the dispatching + typedef + typename get_param_type< edge_weight_t, ArgPack >::type W; + graph::detail::mas_dispatch< W >::apply( + g, arg_pack, get_param(arg_pack, edge_weight)); + } + }; + } // end namespace detail + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(maximum_adjacency_search, 1, 5) +} // end namespace graph + +} // end namespace boost + +#include <boost/graph/iteration_macros_undef.hpp> + +#endif // BOOST_GRAPH_MAXIMUM_ADJACENCY_SEARCH_H diff --git a/contrib/restricted/boost/graph/include/boost/graph/maximum_weighted_matching.hpp b/contrib/restricted/boost/graph/include/boost/graph/maximum_weighted_matching.hpp new file mode 100644 index 0000000000..098a9c2aa7 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/maximum_weighted_matching.hpp @@ -0,0 +1,1313 @@ +//======================================================================= +// Copyright (c) 2018 Yi Ji +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +//======================================================================= + +#ifndef BOOST_GRAPH_MAXIMUM_WEIGHTED_MATCHING_HPP +#define BOOST_GRAPH_MAXIMUM_WEIGHTED_MATCHING_HPP + +#include <algorithm> // for std::iter_swap +#include <boost/shared_ptr.hpp> +#include <boost/make_shared.hpp> +#include <boost/graph/max_cardinality_matching.hpp> + +namespace boost +{ +template < typename Graph, typename MateMap, typename VertexIndexMap > +typename property_traits< + typename property_map< Graph, edge_weight_t >::type >::value_type +matching_weight_sum(const Graph& g, MateMap mate, VertexIndexMap vm) +{ + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename property_traits< typename property_map< Graph, + edge_weight_t >::type >::value_type edge_property_t; + + edge_property_t weight_sum = 0; + vertex_iterator_t vi, vi_end; + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v = *vi; + if (get(mate, v) != graph_traits< Graph >::null_vertex() + && get(vm, v) < get(vm, get(mate, v))) + weight_sum += get(edge_weight, g, edge(v, mate[v], g).first); + } + return weight_sum; +} + +template < typename Graph, typename MateMap > +inline typename property_traits< + typename property_map< Graph, edge_weight_t >::type >::value_type +matching_weight_sum(const Graph& g, MateMap mate) +{ + return matching_weight_sum(g, mate, get(vertex_index, g)); +} + +template < typename Graph, typename MateMap, typename VertexIndexMap > +class weighted_augmenting_path_finder +{ +public: + template < typename T > struct map_vertex_to_ + { + typedef boost::iterator_property_map< + typename std::vector< T >::iterator, VertexIndexMap > + type; + }; + typedef typename graph::detail::VERTEX_STATE vertex_state_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename std::vector< vertex_descriptor_t >::const_iterator + vertex_vec_iter_t; + typedef + typename graph_traits< Graph >::out_edge_iterator out_edge_iterator_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + typedef typename property_traits< typename property_map< Graph, + edge_weight_t >::type >::value_type edge_property_t; + typedef std::deque< vertex_descriptor_t > vertex_list_t; + typedef std::vector< edge_descriptor_t > edge_list_t; + typedef typename map_vertex_to_< vertex_descriptor_t >::type + vertex_to_vertex_map_t; + typedef + typename map_vertex_to_< edge_property_t >::type vertex_to_weight_map_t; + typedef typename map_vertex_to_< bool >::type vertex_to_bool_map_t; + typedef typename map_vertex_to_< std::pair< vertex_descriptor_t, + vertex_descriptor_t > >::type vertex_to_pair_map_t; + typedef + typename map_vertex_to_< std::pair< edge_descriptor_t, bool > >::type + vertex_to_edge_map_t; + typedef typename map_vertex_to_< vertex_to_edge_map_t >::type + vertex_pair_to_edge_map_t; + + class blossom + { + public: + typedef boost::shared_ptr< blossom > blossom_ptr_t; + std::vector< blossom_ptr_t > sub_blossoms; + edge_property_t dual_var; + blossom_ptr_t father; + + blossom() : dual_var(0), father(blossom_ptr_t()) {} + + // get the base vertex of a blossom by recursively getting + // its base sub-blossom, which is always the first one in + // sub_blossoms because of how we create and maintain blossoms + virtual vertex_descriptor_t get_base() const + { + const blossom* b = this; + while (!b->sub_blossoms.empty()) + b = b->sub_blossoms[0].get(); + return b->get_base(); + } + + // set a sub-blossom as a blossom's base by exchanging it + // with its first sub-blossom + void set_base(const blossom_ptr_t& sub) + { + for (blossom_iterator_t bi = sub_blossoms.begin(); + bi != sub_blossoms.end(); ++bi) + { + if (sub.get() == bi->get()) + { + std::iter_swap(sub_blossoms.begin(), bi); + break; + } + } + } + + // get all vertices inside recursively + virtual std::vector< vertex_descriptor_t > vertices() const + { + std::vector< vertex_descriptor_t > all_vertices; + for (typename std::vector< blossom_ptr_t >::const_iterator bi + = sub_blossoms.begin(); + bi != sub_blossoms.end(); ++bi) + { + std::vector< vertex_descriptor_t > some_vertices + = (*bi)->vertices(); + all_vertices.insert(all_vertices.end(), some_vertices.begin(), + some_vertices.end()); + } + return all_vertices; + } + }; + + // a trivial_blossom only has one vertex and no sub-blossom; + // for each vertex v, in_blossom[v] is the trivial_blossom that contains it + // directly + class trivial_blossom : public blossom + { + public: + trivial_blossom(vertex_descriptor_t v) : trivial_vertex(v) {} + virtual vertex_descriptor_t get_base() const { return trivial_vertex; } + + virtual std::vector< vertex_descriptor_t > vertices() const + { + std::vector< vertex_descriptor_t > all_vertices; + all_vertices.push_back(trivial_vertex); + return all_vertices; + } + + private: + vertex_descriptor_t trivial_vertex; + }; + + typedef boost::shared_ptr< blossom > blossom_ptr_t; + typedef typename std::vector< blossom_ptr_t >::iterator blossom_iterator_t; + typedef + typename map_vertex_to_< blossom_ptr_t >::type vertex_to_blossom_map_t; + + weighted_augmenting_path_finder( + const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm) + : g(arg_g) + , vm(arg_vm) + , null_edge(std::pair< edge_descriptor_t, bool >( + num_edges(g) == 0 ? edge_descriptor_t() : *edges(g).first, false)) + , mate_vector(num_vertices(g)) + , label_S_vector(num_vertices(g), graph_traits< Graph >::null_vertex()) + , label_T_vector(num_vertices(g), graph_traits< Graph >::null_vertex()) + , outlet_vector(num_vertices(g), graph_traits< Graph >::null_vertex()) + , tau_idx_vector(num_vertices(g), graph_traits< Graph >::null_vertex()) + , dual_var_vector(std::vector< edge_property_t >( + num_vertices(g), std::numeric_limits< edge_property_t >::min())) + , pi_vector(std::vector< edge_property_t >( + num_vertices(g), std::numeric_limits< edge_property_t >::max())) + , gamma_vector(std::vector< edge_property_t >( + num_vertices(g), std::numeric_limits< edge_property_t >::max())) + , tau_vector(std::vector< edge_property_t >( + num_vertices(g), std::numeric_limits< edge_property_t >::max())) + , in_blossom_vector(num_vertices(g)) + , old_label_vector(num_vertices(g)) + , critical_edge_vectors(num_vertices(g), + std::vector< std::pair< edge_descriptor_t, bool > >( + num_vertices(g), null_edge)) + , + + mate(mate_vector.begin(), vm) + , label_S(label_S_vector.begin(), vm) + , label_T(label_T_vector.begin(), vm) + , outlet(outlet_vector.begin(), vm) + , tau_idx(tau_idx_vector.begin(), vm) + , dual_var(dual_var_vector.begin(), vm) + , pi(pi_vector.begin(), vm) + , gamma(gamma_vector.begin(), vm) + , tau(tau_vector.begin(), vm) + , in_blossom(in_blossom_vector.begin(), vm) + , old_label(old_label_vector.begin(), vm) + { + vertex_iterator_t vi, vi_end; + edge_iterator_t ei, ei_end; + + edge_property_t max_weight + = std::numeric_limits< edge_property_t >::min(); + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + max_weight = std::max(max_weight, get(edge_weight, g, *ei)); + + typename std::vector< + std::vector< std::pair< edge_descriptor_t, bool > > >::iterator vei; + + for (boost::tie(vi, vi_end) = vertices(g), + vei = critical_edge_vectors.begin(); + vi != vi_end; ++vi, ++vei) + { + vertex_descriptor_t u = *vi; + mate[u] = get(arg_mate, u); + dual_var[u] = 2 * max_weight; + in_blossom[u] = boost::make_shared< trivial_blossom >(u); + outlet[u] = u; + critical_edge_vector.push_back( + vertex_to_edge_map_t(vei->begin(), vm)); + } + + critical_edge + = vertex_pair_to_edge_map_t(critical_edge_vector.begin(), vm); + + init(); + } + + // return the top blossom where v is contained inside + blossom_ptr_t in_top_blossom(vertex_descriptor_t v) const + { + blossom_ptr_t b = in_blossom[v]; + while (b->father != blossom_ptr_t()) + b = b->father; + return b; + } + + // check if vertex v is in blossom b + bool is_in_blossom(blossom_ptr_t b, vertex_descriptor_t v) const + { + if (v == graph_traits< Graph >::null_vertex()) + return false; + blossom_ptr_t vb = in_blossom[v]->father; + while (vb != blossom_ptr_t()) + { + if (vb.get() == b.get()) + return true; + vb = vb->father; + } + return false; + } + + // return the base vertex of the top blossom that contains v + inline vertex_descriptor_t base_vertex(vertex_descriptor_t v) const + { + return in_top_blossom(v)->get_base(); + } + + // add an existed top blossom of base vertex v into new top + // blossom b as its sub-blossom + void add_sub_blossom(blossom_ptr_t b, vertex_descriptor_t v) + { + blossom_ptr_t sub = in_top_blossom(v); + sub->father = b; + b->sub_blossoms.push_back(sub); + if (sub->sub_blossoms.empty()) + return; + for (blossom_iterator_t bi = top_blossoms.begin(); + bi != top_blossoms.end(); ++bi) + { + if (bi->get() == sub.get()) + { + top_blossoms.erase(bi); + break; + } + } + } + + // when a top blossom is created or its base vertex getting an S-label, + // add all edges incident to this blossom into even_edges + void bloom(blossom_ptr_t b) + { + std::vector< vertex_descriptor_t > vertices_of_b = b->vertices(); + vertex_vec_iter_t vi; + for (vi = vertices_of_b.begin(); vi != vertices_of_b.end(); ++vi) + { + out_edge_iterator_t oei, oei_end; + for (boost::tie(oei, oei_end) = out_edges(*vi, g); oei != oei_end; + ++oei) + { + if (target(*oei, g) != *vi && mate[*vi] != target(*oei, g)) + even_edges.push_back(*oei); + } + } + } + + // assigning a T-label to a non S-vertex, along with outlet and updating pi + // value if updated pi[v] equals zero, augment the matching from its mate + // vertex + void put_T_label(vertex_descriptor_t v, vertex_descriptor_t T_label, + vertex_descriptor_t outlet_v, edge_property_t pi_v) + { + if (label_S[v] != graph_traits< Graph >::null_vertex()) + return; + + label_T[v] = T_label; + outlet[v] = outlet_v; + pi[v] = pi_v; + + vertex_descriptor_t v_mate = mate[v]; + if (pi[v] == 0) + { + label_T[v_mate] = graph_traits< Graph >::null_vertex(); + label_S[v_mate] = v; + bloom(in_top_blossom(v_mate)); + } + } + + // get the missing T-label for a to-be-expanded base vertex + // the missing T-label is the last vertex of the path from outlet[v] to v + std::pair< vertex_descriptor_t, vertex_descriptor_t > missing_label( + vertex_descriptor_t b_base) + { + vertex_descriptor_t missing_outlet = outlet[b_base]; + + if (outlet[b_base] == b_base) + return std::make_pair( + graph_traits< Graph >::null_vertex(), missing_outlet); + + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]); + + std::pair< vertex_descriptor_t, vertex_state_t > child( + outlet[b_base], graph::detail::V_EVEN); + blossom_ptr_t b = in_blossom[child.first]; + for (; b->father->father != blossom_ptr_t(); b = b->father) + ; + child.first = b->get_base(); + + if (child.first == b_base) + return std::make_pair( + graph_traits< Graph >::null_vertex(), missing_outlet); + + while (true) + { + std::pair< vertex_descriptor_t, vertex_state_t > child_parent + = parent(child, true); + + for (b = in_blossom[child_parent.first]; + b->father->father != blossom_ptr_t(); b = b->father) + ; + missing_outlet = child_parent.first; + child_parent.first = b->get_base(); + + if (child_parent.first == b_base) + break; + else + child = child_parent; + } + return std::make_pair(child.first, missing_outlet); + } + + // expand a top blossom, put all its non-trivial sub-blossoms into + // top_blossoms + blossom_iterator_t expand_blossom( + blossom_iterator_t bi, std::vector< blossom_ptr_t >& new_ones) + { + blossom_ptr_t b = *bi; + for (blossom_iterator_t i = b->sub_blossoms.begin(); + i != b->sub_blossoms.end(); ++i) + { + blossom_ptr_t sub_blossom = *i; + vertex_descriptor_t sub_base = sub_blossom->get_base(); + label_S[sub_base] = label_T[sub_base] + = graph_traits< Graph >::null_vertex(); + outlet[sub_base] = sub_base; + sub_blossom->father = blossom_ptr_t(); + // new top blossoms cannot be pushed back into top_blossoms + // immediately, because push_back() may cause reallocation and then + // invalid iterators + if (!sub_blossom->sub_blossoms.empty()) + new_ones.push_back(sub_blossom); + } + return top_blossoms.erase(bi); + } + + // when expanding a T-blossom with base v, it requires more operations: + // supply the missing T-labels for new base vertices by picking the minimum + // tau from vertices of each corresponding new top-blossoms; when label_T[v] + // is null or we have a smaller tau from missing_label(v), replace T-label + // and outlet of v (but don't bloom v) + blossom_iterator_t expand_T_blossom( + blossom_iterator_t bi, std::vector< blossom_ptr_t >& new_ones) + { + blossom_ptr_t b = *bi; + + vertex_descriptor_t b_base = b->get_base(); + std::pair< vertex_descriptor_t, vertex_descriptor_t > T_and_outlet + = missing_label(b_base); + + blossom_iterator_t next_bi = expand_blossom(bi, new_ones); + + for (blossom_iterator_t i = b->sub_blossoms.begin(); + i != b->sub_blossoms.end(); ++i) + { + blossom_ptr_t sub_blossom = *i; + vertex_descriptor_t sub_base = sub_blossom->get_base(); + vertex_descriptor_t min_tau_v + = graph_traits< Graph >::null_vertex(); + edge_property_t min_tau + = std::numeric_limits< edge_property_t >::max(); + + std::vector< vertex_descriptor_t > sub_vertices + = sub_blossom->vertices(); + for (vertex_vec_iter_t v = sub_vertices.begin(); + v != sub_vertices.end(); ++v) + { + if (tau[*v] < min_tau) + { + min_tau = tau[*v]; + min_tau_v = *v; + } + } + + if (min_tau < std::numeric_limits< edge_property_t >::max()) + put_T_label( + sub_base, tau_idx[min_tau_v], min_tau_v, tau[min_tau_v]); + } + + if (label_T[b_base] == graph_traits< Graph >::null_vertex() + || tau[old_label[b_base].second] < pi[b_base]) + boost::tie(label_T[b_base], outlet[b_base]) = T_and_outlet; + + return next_bi; + } + + // when vertices v and w are matched to each other by augmenting, + // we must set v/w as base vertex of any blossom who contains v/w and + // is a sub-blossom of their lowest (smallest) common blossom + void adjust_blossom(vertex_descriptor_t v, vertex_descriptor_t w) + { + blossom_ptr_t vb = in_blossom[v], wb = in_blossom[w], + lowest_common_blossom; + std::vector< blossom_ptr_t > v_ancestors, w_ancestors; + + while (vb->father != blossom_ptr_t()) + { + v_ancestors.push_back(vb->father); + vb = vb->father; + } + while (wb->father != blossom_ptr_t()) + { + w_ancestors.push_back(wb->father); + wb = wb->father; + } + + typename std::vector< blossom_ptr_t >::reverse_iterator i, j; + i = v_ancestors.rbegin(); + j = w_ancestors.rbegin(); + while (i != v_ancestors.rend() && j != w_ancestors.rend() + && i->get() == j->get()) + { + lowest_common_blossom = *i; + ++i; + ++j; + } + + vb = in_blossom[v]; + wb = in_blossom[w]; + while (vb->father != lowest_common_blossom) + { + vb->father->set_base(vb); + vb = vb->father; + } + while (wb->father != lowest_common_blossom) + { + wb->father->set_base(wb); + wb = wb->father; + } + } + + // every edge weight is multiplied by 4 to ensure integer weights + // throughout the algorithm if all input weights are integers + inline edge_property_t slack(const edge_descriptor_t& e) const + { + vertex_descriptor_t v, w; + v = source(e, g); + w = target(e, g); + return dual_var[v] + dual_var[w] - 4 * get(edge_weight, g, e); + } + + // backtrace one step on vertex v along the augmenting path + // by its labels and its vertex state; + // boolean parameter "use_old" means whether we are updating labels, + // if we are, then we use old labels to backtrace and also we + // don't jump to its base vertex when we reach an odd vertex + std::pair< vertex_descriptor_t, vertex_state_t > parent( + std::pair< vertex_descriptor_t, vertex_state_t > v, + bool use_old = false) const + { + if (v.second == graph::detail::V_EVEN) + { + // a paranoid check: label_S shoule be the same as mate in + // backtracing + if (label_S[v.first] == graph_traits< Graph >::null_vertex()) + label_S[v.first] = mate[v.first]; + return std::make_pair(label_S[v.first], graph::detail::V_ODD); + } + else if (v.second == graph::detail::V_ODD) + { + vertex_descriptor_t w = use_old ? old_label[v.first].first + : base_vertex(label_T[v.first]); + return std::make_pair(w, graph::detail::V_EVEN); + } + return std::make_pair(v.first, graph::detail::V_UNREACHED); + } + + // backtrace from vertices v and w to their free (unmatched) ancesters, + // return the nearest common ancestor (null_vertex if none) of v and w + vertex_descriptor_t nearest_common_ancestor(vertex_descriptor_t v, + vertex_descriptor_t w, vertex_descriptor_t& v_free_ancestor, + vertex_descriptor_t& w_free_ancestor) const + { + std::pair< vertex_descriptor_t, vertex_state_t > v_up( + v, graph::detail::V_EVEN); + std::pair< vertex_descriptor_t, vertex_state_t > w_up( + w, graph::detail::V_EVEN); + vertex_descriptor_t nca; + nca = w_free_ancestor = v_free_ancestor + = graph_traits< Graph >::null_vertex(); + + std::vector< bool > ancestor_of_w_vector(num_vertices(g), false); + std::vector< bool > ancestor_of_v_vector(num_vertices(g), false); + vertex_to_bool_map_t ancestor_of_w(ancestor_of_w_vector.begin(), vm); + vertex_to_bool_map_t ancestor_of_v(ancestor_of_v_vector.begin(), vm); + + while (nca == graph_traits< Graph >::null_vertex() + && (v_free_ancestor == graph_traits< Graph >::null_vertex() + || w_free_ancestor == graph_traits< Graph >::null_vertex())) + { + ancestor_of_w[w_up.first] = true; + ancestor_of_v[v_up.first] = true; + + if (w_free_ancestor == graph_traits< Graph >::null_vertex()) + w_up = parent(w_up); + if (v_free_ancestor == graph_traits< Graph >::null_vertex()) + v_up = parent(v_up); + + if (mate[v_up.first] == graph_traits< Graph >::null_vertex()) + v_free_ancestor = v_up.first; + if (mate[w_up.first] == graph_traits< Graph >::null_vertex()) + w_free_ancestor = w_up.first; + + if (ancestor_of_w[v_up.first] == true || v_up.first == w_up.first) + nca = v_up.first; + else if (ancestor_of_v[w_up.first] == true) + nca = w_up.first; + else if (v_free_ancestor == w_free_ancestor + && v_free_ancestor != graph_traits< Graph >::null_vertex()) + nca = v_up.first; + } + + return nca; + } + + // when a new top blossom b is created by connecting (v, w), we add + // sub-blossoms into b along backtracing from v_prime and w_prime to + // stop_vertex (the base vertex); also, we set labels and outlet for each + // base vertex we pass by + void make_blossom(blossom_ptr_t b, vertex_descriptor_t w_prime, + vertex_descriptor_t v_prime, vertex_descriptor_t stop_vertex) + { + std::pair< vertex_descriptor_t, vertex_state_t > u( + v_prime, graph::detail::V_ODD); + std::pair< vertex_descriptor_t, vertex_state_t > u_up( + w_prime, graph::detail::V_EVEN); + + for (; u_up.first != stop_vertex; u = u_up, u_up = parent(u)) + { + if (u_up.second == graph::detail::V_EVEN) + { + if (!in_top_blossom(u_up.first)->sub_blossoms.empty()) + outlet[u_up.first] = label_T[u.first]; + label_T[u_up.first] = outlet[u.first]; + } + else if (u_up.second == graph::detail::V_ODD) + label_S[u_up.first] = u.first; + + add_sub_blossom(b, u_up.first); + } + } + + // the design of recursively expanding augmenting path in + // (reversed_)retrieve_augmenting_path functions is inspired by same + // functions in max_cardinality_matching.hpp; except that in weighted + // matching, we use "outlet" vertices instead of "bridge" vertex pairs: if + // blossom b is the smallest non-trivial blossom that contains its base + // vertex v, then v and outlet[v] are where augmenting path enters and + // leaves b + void retrieve_augmenting_path( + vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state) + { + if (v == w) + aug_path.push_back(v); + else if (v_state == graph::detail::V_EVEN) + { + aug_path.push_back(v); + retrieve_augmenting_path(label_S[v], w, graph::detail::V_ODD); + } + else if (v_state == graph::detail::V_ODD) + { + if (outlet[v] == v) + aug_path.push_back(v); + else + reversed_retrieve_augmenting_path( + outlet[v], v, graph::detail::V_EVEN); + retrieve_augmenting_path(label_T[v], w, graph::detail::V_EVEN); + } + } + + void reversed_retrieve_augmenting_path( + vertex_descriptor_t v, vertex_descriptor_t w, vertex_state_t v_state) + { + if (v == w) + aug_path.push_back(v); + else if (v_state == graph::detail::V_EVEN) + { + reversed_retrieve_augmenting_path( + label_S[v], w, graph::detail::V_ODD); + aug_path.push_back(v); + } + else if (v_state == graph::detail::V_ODD) + { + reversed_retrieve_augmenting_path( + label_T[v], w, graph::detail::V_EVEN); + if (outlet[v] != v) + retrieve_augmenting_path(outlet[v], v, graph::detail::V_EVEN); + else + aug_path.push_back(v); + } + } + + // correct labels for vertices in the augmenting path + void relabel(vertex_descriptor_t v) + { + blossom_ptr_t b = in_blossom[v]->father; + + if (!is_in_blossom(b, mate[v])) + { // if v is a new base vertex + std::pair< vertex_descriptor_t, vertex_state_t > u( + v, graph::detail::V_EVEN); + while (label_S[u.first] != u.first + && is_in_blossom(b, label_S[u.first])) + u = parent(u, true); + + vertex_descriptor_t old_base = u.first; + if (label_S[old_base] != old_base) + { // if old base is not exposed + label_T[v] = label_S[old_base]; + outlet[v] = old_base; + } + else + { // if old base is exposed then new label_T[v] is not in b, + // we must (i) make b2 the smallest blossom containing v but not + // as base vertex (ii) backtrace from b2's new base vertex to b + label_T[v] = graph_traits< Graph >::null_vertex(); + for (b = b->father; b != blossom_ptr_t() && b->get_base() == v; + b = b->father) + ; + if (b != blossom_ptr_t()) + { + u = std::make_pair(b->get_base(), graph::detail::V_ODD); + while (!is_in_blossom( + in_blossom[v]->father, old_label[u.first].first)) + u = parent(u, true); + label_T[v] = u.first; + outlet[v] = old_label[u.first].first; + } + } + } + else if (label_S[v] == v || !is_in_blossom(b, label_S[v])) + { // if v is an old base vertex + // let u be the new base vertex; backtrace from u's old T-label + std::pair< vertex_descriptor_t, vertex_state_t > u( + b->get_base(), graph::detail::V_ODD); + while ( + old_label[u.first].first != graph_traits< Graph >::null_vertex() + && old_label[u.first].first != v) + u = parent(u, true); + label_T[v] = old_label[u.first].second; + outlet[v] = v; + } + else // if v is neither a new nor an old base vertex + label_T[v] = label_S[v]; + } + + void augmenting(vertex_descriptor_t v, vertex_descriptor_t v_free_ancestor, + vertex_descriptor_t w, vertex_descriptor_t w_free_ancestor) + { + vertex_iterator_t vi, vi_end; + + // retrieve the augmenting path and put it in aug_path + reversed_retrieve_augmenting_path( + v, v_free_ancestor, graph::detail::V_EVEN); + retrieve_augmenting_path(w, w_free_ancestor, graph::detail::V_EVEN); + + // augment the matching along aug_path + vertex_descriptor_t a, b; + vertex_list_t reversed_aug_path; + while (!aug_path.empty()) + { + a = aug_path.front(); + aug_path.pop_front(); + reversed_aug_path.push_back(a); + b = aug_path.front(); + aug_path.pop_front(); + reversed_aug_path.push_back(b); + + mate[a] = b; + mate[b] = a; + + // reset base vertex for every blossom in augment path + adjust_blossom(a, b); + } + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + old_label[*vi] = std::make_pair(label_T[*vi], outlet[*vi]); + + // correct labels for in-blossom vertices along aug_path + while (!reversed_aug_path.empty()) + { + a = reversed_aug_path.front(); + reversed_aug_path.pop_front(); + + if (in_blossom[a]->father != blossom_ptr_t()) + relabel(a); + } + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t u = *vi; + if (mate[u] != graph_traits< Graph >::null_vertex()) + label_S[u] = mate[u]; + } + + // expand blossoms with zero dual variables + std::vector< blossom_ptr_t > new_top_blossoms; + for (blossom_iterator_t bi = top_blossoms.begin(); + bi != top_blossoms.end();) + { + if ((*bi)->dual_var <= 0) + bi = expand_blossom(bi, new_top_blossoms); + else + ++bi; + } + top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(), + new_top_blossoms.end()); + init(); + } + + // create a new blossom and set labels for vertices inside + void blossoming(vertex_descriptor_t v, vertex_descriptor_t v_prime, + vertex_descriptor_t w, vertex_descriptor_t w_prime, + vertex_descriptor_t nca) + { + vertex_iterator_t vi, vi_end; + + std::vector< bool > is_old_base_vector(num_vertices(g)); + vertex_to_bool_map_t is_old_base(is_old_base_vector.begin(), vm); + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + if (*vi == base_vertex(*vi)) + is_old_base[*vi] = true; + } + + blossom_ptr_t b = boost::make_shared< blossom >(); + add_sub_blossom(b, nca); + + label_T[w_prime] = v; + label_T[v_prime] = w; + outlet[w_prime] = w; + outlet[v_prime] = v; + + make_blossom(b, w_prime, v_prime, nca); + make_blossom(b, v_prime, w_prime, nca); + + label_T[nca] = graph_traits< Graph >::null_vertex(); + outlet[nca] = nca; + + top_blossoms.push_back(b); + bloom(b); + + // set gamma[b_base] = min_slack{critical_edge(b_base, other_base)} + // where each critical edge is updated before, by + // argmin{slack(old_bases_in_b, other_base)}; + vertex_vec_iter_t i, j; + std::vector< vertex_descriptor_t > b_vertices = b->vertices(), + old_base_in_b, other_base; + vertex_descriptor_t b_base = b->get_base(); + for (i = b_vertices.begin(); i != b_vertices.end(); ++i) + { + if (is_old_base[*i]) + old_base_in_b.push_back(*i); + } + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + if (*vi != b_base && *vi == base_vertex(*vi)) + other_base.push_back(*vi); + } + for (i = other_base.begin(); i != other_base.end(); ++i) + { + edge_property_t min_slack + = std::numeric_limits< edge_property_t >::max(); + std::pair< edge_descriptor_t, bool > b_vi = null_edge; + for (j = old_base_in_b.begin(); j != old_base_in_b.end(); ++j) + { + if (critical_edge[*j][*i] != null_edge + && min_slack > slack(critical_edge[*j][*i].first)) + { + min_slack = slack(critical_edge[*j][*i].first); + b_vi = critical_edge[*j][*i]; + } + } + critical_edge[b_base][*i] = critical_edge[*i][b_base] = b_vi; + } + gamma[b_base] = std::numeric_limits< edge_property_t >::max(); + for (i = other_base.begin(); i != other_base.end(); ++i) + { + if (critical_edge[b_base][*i] != null_edge) + gamma[b_base] = std::min( + gamma[b_base], slack(critical_edge[b_base][*i].first)); + } + } + + void init() + { + even_edges.clear(); + + vertex_iterator_t vi, vi_end; + typename std::vector< + std::vector< std::pair< edge_descriptor_t, bool > > >::iterator vei; + + for (boost::tie(vi, vi_end) = vertices(g), + vei = critical_edge_vectors.begin(); + vi != vi_end; ++vi, ++vei) + { + vertex_descriptor_t u = *vi; + out_edge_iterator_t ei, ei_end; + + gamma[u] = tau[u] = pi[u] + = std::numeric_limits< edge_property_t >::max(); + std::fill(vei->begin(), vei->end(), null_edge); + + if (base_vertex(u) != u) + continue; + + label_S[u] = label_T[u] = graph_traits< Graph >::null_vertex(); + outlet[u] = u; + + if (mate[u] == graph_traits< Graph >::null_vertex()) + { + label_S[u] = u; + bloom(in_top_blossom(u)); + } + } + } + + bool augment_matching() + { + vertex_descriptor_t v, w, w_free_ancestor, v_free_ancestor; + v = w = w_free_ancestor = v_free_ancestor + = graph_traits< Graph >::null_vertex(); + bool found_alternating_path = false; + + // note that we only use edges of zero slack value for augmenting + while (!even_edges.empty() && !found_alternating_path) + { + // search for augmenting paths depth-first + edge_descriptor_t current_edge = even_edges.back(); + even_edges.pop_back(); + + v = source(current_edge, g); + w = target(current_edge, g); + + vertex_descriptor_t v_prime = base_vertex(v); + vertex_descriptor_t w_prime = base_vertex(w); + + // w_prime == v_prime implies that we get an edge that has been + // shrunk into a blossom + if (v_prime == w_prime) + continue; + + // a paranoid check + if (label_S[v_prime] == graph_traits< Graph >::null_vertex()) + { + std::swap(v_prime, w_prime); + std::swap(v, w); + } + + // w_prime may be unlabeled or have a T-label; replace the existed + // T-label if the edge slack is smaller than current pi[w_prime] and + // update it. Note that a T-label is "deserved" only when pi equals + // zero. also update tau and tau_idx so that tau_idx becomes T-label + // when a T-blossom is expanded + if (label_S[w_prime] == graph_traits< Graph >::null_vertex()) + { + if (slack(current_edge) < pi[w_prime]) + put_T_label(w_prime, v, w, slack(current_edge)); + if (slack(current_edge) < tau[w]) + { + if (in_blossom[w]->father == blossom_ptr_t() + || label_T[w_prime] == v + || label_T[w_prime] + == graph_traits< Graph >::null_vertex() + || nearest_common_ancestor(v_prime, label_T[w_prime], + v_free_ancestor, w_free_ancestor) + == graph_traits< Graph >::null_vertex()) + { + tau[w] = slack(current_edge); + tau_idx[w] = v; + } + } + } + + else + { + if (slack(current_edge) > 0) + { + // update gamma and critical_edges when we have a smaller + // edge slack + gamma[v_prime] + = std::min(gamma[v_prime], slack(current_edge)); + gamma[w_prime] + = std::min(gamma[w_prime], slack(current_edge)); + if (critical_edge[v_prime][w_prime] == null_edge + || slack(critical_edge[v_prime][w_prime].first) + > slack(current_edge)) + { + critical_edge[v_prime][w_prime] + = std::pair< edge_descriptor_t, bool >( + current_edge, true); + critical_edge[w_prime][v_prime] + = std::pair< edge_descriptor_t, bool >( + current_edge, true); + } + continue; + } + else if (slack(current_edge) == 0) + { + // if nca is null_vertex then we have an augmenting path; + // otherwise we have a new top blossom with nca as its base + // vertex + vertex_descriptor_t nca = nearest_common_ancestor( + v_prime, w_prime, v_free_ancestor, w_free_ancestor); + + if (nca == graph_traits< Graph >::null_vertex()) + found_alternating_path + = true; // to break out of the loop + else + blossoming(v, v_prime, w, w_prime, nca); + } + } + } + + if (!found_alternating_path) + return false; + + augmenting(v, v_free_ancestor, w, w_free_ancestor); + return true; + } + + // slack the vertex and blossom dual variables when there is no augmenting + // path found according to the primal-dual method + bool adjust_dual() + { + edge_property_t delta1, delta2, delta3, delta4, delta; + delta1 = delta2 = delta3 = delta4 + = std::numeric_limits< edge_property_t >::max(); + + vertex_iterator_t vi, vi_end; + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + delta1 = std::min(delta1, dual_var[*vi]); + delta4 = pi[*vi] > 0 ? std::min(delta4, pi[*vi]) : delta4; + if (*vi == base_vertex(*vi)) + delta3 = std::min(delta3, gamma[*vi] / 2); + } + + for (blossom_iterator_t bi = top_blossoms.begin(); + bi != top_blossoms.end(); ++bi) + { + vertex_descriptor_t b_base = (*bi)->get_base(); + if (label_T[b_base] != graph_traits< Graph >::null_vertex() + && pi[b_base] == 0) + delta2 = std::min(delta2, (*bi)->dual_var / 2); + } + + delta = std::min(std::min(delta1, delta2), std::min(delta3, delta4)); + + // start updating dual variables, note that the order is important + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v = *vi, v_prime = base_vertex(v); + + if (label_S[v_prime] != graph_traits< Graph >::null_vertex()) + dual_var[v] -= delta; + else if (label_T[v_prime] != graph_traits< Graph >::null_vertex() + && pi[v_prime] == 0) + dual_var[v] += delta; + + if (v == v_prime) + gamma[v] -= 2 * delta; + } + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v_prime = base_vertex(*vi); + if (pi[v_prime] > 0) + tau[*vi] -= delta; + } + + for (blossom_iterator_t bi = top_blossoms.begin(); + bi != top_blossoms.end(); ++bi) + { + vertex_descriptor_t b_base = (*bi)->get_base(); + if (label_T[b_base] != graph_traits< Graph >::null_vertex() + && pi[b_base] == 0) + (*bi)->dual_var -= 2 * delta; + if (label_S[b_base] != graph_traits< Graph >::null_vertex()) + (*bi)->dual_var += 2 * delta; + } + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_descriptor_t v = *vi; + if (pi[v] > 0) + pi[v] -= delta; + + // when some T-vertices have zero pi value, bloom their mates so + // that matching can be further augmented + if (label_T[v] != graph_traits< Graph >::null_vertex() + && pi[v] == 0) + put_T_label(v, label_T[v], outlet[v], pi[v]); + } + + // optimal solution reached, halt + if (delta == delta1) + return false; + + // expand odd blossoms with zero dual variables and zero pi value of + // their base vertices + if (delta == delta2 && delta != delta3) + { + std::vector< blossom_ptr_t > new_top_blossoms; + for (blossom_iterator_t bi = top_blossoms.begin(); + bi != top_blossoms.end();) + { + const blossom_ptr_t b = *bi; + vertex_descriptor_t b_base = b->get_base(); + if (b->dual_var == 0 + && label_T[b_base] != graph_traits< Graph >::null_vertex() + && pi[b_base] == 0) + bi = expand_T_blossom(bi, new_top_blossoms); + else + ++bi; + } + top_blossoms.insert(top_blossoms.end(), new_top_blossoms.begin(), + new_top_blossoms.end()); + } + + while (true) + { + // find a zero-slack critical edge (v, w) of zero gamma values + std::pair< edge_descriptor_t, bool > best_edge = null_edge; + std::vector< vertex_descriptor_t > base_nodes; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + if (*vi == base_vertex(*vi)) + base_nodes.push_back(*vi); + } + for (vertex_vec_iter_t i = base_nodes.begin(); + i != base_nodes.end(); ++i) + { + if (gamma[*i] == 0) + { + for (vertex_vec_iter_t j = base_nodes.begin(); + j != base_nodes.end(); ++j) + { + if (critical_edge[*i][*j] != null_edge + && slack(critical_edge[*i][*j].first) == 0) + best_edge = critical_edge[*i][*j]; + } + } + } + + // if not found, continue finding other augment matching + if (best_edge == null_edge) + { + bool augmented = augment_matching(); + return augmented || delta != delta1; + } + // if found, determine either augmenting or blossoming + vertex_descriptor_t v = source(best_edge.first, g), + w = target(best_edge.first, g); + vertex_descriptor_t v_prime = base_vertex(v), + w_prime = base_vertex(w), v_free_ancestor, + w_free_ancestor; + vertex_descriptor_t nca = nearest_common_ancestor( + v_prime, w_prime, v_free_ancestor, w_free_ancestor); + if (nca == graph_traits< Graph >::null_vertex()) + { + augmenting(v, v_free_ancestor, w, w_free_ancestor); + return true; + } + else + blossoming(v, v_prime, w, w_prime, nca); + } + + return false; + } + + template < typename PropertyMap > void get_current_matching(PropertyMap pm) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(pm, *vi, mate[*vi]); + } + +private: + const Graph& g; + VertexIndexMap vm; + const std::pair< edge_descriptor_t, bool > null_edge; + + // storage for the property maps below + std::vector< vertex_descriptor_t > mate_vector; + std::vector< vertex_descriptor_t > label_S_vector, label_T_vector; + std::vector< vertex_descriptor_t > outlet_vector; + std::vector< vertex_descriptor_t > tau_idx_vector; + std::vector< edge_property_t > dual_var_vector; + std::vector< edge_property_t > pi_vector, gamma_vector, tau_vector; + std::vector< blossom_ptr_t > in_blossom_vector; + std::vector< std::pair< vertex_descriptor_t, vertex_descriptor_t > > + old_label_vector; + std::vector< vertex_to_edge_map_t > critical_edge_vector; + std::vector< std::vector< std::pair< edge_descriptor_t, bool > > > + critical_edge_vectors; + + // iterator property maps + vertex_to_vertex_map_t mate; + vertex_to_vertex_map_t label_S; // v has an S-label -> v can be an even + // vertex, label_S[v] is its mate + vertex_to_vertex_map_t + label_T; // v has a T-label -> v can be an odd vertex, label_T[v] is its + // predecessor in aug_path + vertex_to_vertex_map_t outlet; + vertex_to_vertex_map_t tau_idx; + vertex_to_weight_map_t dual_var; + vertex_to_weight_map_t pi, gamma, tau; + vertex_to_blossom_map_t + in_blossom; // map any vertex v to the trivial blossom containing v + vertex_to_pair_map_t old_label; // <old T-label, old outlet> before + // relabeling or expanding T-blossoms + vertex_pair_to_edge_map_t + critical_edge; // an not matched edge (v, w) is critical if v and w + // belongs to different S-blossoms + + vertex_list_t aug_path; + edge_list_t even_edges; + std::vector< blossom_ptr_t > top_blossoms; +}; + +template < typename Graph, typename MateMap, typename VertexIndexMap > +void maximum_weighted_matching(const Graph& g, MateMap mate, VertexIndexMap vm) +{ + empty_matching< Graph, MateMap >::find_matching(g, mate); + weighted_augmenting_path_finder< Graph, MateMap, VertexIndexMap > augmentor( + g, mate, vm); + + // can have |V| times augmenting at most + for (std::size_t t = 0; t < num_vertices(g); ++t) + { + bool augmented = false; + while (!augmented) + { + augmented = augmentor.augment_matching(); + if (!augmented) + { + // halt if adjusting dual variables can't bring potential + // augment + if (!augmentor.adjust_dual()) + break; + } + } + if (!augmented) + break; + } + + augmentor.get_current_matching(mate); +} + +template < typename Graph, typename MateMap > +inline void maximum_weighted_matching(const Graph& g, MateMap mate) +{ + maximum_weighted_matching(g, mate, get(vertex_index, g)); +} + +// brute-force matcher searches all possible combinations of matched edges to +// get the maximum weighted matching which can be used for testing on small +// graphs (within dozens vertices) +template < typename Graph, typename MateMap, typename VertexIndexMap > +class brute_force_matching +{ +public: + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef + typename std::vector< vertex_descriptor_t >::iterator vertex_vec_iter_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + typedef boost::iterator_property_map< vertex_vec_iter_t, VertexIndexMap > + vertex_to_vertex_map_t; + + brute_force_matching( + const Graph& arg_g, MateMap arg_mate, VertexIndexMap arg_vm) + : g(arg_g) + , vm(arg_vm) + , mate_vector(num_vertices(g)) + , best_mate_vector(num_vertices(g)) + , mate(mate_vector.begin(), vm) + , best_mate(best_mate_vector.begin(), vm) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + best_mate[*vi] = mate[*vi] = get(arg_mate, *vi); + } + + template < typename PropertyMap > void find_matching(PropertyMap pm) + { + edge_iterator_t ei; + boost::tie(ei, ei_end) = edges(g); + select_edge(ei); + + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + put(pm, *vi, best_mate[*vi]); + } + +private: + const Graph& g; + VertexIndexMap vm; + std::vector< vertex_descriptor_t > mate_vector, best_mate_vector; + vertex_to_vertex_map_t mate, best_mate; + edge_iterator_t ei_end; + + void select_edge(edge_iterator_t ei) + { + if (ei == ei_end) + { + if (matching_weight_sum(g, mate) + > matching_weight_sum(g, best_mate)) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + best_mate[*vi] = mate[*vi]; + } + return; + } + + vertex_descriptor_t v, w; + v = source(*ei, g); + w = target(*ei, g); + + select_edge(++ei); + + if (mate[v] == graph_traits< Graph >::null_vertex() + && mate[w] == graph_traits< Graph >::null_vertex()) + { + mate[v] = w; + mate[w] = v; + select_edge(ei); + mate[v] = mate[w] = graph_traits< Graph >::null_vertex(); + } + } +}; + +template < typename Graph, typename MateMap, typename VertexIndexMap > +void brute_force_maximum_weighted_matching( + const Graph& g, MateMap mate, VertexIndexMap vm) +{ + empty_matching< Graph, MateMap >::find_matching(g, mate); + brute_force_matching< Graph, MateMap, VertexIndexMap > brute_force_matcher( + g, mate, vm); + brute_force_matcher.find_matching(mate); +} + +template < typename Graph, typename MateMap > +inline void brute_force_maximum_weighted_matching(const Graph& g, MateMap mate) +{ + brute_force_maximum_weighted_matching(g, mate, get(vertex_index, g)); +} + +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/mcgregor_common_subgraphs.hpp b/contrib/restricted/boost/graph/include/boost/graph/mcgregor_common_subgraphs.hpp new file mode 100644 index 0000000000..9c2b4b980d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/mcgregor_common_subgraphs.hpp @@ -0,0 +1,1117 @@ +//======================================================================= +// Copyright 2009 Trustees of Indiana University. +// Authors: Michael Hansen, Andrew Lumsdaine +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP +#define BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP + +#include <algorithm> +#include <vector> +#include <stack> + +#include <boost/make_shared.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/filtered_graph.hpp> +#include <boost/graph/graph_utility.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/properties.hpp> +#include <boost/property_map/shared_array_property_map.hpp> + +namespace boost +{ + +namespace detail +{ + + // Traits associated with common subgraphs, used mainly to keep a + // consistent type for the correspondence maps. + template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond > + struct mcgregor_common_subgraph_traits + { + typedef typename graph_traits< GraphFirst >::vertex_descriptor + vertex_first_type; + typedef typename graph_traits< GraphSecond >::vertex_descriptor + vertex_second_type; + + typedef shared_array_property_map< vertex_second_type, + VertexIndexMapFirst > + correspondence_map_first_to_second_type; + + typedef shared_array_property_map< vertex_first_type, + VertexIndexMapSecond > + correspondence_map_second_to_first_type; + }; + +} // namespace detail + +// ========================================================================== + +// Binary function object that returns true if the values for item1 +// in property_map1 and item2 in property_map2 are equivalent. +template < typename PropertyMapFirst, typename PropertyMapSecond > +struct property_map_equivalent +{ + + property_map_equivalent(const PropertyMapFirst property_map1, + const PropertyMapSecond property_map2) + : m_property_map1(property_map1), m_property_map2(property_map2) + { + } + + template < typename ItemFirst, typename ItemSecond > + bool operator()(const ItemFirst item1, const ItemSecond item2) + { + return (get(m_property_map1, item1) == get(m_property_map2, item2)); + } + +private: + const PropertyMapFirst m_property_map1; + const PropertyMapSecond m_property_map2; +}; + +// Returns a property_map_equivalent object that compares the values +// of property_map1 and property_map2. +template < typename PropertyMapFirst, typename PropertyMapSecond > +property_map_equivalent< PropertyMapFirst, PropertyMapSecond > +make_property_map_equivalent( + const PropertyMapFirst property_map1, const PropertyMapSecond property_map2) +{ + + return (property_map_equivalent< PropertyMapFirst, PropertyMapSecond >( + property_map1, property_map2)); +} + +// Binary function object that always returns true. Used when +// vertices or edges are always equivalent (i.e. have no labels). +struct always_equivalent +{ + + template < typename ItemFirst, typename ItemSecond > + bool operator()(const ItemFirst&, const ItemSecond&) + { + return (true); + } +}; + +// ========================================================================== + +namespace detail +{ + + // Return true if new_vertex1 and new_vertex2 can extend the + // subgraph represented by correspondence_map_1_to_2 and + // correspondence_map_2_to_1. The vertices_equivalent and + // edges_equivalent predicates are used to test vertex and edge + // equivalency between the two graphs. + template < typename GraphFirst, typename GraphSecond, + typename CorrespondenceMapFirstToSecond, + typename CorrespondenceMapSecondToFirst, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate > + bool can_extend_graph(const GraphFirst& graph1, const GraphSecond& graph2, + CorrespondenceMapFirstToSecond correspondence_map_1_to_2, + CorrespondenceMapSecondToFirst /*correspondence_map_2_to_1*/, + typename graph_traits< GraphFirst >::vertices_size_type subgraph_size, + typename graph_traits< GraphFirst >::vertex_descriptor new_vertex1, + typename graph_traits< GraphSecond >::vertex_descriptor new_vertex2, + EdgeEquivalencePredicate edges_equivalent, + VertexEquivalencePredicate vertices_equivalent, + bool only_connected_subgraphs) + { + typedef typename graph_traits< GraphSecond >::vertex_descriptor + VertexSecond; + + typedef typename graph_traits< GraphFirst >::edge_descriptor EdgeFirst; + typedef + typename graph_traits< GraphSecond >::edge_descriptor EdgeSecond; + + // Check vertex equality + if (!vertices_equivalent(new_vertex1, new_vertex2)) + { + return (false); + } + + // Vertices match and graph is empty, so we can extend the subgraph + if (subgraph_size == 0) + { + return (true); + } + + bool has_one_edge = false; + + // Verify edges with existing sub-graph + BGL_FORALL_VERTICES_T(existing_vertex1, graph1, GraphFirst) + { + + VertexSecond existing_vertex2 + = get(correspondence_map_1_to_2, existing_vertex1); + + // Skip unassociated vertices + if (existing_vertex2 == graph_traits< GraphSecond >::null_vertex()) + { + continue; + } + + // NOTE: This will not work with parallel edges, since the + // first matching edge is always chosen. + EdgeFirst edge_to_new1, edge_from_new1; + bool edge_to_new_exists1 = false, edge_from_new_exists1 = false; + + EdgeSecond edge_to_new2, edge_from_new2; + bool edge_to_new_exists2 = false, edge_from_new_exists2 = false; + + // Search for edge from existing to new vertex (graph1) + BGL_FORALL_OUTEDGES_T(existing_vertex1, edge1, graph1, GraphFirst) + { + if (target(edge1, graph1) == new_vertex1) + { + edge_to_new1 = edge1; + edge_to_new_exists1 = true; + break; + } + } + + // Search for edge from existing to new vertex (graph2) + BGL_FORALL_OUTEDGES_T(existing_vertex2, edge2, graph2, GraphSecond) + { + if (target(edge2, graph2) == new_vertex2) + { + edge_to_new2 = edge2; + edge_to_new_exists2 = true; + break; + } + } + + // Make sure edges from existing to new vertices are equivalent + if ((edge_to_new_exists1 != edge_to_new_exists2) + || ((edge_to_new_exists1 && edge_to_new_exists2) + && !edges_equivalent(edge_to_new1, edge_to_new2))) + { + + return (false); + } + + bool is_undirected1 = is_undirected(graph1), + is_undirected2 = is_undirected(graph2); + + if (is_undirected1 && is_undirected2) + { + + // Edge in both graphs exists and both graphs are undirected + if (edge_to_new_exists1 && edge_to_new_exists2) + { + has_one_edge = true; + } + + continue; + } + else + { + + if (!is_undirected1) + { + + // Search for edge from new to existing vertex (graph1) + BGL_FORALL_OUTEDGES_T( + new_vertex1, edge1, graph1, GraphFirst) + { + if (target(edge1, graph1) == existing_vertex1) + { + edge_from_new1 = edge1; + edge_from_new_exists1 = true; + break; + } + } + } + + if (!is_undirected2) + { + + // Search for edge from new to existing vertex (graph2) + BGL_FORALL_OUTEDGES_T( + new_vertex2, edge2, graph2, GraphSecond) + { + if (target(edge2, graph2) == existing_vertex2) + { + edge_from_new2 = edge2; + edge_from_new_exists2 = true; + break; + } + } + } + + // Make sure edges from new to existing vertices are equivalent + if ((edge_from_new_exists1 != edge_from_new_exists2) + || ((edge_from_new_exists1 && edge_from_new_exists2) + && !edges_equivalent(edge_from_new1, edge_from_new2))) + { + + return (false); + } + + if ((edge_from_new_exists1 && edge_from_new_exists2) + || (edge_to_new_exists1 && edge_to_new_exists2)) + { + has_one_edge = true; + } + + } // else + + } // BGL_FORALL_VERTICES_T + + // Make sure new vertices are connected to the existing subgraph + if (only_connected_subgraphs && !has_one_edge) + { + return (false); + } + + return (true); + } + + // Recursive method that does a depth-first search in the space of + // potential subgraphs. At each level, every new vertex pair from + // both graphs is tested to see if it can extend the current + // subgraph. If so, the subgraph is output to subgraph_callback + // in the form of two correspondence maps (one for each graph). + // Returning false from subgraph_callback will terminate the + // search. Function returns true if the entire search space was + // explored. + template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename CorrespondenceMapFirstToSecond, + typename CorrespondenceMapSecondToFirst, typename VertexStackFirst, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphInternalCallback > + bool mcgregor_common_subgraphs_internal(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst& vindex_map1, + const VertexIndexMapSecond& vindex_map2, + CorrespondenceMapFirstToSecond correspondence_map_1_to_2, + CorrespondenceMapSecondToFirst correspondence_map_2_to_1, + VertexStackFirst& vertex_stack1, + EdgeEquivalencePredicate edges_equivalent, + VertexEquivalencePredicate vertices_equivalent, + bool only_connected_subgraphs, + SubGraphInternalCallback subgraph_callback) + { + typedef + typename graph_traits< GraphFirst >::vertex_descriptor VertexFirst; + typedef typename graph_traits< GraphSecond >::vertex_descriptor + VertexSecond; + typedef typename graph_traits< GraphFirst >::vertices_size_type + VertexSizeFirst; + + // Get iterators for vertices from both graphs + typename graph_traits< GraphFirst >::vertex_iterator vertex1_iter, + vertex1_end; + + typename graph_traits< GraphSecond >::vertex_iterator vertex2_begin, + vertex2_end, vertex2_iter; + + boost::tie(vertex1_iter, vertex1_end) = vertices(graph1); + boost::tie(vertex2_begin, vertex2_end) = vertices(graph2); + vertex2_iter = vertex2_begin; + + // Iterate until all vertices have been visited + BGL_FORALL_VERTICES_T(new_vertex1, graph1, GraphFirst) + { + + VertexSecond existing_vertex2 + = get(correspondence_map_1_to_2, new_vertex1); + + // Skip already matched vertices in first graph + if (existing_vertex2 != graph_traits< GraphSecond >::null_vertex()) + { + continue; + } + + BGL_FORALL_VERTICES_T(new_vertex2, graph2, GraphSecond) + { + + VertexFirst existing_vertex1 + = get(correspondence_map_2_to_1, new_vertex2); + + // Skip already matched vertices in second graph + if (existing_vertex1 + != graph_traits< GraphFirst >::null_vertex()) + { + continue; + } + + // Check if current sub-graph can be extended with the matched + // vertex pair + if (can_extend_graph(graph1, graph2, correspondence_map_1_to_2, + correspondence_map_2_to_1, + (VertexSizeFirst)vertex_stack1.size(), new_vertex1, + new_vertex2, edges_equivalent, vertices_equivalent, + only_connected_subgraphs)) + { + + // Keep track of old graph size for restoring later + VertexSizeFirst old_graph_size + = (VertexSizeFirst)vertex_stack1.size(), + new_graph_size = old_graph_size + 1; + + // Extend subgraph + put(correspondence_map_1_to_2, new_vertex1, new_vertex2); + put(correspondence_map_2_to_1, new_vertex2, new_vertex1); + vertex_stack1.push(new_vertex1); + + // Returning false from the callback will cancel iteration + if (!subgraph_callback(correspondence_map_1_to_2, + correspondence_map_2_to_1, new_graph_size)) + { + return (false); + } + + // Depth-first search into the state space of possible + // sub-graphs + bool continue_iteration + = mcgregor_common_subgraphs_internal(graph1, graph2, + vindex_map1, vindex_map2, correspondence_map_1_to_2, + correspondence_map_2_to_1, vertex_stack1, + edges_equivalent, vertices_equivalent, + only_connected_subgraphs, subgraph_callback); + + if (!continue_iteration) + { + return (false); + } + + // Restore previous state + if (vertex_stack1.size() > old_graph_size) + { + + VertexFirst stack_vertex1 = vertex_stack1.top(); + VertexSecond stack_vertex2 + = get(correspondence_map_1_to_2, stack_vertex1); + + // Contract subgraph + put(correspondence_map_1_to_2, stack_vertex1, + graph_traits< GraphSecond >::null_vertex()); + + put(correspondence_map_2_to_1, stack_vertex2, + graph_traits< GraphFirst >::null_vertex()); + + vertex_stack1.pop(); + } + + } // if can_extend_graph + + } // BGL_FORALL_VERTICES_T (graph2) + + } // BGL_FORALL_VERTICES_T (graph1) + + return (true); + } + + // Internal method that initializes blank correspondence maps and + // a vertex stack for use in mcgregor_common_subgraphs_internal. + template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphInternalCallback > + inline void mcgregor_common_subgraphs_internal_init( + const GraphFirst& graph1, const GraphSecond& graph2, + const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + EdgeEquivalencePredicate edges_equivalent, + VertexEquivalencePredicate vertices_equivalent, + bool only_connected_subgraphs, + SubGraphInternalCallback subgraph_callback) + { + typedef mcgregor_common_subgraph_traits< GraphFirst, GraphSecond, + VertexIndexMapFirst, VertexIndexMapSecond > + SubGraphTraits; + + typename SubGraphTraits::correspondence_map_first_to_second_type + correspondence_map_1_to_2(num_vertices(graph1), vindex_map1); + + BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) + { + put(correspondence_map_1_to_2, vertex1, + graph_traits< GraphSecond >::null_vertex()); + } + + typename SubGraphTraits::correspondence_map_second_to_first_type + correspondence_map_2_to_1(num_vertices(graph2), vindex_map2); + + BGL_FORALL_VERTICES_T(vertex2, graph2, GraphSecond) + { + put(correspondence_map_2_to_1, vertex2, + graph_traits< GraphFirst >::null_vertex()); + } + + typedef + typename graph_traits< GraphFirst >::vertex_descriptor VertexFirst; + + std::stack< VertexFirst > vertex_stack1; + + mcgregor_common_subgraphs_internal(graph1, graph2, vindex_map1, + vindex_map2, correspondence_map_1_to_2, correspondence_map_2_to_1, + vertex_stack1, edges_equivalent, vertices_equivalent, + only_connected_subgraphs, subgraph_callback); + } + +} // namespace detail + +// ========================================================================== + +// Enumerates all common subgraphs present in graph1 and graph2. +// Continues until the search space has been fully explored or false +// is returned from user_callback. +template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphCallback > +void mcgregor_common_subgraphs(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + EdgeEquivalencePredicate edges_equivalent, + VertexEquivalencePredicate vertices_equivalent, + bool only_connected_subgraphs, SubGraphCallback user_callback) +{ + + detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, + vindex_map2, edges_equivalent, vertices_equivalent, + only_connected_subgraphs, user_callback); +} + +// Variant of mcgregor_common_subgraphs with all default parameters +template < typename GraphFirst, typename GraphSecond, + typename SubGraphCallback > +void mcgregor_common_subgraphs(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback) +{ + + detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, + get(vertex_index, graph1), get(vertex_index, graph2), + always_equivalent(), always_equivalent(), only_connected_subgraphs, + user_callback); +} + +// Named parameter variant of mcgregor_common_subgraphs +template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, + typename Param, typename Tag, typename Rest > +void mcgregor_common_subgraphs(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback, + const bgl_named_params< Param, Tag, Rest >& params) +{ + + detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, + choose_const_pmap( + get_param(params, vertex_index1), graph1, vertex_index), + choose_const_pmap( + get_param(params, vertex_index2), graph2, vertex_index), + choose_param( + get_param(params, edges_equivalent_t()), always_equivalent()), + choose_param( + get_param(params, vertices_equivalent_t()), always_equivalent()), + only_connected_subgraphs, user_callback); +} + +// ========================================================================== + +namespace detail +{ + + // Binary function object that intercepts subgraphs from + // mcgregor_common_subgraphs_internal and maintains a cache of + // unique subgraphs. The user callback is invoked for each unique + // subgraph. + template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename SubGraphCallback > + struct unique_subgraph_interceptor + { + + typedef typename graph_traits< GraphFirst >::vertices_size_type + VertexSizeFirst; + + typedef mcgregor_common_subgraph_traits< GraphFirst, GraphSecond, + VertexIndexMapFirst, VertexIndexMapSecond > + SubGraphTraits; + + typedef typename SubGraphTraits::correspondence_map_first_to_second_type + CachedCorrespondenceMapFirstToSecond; + + typedef typename SubGraphTraits::correspondence_map_second_to_first_type + CachedCorrespondenceMapSecondToFirst; + + typedef std::pair< VertexSizeFirst, + std::pair< CachedCorrespondenceMapFirstToSecond, + CachedCorrespondenceMapSecondToFirst > > + SubGraph; + + typedef std::vector< SubGraph > SubGraphList; + + unique_subgraph_interceptor(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + SubGraphCallback user_callback) + : m_graph1(graph1) + , m_graph2(graph2) + , m_vindex_map1(vindex_map1) + , m_vindex_map2(vindex_map2) + , m_subgraphs(make_shared< SubGraphList >()) + , m_user_callback(user_callback) + { + } + + template < typename CorrespondenceMapFirstToSecond, + typename CorrespondenceMapSecondToFirst > + bool operator()( + CorrespondenceMapFirstToSecond correspondence_map_1_to_2, + CorrespondenceMapSecondToFirst correspondence_map_2_to_1, + VertexSizeFirst subgraph_size) + { + + for (typename SubGraphList::const_iterator subgraph_iter + = m_subgraphs->begin(); + subgraph_iter != m_subgraphs->end(); ++subgraph_iter) + { + + SubGraph subgraph_cached = *subgraph_iter; + + // Compare subgraph sizes + if (subgraph_size != subgraph_cached.first) + { + continue; + } + + if (!are_property_maps_different(correspondence_map_1_to_2, + subgraph_cached.second.first, m_graph1)) + { + + // New subgraph is a duplicate + return (true); + } + } + + // Subgraph is unique, so make a cached copy + CachedCorrespondenceMapFirstToSecond new_subgraph_1_to_2 + = CachedCorrespondenceMapFirstToSecond( + num_vertices(m_graph1), m_vindex_map1); + + CachedCorrespondenceMapSecondToFirst new_subgraph_2_to_1 + = CorrespondenceMapSecondToFirst( + num_vertices(m_graph2), m_vindex_map2); + + BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) + { + put(new_subgraph_1_to_2, vertex1, + get(correspondence_map_1_to_2, vertex1)); + } + + BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) + { + put(new_subgraph_2_to_1, vertex2, + get(correspondence_map_2_to_1, vertex2)); + } + + m_subgraphs->push_back(std::make_pair(subgraph_size, + std::make_pair(new_subgraph_1_to_2, new_subgraph_2_to_1))); + + return (m_user_callback(correspondence_map_1_to_2, + correspondence_map_2_to_1, subgraph_size)); + } + + private: + const GraphFirst& m_graph1; + const GraphFirst& m_graph2; + const VertexIndexMapFirst m_vindex_map1; + const VertexIndexMapSecond m_vindex_map2; + shared_ptr< SubGraphList > m_subgraphs; + SubGraphCallback m_user_callback; + }; + +} // namespace detail + +// Enumerates all unique common subgraphs between graph1 and graph2. +// The user callback is invoked for each unique subgraph as they are +// discovered. +template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphCallback > +void mcgregor_common_subgraphs_unique(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + EdgeEquivalencePredicate edges_equivalent, + VertexEquivalencePredicate vertices_equivalent, + bool only_connected_subgraphs, SubGraphCallback user_callback) +{ + detail::unique_subgraph_interceptor< GraphFirst, GraphSecond, + VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback > + unique_callback( + graph1, graph2, vindex_map1, vindex_map2, user_callback); + + detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, + vindex_map2, edges_equivalent, vertices_equivalent, + only_connected_subgraphs, unique_callback); +} + +// Variant of mcgregor_common_subgraphs_unique with all default +// parameters. +template < typename GraphFirst, typename GraphSecond, + typename SubGraphCallback > +void mcgregor_common_subgraphs_unique(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback) +{ + mcgregor_common_subgraphs_unique(graph1, graph2, get(vertex_index, graph1), + get(vertex_index, graph2), always_equivalent(), always_equivalent(), + only_connected_subgraphs, user_callback); +} + +// Named parameter variant of mcgregor_common_subgraphs_unique +template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, + typename Param, typename Tag, typename Rest > +void mcgregor_common_subgraphs_unique(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback, + const bgl_named_params< Param, Tag, Rest >& params) +{ + mcgregor_common_subgraphs_unique(graph1, graph2, + choose_const_pmap( + get_param(params, vertex_index1), graph1, vertex_index), + choose_const_pmap( + get_param(params, vertex_index2), graph2, vertex_index), + choose_param( + get_param(params, edges_equivalent_t()), always_equivalent()), + choose_param( + get_param(params, vertices_equivalent_t()), always_equivalent()), + only_connected_subgraphs, user_callback); +} + +// ========================================================================== + +namespace detail +{ + + // Binary function object that intercepts subgraphs from + // mcgregor_common_subgraphs_internal and maintains a cache of the + // largest subgraphs. + template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename SubGraphCallback > + struct maximum_subgraph_interceptor + { + + typedef typename graph_traits< GraphFirst >::vertices_size_type + VertexSizeFirst; + + typedef mcgregor_common_subgraph_traits< GraphFirst, GraphSecond, + VertexIndexMapFirst, VertexIndexMapSecond > + SubGraphTraits; + + typedef typename SubGraphTraits::correspondence_map_first_to_second_type + CachedCorrespondenceMapFirstToSecond; + + typedef typename SubGraphTraits::correspondence_map_second_to_first_type + CachedCorrespondenceMapSecondToFirst; + + typedef std::pair< VertexSizeFirst, + std::pair< CachedCorrespondenceMapFirstToSecond, + CachedCorrespondenceMapSecondToFirst > > + SubGraph; + + typedef std::vector< SubGraph > SubGraphList; + + maximum_subgraph_interceptor(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + SubGraphCallback user_callback) + : m_graph1(graph1) + , m_graph2(graph2) + , m_vindex_map1(vindex_map1) + , m_vindex_map2(vindex_map2) + , m_subgraphs(make_shared< SubGraphList >()) + , m_largest_size_so_far(make_shared< VertexSizeFirst >(0)) + , m_user_callback(user_callback) + { + } + + template < typename CorrespondenceMapFirstToSecond, + typename CorrespondenceMapSecondToFirst > + bool operator()( + CorrespondenceMapFirstToSecond correspondence_map_1_to_2, + CorrespondenceMapSecondToFirst correspondence_map_2_to_1, + VertexSizeFirst subgraph_size) + { + + if (subgraph_size > *m_largest_size_so_far) + { + m_subgraphs->clear(); + *m_largest_size_so_far = subgraph_size; + } + + if (subgraph_size == *m_largest_size_so_far) + { + + // Make a cached copy + CachedCorrespondenceMapFirstToSecond new_subgraph_1_to_2 + = CachedCorrespondenceMapFirstToSecond( + num_vertices(m_graph1), m_vindex_map1); + + CachedCorrespondenceMapSecondToFirst new_subgraph_2_to_1 + = CachedCorrespondenceMapSecondToFirst( + num_vertices(m_graph2), m_vindex_map2); + + BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) + { + put(new_subgraph_1_to_2, vertex1, + get(correspondence_map_1_to_2, vertex1)); + } + + BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) + { + put(new_subgraph_2_to_1, vertex2, + get(correspondence_map_2_to_1, vertex2)); + } + + m_subgraphs->push_back(std::make_pair(subgraph_size, + std::make_pair(new_subgraph_1_to_2, new_subgraph_2_to_1))); + } + + return (true); + } + + void output_subgraphs() + { + for (typename SubGraphList::const_iterator subgraph_iter + = m_subgraphs->begin(); + subgraph_iter != m_subgraphs->end(); ++subgraph_iter) + { + + SubGraph subgraph_cached = *subgraph_iter; + m_user_callback(subgraph_cached.second.first, + subgraph_cached.second.second, subgraph_cached.first); + } + } + + private: + const GraphFirst& m_graph1; + const GraphFirst& m_graph2; + const VertexIndexMapFirst m_vindex_map1; + const VertexIndexMapSecond m_vindex_map2; + shared_ptr< SubGraphList > m_subgraphs; + shared_ptr< VertexSizeFirst > m_largest_size_so_far; + SubGraphCallback m_user_callback; + }; + +} // namespace detail + +// Enumerates the largest common subgraphs found between graph1 +// and graph2. Note that the ENTIRE search space is explored before +// user_callback is actually invoked. +template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphCallback > +void mcgregor_common_subgraphs_maximum(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + EdgeEquivalencePredicate edges_equivalent, + VertexEquivalencePredicate vertices_equivalent, + bool only_connected_subgraphs, SubGraphCallback user_callback) +{ + detail::maximum_subgraph_interceptor< GraphFirst, GraphSecond, + VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback > + max_interceptor( + graph1, graph2, vindex_map1, vindex_map2, user_callback); + + detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, + vindex_map2, edges_equivalent, vertices_equivalent, + only_connected_subgraphs, max_interceptor); + + // Only output the largest subgraphs + max_interceptor.output_subgraphs(); +} + +// Variant of mcgregor_common_subgraphs_maximum with all default +// parameters. +template < typename GraphFirst, typename GraphSecond, + typename SubGraphCallback > +void mcgregor_common_subgraphs_maximum(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback) +{ + mcgregor_common_subgraphs_maximum(graph1, graph2, get(vertex_index, graph1), + get(vertex_index, graph2), always_equivalent(), always_equivalent(), + only_connected_subgraphs, user_callback); +} + +// Named parameter variant of mcgregor_common_subgraphs_maximum +template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, + typename Param, typename Tag, typename Rest > +void mcgregor_common_subgraphs_maximum(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback, + const bgl_named_params< Param, Tag, Rest >& params) +{ + mcgregor_common_subgraphs_maximum(graph1, graph2, + choose_const_pmap( + get_param(params, vertex_index1), graph1, vertex_index), + choose_const_pmap( + get_param(params, vertex_index2), graph2, vertex_index), + choose_param( + get_param(params, edges_equivalent_t()), always_equivalent()), + choose_param( + get_param(params, vertices_equivalent_t()), always_equivalent()), + only_connected_subgraphs, user_callback); +} + +// ========================================================================== + +namespace detail +{ + + // Binary function object that intercepts subgraphs from + // mcgregor_common_subgraphs_internal and maintains a cache of the + // largest, unique subgraphs. + template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename SubGraphCallback > + struct unique_maximum_subgraph_interceptor + { + + typedef typename graph_traits< GraphFirst >::vertices_size_type + VertexSizeFirst; + + typedef mcgregor_common_subgraph_traits< GraphFirst, GraphSecond, + VertexIndexMapFirst, VertexIndexMapSecond > + SubGraphTraits; + + typedef typename SubGraphTraits::correspondence_map_first_to_second_type + CachedCorrespondenceMapFirstToSecond; + + typedef typename SubGraphTraits::correspondence_map_second_to_first_type + CachedCorrespondenceMapSecondToFirst; + + typedef std::pair< VertexSizeFirst, + std::pair< CachedCorrespondenceMapFirstToSecond, + CachedCorrespondenceMapSecondToFirst > > + SubGraph; + + typedef std::vector< SubGraph > SubGraphList; + + unique_maximum_subgraph_interceptor(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + SubGraphCallback user_callback) + : m_graph1(graph1) + , m_graph2(graph2) + , m_vindex_map1(vindex_map1) + , m_vindex_map2(vindex_map2) + , m_subgraphs(make_shared< SubGraphList >()) + , m_largest_size_so_far(make_shared< VertexSizeFirst >(0)) + , m_user_callback(user_callback) + { + } + + template < typename CorrespondenceMapFirstToSecond, + typename CorrespondenceMapSecondToFirst > + bool operator()( + CorrespondenceMapFirstToSecond correspondence_map_1_to_2, + CorrespondenceMapSecondToFirst correspondence_map_2_to_1, + VertexSizeFirst subgraph_size) + { + + if (subgraph_size > *m_largest_size_so_far) + { + m_subgraphs->clear(); + *m_largest_size_so_far = subgraph_size; + } + + if (subgraph_size == *m_largest_size_so_far) + { + + // Check if subgraph is unique + for (typename SubGraphList::const_iterator subgraph_iter + = m_subgraphs->begin(); + subgraph_iter != m_subgraphs->end(); ++subgraph_iter) + { + + SubGraph subgraph_cached = *subgraph_iter; + + if (!are_property_maps_different(correspondence_map_1_to_2, + subgraph_cached.second.first, m_graph1)) + { + + // New subgraph is a duplicate + return (true); + } + } + + // Subgraph is unique, so make a cached copy + CachedCorrespondenceMapFirstToSecond new_subgraph_1_to_2 + = CachedCorrespondenceMapFirstToSecond( + num_vertices(m_graph1), m_vindex_map1); + + CachedCorrespondenceMapSecondToFirst new_subgraph_2_to_1 + = CachedCorrespondenceMapSecondToFirst( + num_vertices(m_graph2), m_vindex_map2); + + BGL_FORALL_VERTICES_T(vertex1, m_graph1, GraphFirst) + { + put(new_subgraph_1_to_2, vertex1, + get(correspondence_map_1_to_2, vertex1)); + } + + BGL_FORALL_VERTICES_T(vertex2, m_graph2, GraphFirst) + { + put(new_subgraph_2_to_1, vertex2, + get(correspondence_map_2_to_1, vertex2)); + } + + m_subgraphs->push_back(std::make_pair(subgraph_size, + std::make_pair(new_subgraph_1_to_2, new_subgraph_2_to_1))); + } + + return (true); + } + + void output_subgraphs() + { + for (typename SubGraphList::const_iterator subgraph_iter + = m_subgraphs->begin(); + subgraph_iter != m_subgraphs->end(); ++subgraph_iter) + { + + SubGraph subgraph_cached = *subgraph_iter; + m_user_callback(subgraph_cached.second.first, + subgraph_cached.second.second, subgraph_cached.first); + } + } + + private: + const GraphFirst& m_graph1; + const GraphFirst& m_graph2; + const VertexIndexMapFirst m_vindex_map1; + const VertexIndexMapSecond m_vindex_map2; + shared_ptr< SubGraphList > m_subgraphs; + shared_ptr< VertexSizeFirst > m_largest_size_so_far; + SubGraphCallback m_user_callback; + }; + +} // namespace detail + +// Enumerates the largest, unique common subgraphs found between +// graph1 and graph2. Note that the ENTIRE search space is explored +// before user_callback is actually invoked. +template < typename GraphFirst, typename GraphSecond, + typename VertexIndexMapFirst, typename VertexIndexMapSecond, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphCallback > +void mcgregor_common_subgraphs_maximum_unique(const GraphFirst& graph1, + const GraphSecond& graph2, const VertexIndexMapFirst vindex_map1, + const VertexIndexMapSecond vindex_map2, + EdgeEquivalencePredicate edges_equivalent, + VertexEquivalencePredicate vertices_equivalent, + bool only_connected_subgraphs, SubGraphCallback user_callback) +{ + detail::unique_maximum_subgraph_interceptor< GraphFirst, GraphSecond, + VertexIndexMapFirst, VertexIndexMapSecond, SubGraphCallback > + unique_max_interceptor( + graph1, graph2, vindex_map1, vindex_map2, user_callback); + + detail::mcgregor_common_subgraphs_internal_init(graph1, graph2, vindex_map1, + vindex_map2, edges_equivalent, vertices_equivalent, + only_connected_subgraphs, unique_max_interceptor); + + // Only output the largest, unique subgraphs + unique_max_interceptor.output_subgraphs(); +} + +// Variant of mcgregor_common_subgraphs_maximum_unique with all default +// parameters +template < typename GraphFirst, typename GraphSecond, + typename SubGraphCallback > +void mcgregor_common_subgraphs_maximum_unique(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback) +{ + + mcgregor_common_subgraphs_maximum_unique(graph1, graph2, + get(vertex_index, graph1), get(vertex_index, graph2), + always_equivalent(), always_equivalent(), only_connected_subgraphs, + user_callback); +} + +// Named parameter variant of +// mcgregor_common_subgraphs_maximum_unique +template < typename GraphFirst, typename GraphSecond, typename SubGraphCallback, + typename Param, typename Tag, typename Rest > +void mcgregor_common_subgraphs_maximum_unique(const GraphFirst& graph1, + const GraphSecond& graph2, bool only_connected_subgraphs, + SubGraphCallback user_callback, + const bgl_named_params< Param, Tag, Rest >& params) +{ + mcgregor_common_subgraphs_maximum_unique(graph1, graph2, + choose_const_pmap( + get_param(params, vertex_index1), graph1, vertex_index), + choose_const_pmap( + get_param(params, vertex_index2), graph2, vertex_index), + choose_param( + get_param(params, edges_equivalent_t()), always_equivalent()), + choose_param( + get_param(params, vertices_equivalent_t()), always_equivalent()), + only_connected_subgraphs, user_callback); +} + +// ========================================================================== + +// Fills a membership map (vertex -> bool) using the information +// present in correspondence_map_1_to_2. Every vertex in a +// membership map will have a true value only if it is not +// associated with a null vertex in the correspondence map. +template < typename GraphSecond, typename GraphFirst, + typename CorrespondenceMapFirstToSecond, typename MembershipMapFirst > +void fill_membership_map(const GraphFirst& graph1, + const CorrespondenceMapFirstToSecond correspondence_map_1_to_2, + MembershipMapFirst membership_map1) +{ + + BGL_FORALL_VERTICES_T(vertex1, graph1, GraphFirst) + { + put(membership_map1, vertex1, + get(correspondence_map_1_to_2, vertex1) + != graph_traits< GraphSecond >::null_vertex()); + } +} + +// Traits associated with a membership map filtered graph. Provided +// for convenience to access graph and vertex filter types. +template < typename Graph, typename MembershipMap > +struct membership_filtered_graph_traits +{ + typedef property_map_filter< MembershipMap > vertex_filter_type; + typedef filtered_graph< Graph, keep_all, vertex_filter_type > graph_type; +}; + +// Returns a filtered sub-graph of graph whose edge and vertex +// inclusion is dictated by membership_map. +template < typename Graph, typename MembershipMap > +typename membership_filtered_graph_traits< Graph, MembershipMap >::graph_type +make_membership_filtered_graph( + const Graph& graph, MembershipMap& membership_map) +{ + + typedef membership_filtered_graph_traits< Graph, MembershipMap > MFGTraits; + typedef typename MFGTraits::graph_type MembershipFilteredGraph; + + typename MFGTraits::vertex_filter_type v_filter(membership_map); + + return (MembershipFilteredGraph(graph, keep_all(), v_filter)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_MCGREGOR_COMMON_SUBGRAPHS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/mesh_graph_generator.hpp b/contrib/restricted/boost/graph/include/boost/graph/mesh_graph_generator.hpp new file mode 100644 index 0000000000..0dcba2adad --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/mesh_graph_generator.hpp @@ -0,0 +1,184 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Nick Edmonds +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_MESH_GENERATOR_HPP +#define BOOST_GRAPH_MESH_GENERATOR_HPP + +#include <iterator> +#include <utility> +#include <boost/assert.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/type_traits/is_same.hpp> + +namespace boost +{ + +template < typename Graph > class mesh_iterator +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + + BOOST_STATIC_CONSTANT(bool, + is_undirected + = (is_base_and_derived< undirected_tag, directed_category >::value + || is_same< undirected_tag, directed_category >::value)); + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + mesh_iterator() : x(0), y(0), done(true) {} + + // Vertices are numbered in row-major order + // Assumes directed + mesh_iterator( + vertices_size_type x, vertices_size_type y, bool toroidal = true) + : x(x) + , y(y) + , n(x * y) + , source(0) + , target(1) + , current(0, 1) + , toroidal(toroidal) + , done(false) + { + BOOST_ASSERT(x > 1 && y > 1); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + mesh_iterator& operator++() + { + if (is_undirected) + { + if (!toroidal) + { + if (target == source + 1) + if (source < x * (y - 1)) + target = source + x; + else + { + source++; + target = (source % x) < x - 1 ? source + 1 : source + x; + if (target > n) + done = true; + } + else if (target == source + x) + { + source++; + target = (source % x) < x - 1 ? source + 1 : source + x; + } + } + else + { + if (target == source + 1 || target == source - (source % x)) + target = (source + x) % n; + else if (target == (source + x) % n) + { + if (source == n - 1) + done = true; + else + { + source++; + target = (source % x) < (x - 1) ? source + 1 + : source - (source % x); + } + } + } + } + else + { // Directed + if (!toroidal) + { + if (target == source - x) + target = source % x > 0 ? source - 1 : source + 1; + else if (target == source - 1) + if ((source % x) < (x - 1)) + target = source + 1; + else if (source < x * (y - 1)) + target = source + x; + else + { + done = true; + } + else if (target == source + 1) + if (source < x * (y - 1)) + target = source + x; + else + { + source++; + target = source - x; + } + else if (target == source + x) + { + source++; + target = (source >= x) ? source - x : source - 1; + } + } + else + { + if (source == n - 1 && target == (source + x) % n) + done = true; + else if (target == source - 1 || target == source + x - 1) + target = (source + x) % n; + else if (target == source + 1 + || target == source - (source % x)) + target = (source - x + n) % n; + else if (target == (source - x + n) % n) + target = (source % x > 0) ? source - 1 : source + x - 1; + else if (target == (source + x) % n) + { + source++; + target = (source % x) < (x - 1) ? source + 1 + : source - (source % x); + } + } + } + + current.first = source; + current.second = target; + + return *this; + } + + mesh_iterator operator++(int) + { + mesh_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const mesh_iterator& other) const + { + return done == other.done; + } + + bool operator!=(const mesh_iterator& other) const + { + return !(*this == other); + } + +private: + vertices_size_type x, y; + vertices_size_type n; + vertices_size_type source; + vertices_size_type target; + value_type current; + bool toroidal; + bool done; +}; + +} // end namespace boost + +#endif // BOOST_GRAPH_MESH_GENERATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/metis.hpp b/contrib/restricted/boost/graph/include/boost/graph/metis.hpp new file mode 100644 index 0000000000..e6567c999a --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/metis.hpp @@ -0,0 +1,369 @@ +// Copyright 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_METIS_HPP +#define BOOST_GRAPH_METIS_HPP + +#ifdef BOOST_GRAPH_METIS_NO_INLINE +#define BOOST_GRAPH_METIS_INLINE_KEYWORD +#else +#define BOOST_GRAPH_METIS_INLINE_KEYWORD inline +#endif + +#include <string> +#include <iostream> +#include <iterator> +#include <utility> +#include <sstream> +#include <exception> +#include <vector> +#include <algorithm> + +#include <boost/throw_exception.hpp> + +namespace boost +{ +namespace graph +{ + + class BOOST_SYMBOL_VISIBLE metis_exception : public std::exception + { + }; + class BOOST_SYMBOL_VISIBLE metis_input_exception : public metis_exception + { + }; + + class metis_reader + { + public: + typedef std::size_t vertices_size_type; + typedef std::size_t edges_size_type; + typedef double vertex_weight_type; + typedef double edge_weight_type; + + class edge_iterator + { + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > + value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; + + private: + class postincrement_proxy + { + postincrement_proxy(const value_type& value) : value(value) {} + + public: + reference operator*() const { return value; } + + private: + value_type value; + friend class edge_iterator; + }; + + public: + edge_iterator& operator++(); + postincrement_proxy operator++(int); + + reference operator*() const { return self->edge; } + pointer operator->() const { return &self->edge; } + + // Default copy constructor and assignment operator are okay + + private: + edge_iterator(metis_reader* self); + void advance(bool skip_initial_read); + + metis_reader* self; + + friend class metis_reader; + friend bool operator==(edge_iterator, edge_iterator); + friend bool operator!=(edge_iterator, edge_iterator); + }; + friend class edge_iterator; + + class edge_weight_iterator + { + public: + typedef std::input_iterator_tag iterator_category; + typedef edge_weight_type value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + + // Default copy constructor and assignment operator are okay + + reference operator*() const { return self->edge_weight; } + pointer operator->() const { return &self->edge_weight; } + + edge_weight_iterator& operator++() { return *this; } + edge_weight_iterator operator++(int) { return *this; } + + private: + edge_weight_iterator(metis_reader* self) : self(self) {} + + metis_reader* self; + + friend class metis_reader; + }; + + metis_reader(std::istream& in) : in(in), edge_weight(1.0) { start(); } + + edge_iterator begin(); + edge_iterator end(); + edge_weight_iterator weight_begin(); + + vertices_size_type num_vertices() const { return n_vertices; } + edges_size_type num_edges() const { return n_edges; } + + std::size_t num_vertex_weights() const { return n_vertex_weights; } + + vertex_weight_type vertex_weight(vertices_size_type v, std::size_t n) + { + return vertex_weights[v * num_vertex_weights() + n]; + } + + bool has_edge_weights() const { return edge_weights; } + + private: + void start(); + + // Configuration information + std::istream& in; + + // Information about the current METIS file + vertices_size_type n_vertices; + edges_size_type n_edges; + std::size_t n_vertex_weights; + bool edge_weights; + + // Information about the current edge/vertex + std::istringstream line_in; + std::pair< vertices_size_type, vertices_size_type > edge; + std::vector< vertex_weight_type > vertex_weights; + edge_weight_type edge_weight; + + friend bool operator==(edge_iterator, edge_iterator); + friend bool operator!=(edge_iterator, edge_iterator); + }; + + class metis_distribution + { + public: + typedef int process_id_type; + typedef std::size_t size_type; + typedef std::vector< process_id_type >::iterator iterator; + + metis_distribution(std::istream& in, process_id_type my_id); + + size_type block_size(process_id_type id, size_type) const; + process_id_type operator()(size_type n) const { return vertices[n]; } + size_type local(size_type n) const; + size_type global(size_type n) const { return global(my_id, n); } + size_type global(process_id_type id, size_type n) const; + + iterator begin() { return vertices.begin(); } + iterator end() { return vertices.end(); } + + private: + process_id_type my_id; + std::vector< process_id_type > vertices; + }; + +#if !defined(BOOST_GRAPH_METIS_NO_INLINE) || defined(BOOST_GRAPH_METIS_SOURCE) + BOOST_GRAPH_METIS_INLINE_KEYWORD + bool operator==( + metis_reader::edge_iterator x, metis_reader::edge_iterator y) + { + return (x.self == y.self + || (x.self && x.self->edge.first == x.self->num_vertices()) + || (y.self && y.self->edge.first == y.self->num_vertices())); + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + bool operator!=( + metis_reader::edge_iterator x, metis_reader::edge_iterator y) + { + return !(x == y); + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + metis_reader::edge_iterator::edge_iterator(metis_reader* self) : self(self) + { + if (self) + advance(true); + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + metis_reader::edge_iterator& metis_reader::edge_iterator::operator++() + { + advance(false); + return *this; + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + void metis_reader::edge_iterator::advance(bool skip_initial_read) + { + do + { + + if (!skip_initial_read) + { + // Try to read the next edge + if (self->line_in >> std::ws >> self->edge.second) + { + --self->edge.second; + if (self->has_edge_weights()) + { + if (!(self->line_in >> self->edge_weight)) + boost::throw_exception(metis_input_exception()); + } + return; + } + + // Check if we're done + ++self->edge.first; + if (self->edge.first == self->num_vertices()) + return; + } + + // Find the next line + std::string line; + while (getline(self->in, line) && !line.empty() && line[0] == '%') + { + /* Keep reading lines in the loop header... */ + } + if (!self->in) + boost::throw_exception(metis_input_exception()); + self->line_in.str(line); + self->line_in.clear(); + + // Read the next line + std::size_t weights_left = self->n_vertex_weights; + vertex_weight_type weight; + while (weights_left > 0) + { + if (self->line_in >> weight) + self->vertex_weights.push_back(weight); + else + boost::throw_exception(metis_input_exception()); + --weights_left; + } + + // Successive iterations will pick up edges for this vertex. + skip_initial_read = false; + } while (true); + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + metis_reader::edge_iterator::postincrement_proxy + metis_reader::edge_iterator::operator++(int) + { + postincrement_proxy result(**this); + ++(*this); + return result; + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + metis_reader::edge_iterator metis_reader::begin() + { + if (edge.first != 0) + start(); + return edge_iterator(this); + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + metis_reader::edge_iterator metis_reader::end() { return edge_iterator(0); } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + metis_reader::edge_weight_iterator metis_reader::weight_begin() + { + return edge_weight_iterator(this); + } + + BOOST_GRAPH_METIS_INLINE_KEYWORD + void metis_reader::start() + { + in.seekg(0, std::ios::beg); + std::string line; + while (getline(in, line) && !line.empty() && line[0] == '%') + { + /* Keep getting lines in loop header. */ + } + + if (!in || line.empty()) + boost::throw_exception(metis_input_exception()); + + // Determine number of vertices and edges in the graph + line_in.str(line); + if (!(line_in >> n_vertices >> n_edges)) + boost::throw_exception(metis_input_exception()); + + // Determine whether vertex or edge weights are included in the graph + int fmt = 0; + line_in >> fmt; + n_vertex_weights = fmt / 10; + edge_weights = (fmt % 10 == 1); + + // Determine how many (if any!) vertex weights are included + if (n_vertex_weights) + line_in >> n_vertex_weights; + + // Setup the iteration data structures + edge_weight = 1.0; + edge.first = 0; + edge.second = 0; + vertex_weights.reserve(n_vertex_weights * num_vertices()); + } + + metis_distribution::metis_distribution( + std::istream& in, process_id_type my_id) + : my_id(my_id) + , vertices(std::istream_iterator< process_id_type >(in), + std::istream_iterator< process_id_type >()) + { + } + + metis_distribution::size_type metis_distribution::block_size( + process_id_type id, size_type) const + { + return std::count(vertices.begin(), vertices.end(), id); + } + + metis_distribution::size_type metis_distribution::local(size_type n) const + { + return std::count(vertices.begin(), vertices.begin() + n, vertices[n]); + } + + metis_distribution::size_type metis_distribution::global( + process_id_type id, size_type n) const + { + std::vector< process_id_type >::const_iterator i = vertices.begin(); + while (*i != id) + ++i; + + while (n > 0) + { + do + { + ++i; + } while (*i != id); + --n; + } + + return i - vertices.begin(); + } + +#endif + +} +} // end namespace boost::graph + +#endif // BOOST_GRAPH_METIS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/metric_tsp_approx.hpp b/contrib/restricted/boost/graph/include/boost/graph/metric_tsp_approx.hpp new file mode 100644 index 0000000000..38eaf6fa61 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/metric_tsp_approx.hpp @@ -0,0 +1,316 @@ + +//======================================================================= +// Copyright 2008 +// Author: Matyas W Egyhazy +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_METRIC_TSP_APPROX_HPP +#define BOOST_GRAPH_METRIC_TSP_APPROX_HPP + +// metric_tsp_approx +// Generates an approximate tour solution for the traveling salesperson +// problem in polynomial time. The current algorithm guarantees a tour with a +// length at most as long as 2x optimal solution. The graph should have +// 'natural' (metric) weights such that the triangle inequality is maintained. +// Graphs must be fully interconnected. + +// TODO: +// There are a couple of improvements that could be made. +// 1) Change implementation to lower uppper bound Christofides heuristic +// 2) Implement a less restrictive TSP heuristic (one that does not rely on +// triangle inequality). +// 3) Determine if the algorithm can be implemented without creating a new +// graph. + +#include <vector> + +#include <boost/shared_ptr.hpp> +#include <boost/concept_check.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_as_tree.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/prim_minimum_spanning_tree.hpp> +#include <boost/graph/lookup_edge.hpp> +#include <boost/throw_exception.hpp> + +namespace boost +{ +// Define a concept for the concept-checking library. +template < typename Visitor, typename Graph > struct TSPVertexVisitorConcept +{ +private: + Visitor vis_; + +public: + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + BOOST_CONCEPT_USAGE(TSPVertexVisitorConcept) + { + Visitor vis(vis_); // require copy construction + Graph g(1); + Vertex v(*vertices(g).first); + vis.visit_vertex(v, g); // require visit_vertex + } +}; + +// Tree visitor that keeps track of a preorder traversal of a tree +// TODO: Consider migrating this to the graph_as_tree header. +// TODO: Parameterize the underlying stores so it doesn't have to be a vector. +template < typename Node, typename Tree > class PreorderTraverser +{ +private: + std::vector< Node >& path_; + +public: + typedef typename std::vector< Node >::const_iterator const_iterator; + + PreorderTraverser(std::vector< Node >& p) : path_(p) {} + + void preorder(Node n, const Tree&) { path_.push_back(n); } + + void inorder(Node, const Tree&) const {} + void postorder(Node, const Tree&) const {} + + const_iterator begin() const { return path_.begin(); } + const_iterator end() const { return path_.end(); } +}; + +// Forward declarations +template < typename > class tsp_tour_visitor; +template < typename, typename, typename, typename > class tsp_tour_len_visitor; + +template < typename VertexListGraph, typename OutputIterator > +void metric_tsp_approx_tour(VertexListGraph& g, OutputIterator o) +{ + metric_tsp_approx_from_vertex(g, *vertices(g).first, get(edge_weight, g), + get(vertex_index, g), tsp_tour_visitor< OutputIterator >(o)); +} + +template < typename VertexListGraph, typename WeightMap, + typename OutputIterator > +void metric_tsp_approx_tour(VertexListGraph& g, WeightMap w, OutputIterator o) +{ + metric_tsp_approx_from_vertex( + g, *vertices(g).first, w, tsp_tour_visitor< OutputIterator >(o)); +} + +template < typename VertexListGraph, typename OutputIterator > +void metric_tsp_approx_tour_from_vertex(VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor start, + OutputIterator o) +{ + metric_tsp_approx_from_vertex(g, start, get(edge_weight, g), + get(vertex_index, g), tsp_tour_visitor< OutputIterator >(o)); +} + +template < typename VertexListGraph, typename WeightMap, + typename OutputIterator > +void metric_tsp_approx_tour_from_vertex(VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor start, + WeightMap w, OutputIterator o) +{ + metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g), + tsp_tour_visitor< OutputIterator >(o)); +} + +template < typename VertexListGraph, typename TSPVertexVisitor > +void metric_tsp_approx(VertexListGraph& g, TSPVertexVisitor vis) +{ + metric_tsp_approx_from_vertex( + g, *vertices(g).first, get(edge_weight, g), get(vertex_index, g), vis); +} + +template < typename VertexListGraph, typename Weightmap, + typename VertexIndexMap, typename TSPVertexVisitor > +void metric_tsp_approx(VertexListGraph& g, Weightmap w, TSPVertexVisitor vis) +{ + metric_tsp_approx_from_vertex( + g, *vertices(g).first, w, get(vertex_index, g), vis); +} + +template < typename VertexListGraph, typename WeightMap, + typename VertexIndexMap, typename TSPVertexVisitor > +void metric_tsp_approx( + VertexListGraph& g, WeightMap w, VertexIndexMap id, TSPVertexVisitor vis) +{ + metric_tsp_approx_from_vertex(g, *vertices(g).first, w, id, vis); +} + +template < typename VertexListGraph, typename WeightMap, + typename TSPVertexVisitor > +void metric_tsp_approx_from_vertex(VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor start, + WeightMap w, TSPVertexVisitor vis) +{ + metric_tsp_approx_from_vertex(g, start, w, get(vertex_index, g), vis); +} + +template < typename VertexListGraph, typename WeightMap, + typename VertexIndexMap, typename TSPVertexVisitor > +void metric_tsp_approx_from_vertex(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor start, + WeightMap weightmap, VertexIndexMap indexmap, TSPVertexVisitor vis) +{ + using namespace boost; + using namespace std; + + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< VertexListGraph >)); + BOOST_CONCEPT_ASSERT( + (TSPVertexVisitorConcept< TSPVertexVisitor, VertexListGraph >)); + + // Types related to the input graph (GVertex is a template parameter). + typedef typename graph_traits< VertexListGraph >::vertex_descriptor GVertex; + typedef typename graph_traits< VertexListGraph >::vertex_iterator GVItr; + + // We build a custom graph in this algorithm. + typedef adjacency_list< vecS, vecS, directedS, no_property, no_property > + MSTImpl; + typedef graph_traits< MSTImpl >::vertex_descriptor Vertex; + typedef graph_traits< MSTImpl >::vertex_iterator VItr; + + // And then re-cast it as a tree. + typedef iterator_property_map< vector< Vertex >::iterator, + property_map< MSTImpl, vertex_index_t >::type > + ParentMap; + typedef graph_as_tree< MSTImpl, ParentMap > Tree; + typedef tree_traits< Tree >::node_descriptor Node; + + // A predecessor map. + typedef vector< GVertex > PredMap; + typedef iterator_property_map< typename PredMap::iterator, VertexIndexMap > + PredPMap; + + PredMap preds(num_vertices(g)); + PredPMap pred_pmap(preds.begin(), indexmap); + + // Compute a spanning tree over the in put g. + prim_minimum_spanning_tree(g, pred_pmap, + root_vertex(start).vertex_index_map(indexmap).weight_map(weightmap)); + + // Build a MST using the predecessor map from prim mst + MSTImpl mst(num_vertices(g)); + std::size_t cnt = 0; + pair< VItr, VItr > mst_verts(vertices(mst)); + for (typename PredMap::iterator vi(preds.begin()); vi != preds.end(); + ++vi, ++cnt) + { + if (indexmap[*vi] != cnt) + { + add_edge(*next(mst_verts.first, indexmap[*vi]), + *next(mst_verts.first, cnt), mst); + } + } + + // Build a tree abstraction over the MST. + vector< Vertex > parent(num_vertices(mst)); + Tree t(mst, *vertices(mst).first, + make_iterator_property_map(parent.begin(), get(vertex_index, mst))); + + // Create tour using a preorder traversal of the mst + vector< Node > tour; + PreorderTraverser< Node, Tree > tvis(tour); + traverse_tree(indexmap[start], t, tvis); + + pair< GVItr, GVItr > g_verts(vertices(g)); + for (PreorderTraverser< Node, Tree >::const_iterator curr(tvis.begin()); + curr != tvis.end(); ++curr) + { + // TODO: This is will be O(n^2) if vertex storage of g != vecS. + GVertex v = *next(g_verts.first, get(vertex_index, mst)[*curr]); + vis.visit_vertex(v, g); + } + + // Connect back to the start of the tour + vis.visit_vertex(start, g); +} + +// Default tsp tour visitor that puts the tour in an OutputIterator +template < typename OutItr > class tsp_tour_visitor +{ + OutItr itr_; + +public: + tsp_tour_visitor(OutItr itr) : itr_(itr) {} + + template < typename Vertex, typename Graph > + void visit_vertex(Vertex v, const Graph&) + { + BOOST_CONCEPT_ASSERT((OutputIterator< OutItr, Vertex >)); + *itr_++ = v; + } +}; + +// Tsp tour visitor that adds the total tour length. +template < typename Graph, typename WeightMap, typename OutIter, + typename Length > +class tsp_tour_len_visitor +{ + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + BOOST_CONCEPT_ASSERT((OutputIterator< OutIter, Vertex >)); + + OutIter iter_; + Length& tourlen_; + WeightMap& wmap_; + Vertex previous_; + + // Helper function for getting the null vertex. + Vertex null() { return graph_traits< Graph >::null_vertex(); } + +public: + tsp_tour_len_visitor(Graph const&, OutIter iter, Length& l, WeightMap& map) + : iter_(iter), tourlen_(l), wmap_(map), previous_(null()) + { + } + + void visit_vertex(Vertex v, const Graph& g) + { + typedef typename graph_traits< Graph >::edge_descriptor Edge; + + // If it is not the start, then there is a + // previous vertex + if (previous_ != null()) + { + // NOTE: For non-adjacency matrix graphs g, this bit of code + // will be linear in the degree of previous_ or v. A better + // solution would be to visit edges of the graph, but that + // would require revisiting the core algorithm. + Edge e; + bool found; + boost::tie(e, found) = lookup_edge(previous_, v, g); + if (!found) + { + BOOST_THROW_EXCEPTION(not_complete()); + } + + tourlen_ += wmap_[e]; + } + + previous_ = v; + *iter_++ = v; + } +}; + +// Object generator(s) +template < typename OutIter > +inline tsp_tour_visitor< OutIter > make_tsp_tour_visitor(OutIter iter) +{ + return tsp_tour_visitor< OutIter >(iter); +} + +template < typename Graph, typename WeightMap, typename OutIter, + typename Length > +inline tsp_tour_len_visitor< Graph, WeightMap, OutIter, Length > +make_tsp_tour_len_visitor( + Graph const& g, OutIter iter, Length& l, WeightMap map) +{ + return tsp_tour_len_visitor< Graph, WeightMap, OutIter, Length >( + g, iter, l, map); +} + +} // boost + +#endif // BOOST_GRAPH_METRIC_TSP_APPROX_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/minimum_degree_ordering.hpp b/contrib/restricted/boost/graph/include/boost/graph/minimum_degree_ordering.hpp new file mode 100644 index 0000000000..2630831f5e --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/minimum_degree_ordering.hpp @@ -0,0 +1,760 @@ +//-*-c++-*- +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Authors: Lie-Quan Lee, Jeremy Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP +#define BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP + +#include <vector> +#include <boost/assert.hpp> +#include <boost/config.hpp> +#include <boost/pending/bucket_sorter.hpp> +#include <boost/detail/numeric_traits.hpp> // for integer_traits +#include <boost/graph/graph_traits.hpp> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +namespace detail +{ + + // + // Given a set of n integers (where the integer values range from + // zero to n-1), we want to keep track of a collection of stacks + // of integers. It so happens that an integer will appear in at + // most one stack at a time, so the stacks form disjoint sets. + // Because of these restrictions, we can use one big array to + // store all the stacks, intertwined with one another. + // No allocation/deallocation happens in the push()/pop() methods + // so this is faster than using std::stack's. + // + template < class SignedInteger > class Stacks + { + typedef SignedInteger value_type; + typedef typename std::vector< value_type >::size_type size_type; + + public: + Stacks(size_type n) : data(n) {} + + //: stack + class stack + { + typedef typename std::vector< value_type >::iterator Iterator; + + public: + stack(Iterator _data, const value_type& head) + : data(_data), current(head) + { + } + + // did not use default argument here to avoid internal compiler + // error in g++. + stack(Iterator _data) + : data(_data), current(-(std::numeric_limits< value_type >::max)()) + { + } + + void pop() + { + BOOST_ASSERT(!empty()); + current = data[current]; + } + void push(value_type v) + { + data[v] = current; + current = v; + } + bool empty() + { + return current == -(std::numeric_limits< value_type >::max)(); + } + value_type& top() { return current; } + + private: + Iterator data; + value_type current; + }; + + // To return a stack object + stack make_stack() { return stack(data.begin()); } + + protected: + std::vector< value_type > data; + }; + + // marker class, a generalization of coloring. + // + // This class is to provide a generalization of coloring which has + // complexity of amortized constant time to set all vertices' color + // back to be untagged. It implemented by increasing a tag. + // + // The colors are: + // not tagged + // tagged + // multiple_tagged + // done + // + template < class SignedInteger, class Vertex, class VertexIndexMap > + class Marker + { + typedef SignedInteger value_type; + typedef typename std::vector< value_type >::size_type size_type; + + static value_type done() + { + return (std::numeric_limits< value_type >::max)() / 2; + } + + public: + Marker(size_type _num, VertexIndexMap index_map) + : tag(1 - (std::numeric_limits< value_type >::max)()) + , data(_num, -(std::numeric_limits< value_type >::max)()) + , id(index_map) + { + } + + void mark_done(Vertex node) { data[get(id, node)] = done(); } + + bool is_done(Vertex node) { return data[get(id, node)] == done(); } + + void mark_tagged(Vertex node) { data[get(id, node)] = tag; } + + void mark_multiple_tagged(Vertex node) + { + data[get(id, node)] = multiple_tag; + } + + bool is_tagged(Vertex node) const { return data[get(id, node)] >= tag; } + + bool is_not_tagged(Vertex node) const + { + return data[get(id, node)] < tag; + } + + bool is_multiple_tagged(Vertex node) const + { + return data[get(id, node)] >= multiple_tag; + } + + void increment_tag() + { + const size_type num = data.size(); + ++tag; + if (tag >= done()) + { + tag = 1 - (std::numeric_limits< value_type >::max)(); + for (size_type i = 0; i < num; ++i) + if (data[i] < done()) + data[i] = -(std::numeric_limits< value_type >::max)(); + } + } + + void set_multiple_tag(value_type mdeg0) + { + const size_type num = data.size(); + multiple_tag = tag + mdeg0; + + if (multiple_tag >= done()) + { + tag = 1 - (std::numeric_limits< value_type >::max)(); + + for (size_type i = 0; i < num; i++) + if (data[i] < done()) + data[i] = -(std::numeric_limits< value_type >::max)(); + + multiple_tag = tag + mdeg0; + } + } + + void set_tag_as_multiple_tag() { tag = multiple_tag; } + + protected: + value_type tag; + value_type multiple_tag; + std::vector< value_type > data; + VertexIndexMap id; + }; + + template < class Iterator, class SignedInteger, class Vertex, + class VertexIndexMap, int offset = 1 > + class Numbering + { + typedef SignedInteger number_type; + number_type num; // start from 1 instead of zero + Iterator data; + number_type max_num; + VertexIndexMap id; + + public: + Numbering(Iterator _data, number_type _max_num, VertexIndexMap id) + : num(1), data(_data), max_num(_max_num), id(id) + { + } + void operator()(Vertex node) { data[get(id, node)] = -num; } + bool all_done(number_type i = 0) const { return num + i > max_num; } + void increment(number_type i = 1) { num += i; } + bool is_numbered(Vertex node) const { return data[get(id, node)] < 0; } + void indistinguishable(Vertex i, Vertex j) + { + data[get(id, i)] = -(get(id, j) + offset); + } + }; + + template < class SignedInteger, class Vertex, class VertexIndexMap > + class degreelists_marker + { + public: + typedef SignedInteger value_type; + typedef typename std::vector< value_type >::size_type size_type; + degreelists_marker(size_type n, VertexIndexMap id) : marks(n, 0), id(id) + { + } + void mark_need_update(Vertex i) { marks[get(id, i)] = 1; } + bool need_update(Vertex i) { return marks[get(id, i)] == 1; } + bool outmatched_or_done(Vertex i) { return marks[get(id, i)] == -1; } + void mark(Vertex i) { marks[get(id, i)] = -1; } + void unmark(Vertex i) { marks[get(id, i)] = 0; } + + private: + std::vector< value_type > marks; + VertexIndexMap id; + }; + + // Helper function object for edge removal + template < class Graph, class MarkerP, class NumberD, class Stack, + class VertexIndexMap > + class predicateRemoveEdge1 + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + + public: + predicateRemoveEdge1(Graph& _g, MarkerP& _marker, NumberD _numbering, + Stack& n_e, VertexIndexMap id) + : g(&_g) + , marker(&_marker) + , numbering(_numbering) + , neighbor_elements(&n_e) + , id(id) + { + } + + bool operator()(edge_t e) + { + vertex_t dist = target(e, *g); + if (marker->is_tagged(dist)) + return true; + marker->mark_tagged(dist); + if (numbering.is_numbered(dist)) + { + neighbor_elements->push(get(id, dist)); + return true; + } + return false; + } + + private: + Graph* g; + MarkerP* marker; + NumberD numbering; + Stack* neighbor_elements; + VertexIndexMap id; + }; + + // Helper function object for edge removal + template < class Graph, class MarkerP > class predicate_remove_tagged_edges + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + + public: + predicate_remove_tagged_edges(Graph& _g, MarkerP& _marker) + : g(&_g), marker(&_marker) + { + } + + bool operator()(edge_t e) + { + vertex_t dist = target(e, *g); + if (marker->is_tagged(dist)) + return true; + return false; + } + + private: + Graph* g; + MarkerP* marker; + }; + + template < class Graph, class DegreeMap, class InversePermutationMap, + class PermutationMap, class SuperNodeMap, class VertexIndexMap > + class mmd_impl + { + // Typedefs + typedef graph_traits< Graph > Traits; + typedef typename Traits::vertices_size_type size_type; + typedef typename detail::integer_traits< size_type >::difference_type + diff_t; + typedef typename Traits::vertex_descriptor vertex_t; + typedef typename Traits::adjacency_iterator adj_iter; + typedef iterator_property_map< vertex_t*, identity_property_map, + vertex_t, vertex_t& > + IndexVertexMap; + typedef detail::Stacks< diff_t > Workspace; + typedef bucket_sorter< size_type, vertex_t, DegreeMap, VertexIndexMap > + DegreeLists; + typedef Numbering< InversePermutationMap, diff_t, vertex_t, + VertexIndexMap > + NumberingD; + typedef degreelists_marker< diff_t, vertex_t, VertexIndexMap > + DegreeListsMarker; + typedef Marker< diff_t, vertex_t, VertexIndexMap > MarkerP; + + // Data Members + bool has_no_edges; + + // input parameters + Graph& G; + int delta; + DegreeMap degree; + InversePermutationMap inverse_perm; + PermutationMap perm; + SuperNodeMap supernode_size; + VertexIndexMap vertex_index_map; + + // internal data-structures + std::vector< vertex_t > index_vertex_vec; + size_type n; + IndexVertexMap index_vertex_map; + DegreeLists degreelists; + NumberingD numbering; + DegreeListsMarker degree_lists_marker; + MarkerP marker; + Workspace work_space; + + public: + mmd_impl(Graph& g, size_type n_, int delta, DegreeMap degree, + InversePermutationMap inverse_perm, PermutationMap perm, + SuperNodeMap supernode_size, VertexIndexMap id) + : has_no_edges(true) + , G(g) + , delta(delta) + , degree(degree) + , inverse_perm(inverse_perm) + , perm(perm) + , supernode_size(supernode_size) + , vertex_index_map(id) + , index_vertex_vec(n_) + , n(n_) + , degreelists(n_ + 1, n_, degree, id) + , numbering(inverse_perm, n_, vertex_index_map) + , degree_lists_marker(n_, vertex_index_map) + , marker(n_, vertex_index_map) + , work_space(n_) + { + typename graph_traits< Graph >::vertex_iterator v, vend; + size_type vid = 0; + for (boost::tie(v, vend) = vertices(G); v != vend; ++v, ++vid) + index_vertex_vec[vid] = *v; + index_vertex_map = IndexVertexMap(&index_vertex_vec[0]); + + // Initialize degreelists. Degreelists organizes the nodes + // according to their degree. + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) + { + typename Traits::degree_size_type d = out_degree(*v, G); + put(degree, *v, d); + if (0 < d) + has_no_edges = false; + degreelists.push(*v); + } + } + + void do_mmd() + { + // Eliminate the isolated nodes -- these are simply the nodes + // with no neighbors, which are accessible as a list (really, a + // stack) at location 0. Since these don't affect any other + // nodes, we can eliminate them without doing degree updates. + typename DegreeLists::stack list_isolated = degreelists[0]; + while (!list_isolated.empty()) + { + vertex_t node = list_isolated.top(); + marker.mark_done(node); + numbering(node); + numbering.increment(); + list_isolated.pop(); + } + + if (has_no_edges) + { + return; + } + + size_type min_degree = 1; + typename DegreeLists::stack list_min_degree + = degreelists[min_degree]; + + while (list_min_degree.empty()) + { + ++min_degree; + list_min_degree = degreelists[min_degree]; + } + + // check if the whole eliminating process is done + while (!numbering.all_done()) + { + + size_type min_degree_limit = min_degree + delta; // WARNING + typename Workspace::stack llist = work_space.make_stack(); + + // multiple elimination + while (delta >= 0) + { + + // Find the next non-empty degree + for (list_min_degree = degreelists[min_degree]; + list_min_degree.empty() + && min_degree <= min_degree_limit; + ++min_degree, + list_min_degree = degreelists[min_degree]) + ; + if (min_degree > min_degree_limit) + break; + + const vertex_t node = list_min_degree.top(); + const size_type node_id = get(vertex_index_map, node); + list_min_degree.pop(); + numbering(node); + + // check if node is the last one + if (numbering.all_done(supernode_size[node])) + { + numbering.increment(supernode_size[node]); + break; + } + marker.increment_tag(); + marker.mark_tagged(node); + + this->eliminate(node); + + numbering.increment(supernode_size[node]); + llist.push(node_id); + } // multiple elimination + + if (numbering.all_done()) + break; + + this->update(llist, min_degree); + } + + } // do_mmd() + + void eliminate(vertex_t node) + { + typename Workspace::stack element_neighbor + = work_space.make_stack(); + + // Create two function objects for edge removal + typedef typename Workspace::stack WorkStack; + predicateRemoveEdge1< Graph, MarkerP, NumberingD, WorkStack, + VertexIndexMap > + p(G, marker, numbering, element_neighbor, vertex_index_map); + + predicate_remove_tagged_edges< Graph, MarkerP > p2(G, marker); + + // Reconstruct the adjacent node list, push element neighbor in a + // List. + remove_out_edge_if(node, p, G); + // during removal element neighbors are collected. + + while (!element_neighbor.empty()) + { + // element absorb + size_type e_id = element_neighbor.top(); + vertex_t element = get(index_vertex_map, e_id); + adj_iter i, i_end; + for (boost::tie(i, i_end) = adjacent_vertices(element, G); + i != i_end; ++i) + { + vertex_t i_node = *i; + if (!marker.is_tagged(i_node) + && !numbering.is_numbered(i_node)) + { + marker.mark_tagged(i_node); + add_edge(node, i_node, G); + } + } + element_neighbor.pop(); + } + adj_iter v, ve; + for (boost::tie(v, ve) = adjacent_vertices(node, G); v != ve; ++v) + { + vertex_t v_node = *v; + if (!degree_lists_marker.need_update(v_node) + && !degree_lists_marker.outmatched_or_done(v_node)) + { + degreelists.remove(v_node); + } + // update out edges of v_node + remove_out_edge_if(v_node, p2, G); + + if (out_degree(v_node, G) == 0) + { // indistinguishable nodes + supernode_size[node] += supernode_size[v_node]; + supernode_size[v_node] = 0; + numbering.indistinguishable(v_node, node); + marker.mark_done(v_node); + degree_lists_marker.mark(v_node); + } + else + { // not indistinguishable nodes + add_edge(v_node, node, G); + degree_lists_marker.mark_need_update(v_node); + } + } + } // eliminate() + + template < class Stack > void update(Stack llist, size_type& min_degree) + { + size_type min_degree0 = min_degree + delta + 1; + + while (!llist.empty()) + { + size_type deg, deg0 = 0; + + marker.set_multiple_tag(min_degree0); + typename Workspace::stack q2list = work_space.make_stack(); + typename Workspace::stack qxlist = work_space.make_stack(); + + vertex_t current = get(index_vertex_map, llist.top()); + adj_iter i, ie; + for (boost::tie(i, ie) = adjacent_vertices(current, G); i != ie; + ++i) + { + vertex_t i_node = *i; + const size_type i_id = get(vertex_index_map, i_node); + if (supernode_size[i_node] != 0) + { + deg0 += supernode_size[i_node]; + marker.mark_multiple_tagged(i_node); + if (degree_lists_marker.need_update(i_node)) + { + if (out_degree(i_node, G) == 2) + q2list.push(i_id); + else + qxlist.push(i_id); + } + } + } + + while (!q2list.empty()) + { + const size_type u_id = q2list.top(); + vertex_t u_node = get(index_vertex_map, u_id); + // if u_id is outmatched by others, no need to update degree + if (degree_lists_marker.outmatched_or_done(u_node)) + { + q2list.pop(); + continue; + } + marker.increment_tag(); + deg = deg0; + + adj_iter nu = adjacent_vertices(u_node, G).first; + vertex_t neighbor = *nu; + if (neighbor == u_node) + { + ++nu; + neighbor = *nu; + } + if (numbering.is_numbered(neighbor)) + { + adj_iter i, ie; + for (boost::tie(i, ie) = adjacent_vertices(neighbor, G); + i != ie; ++i) + { + const vertex_t i_node = *i; + if (i_node == u_node || supernode_size[i_node] == 0) + continue; + if (marker.is_tagged(i_node)) + { + if (degree_lists_marker.need_update(i_node)) + { + if (out_degree(i_node, G) == 2) + { // is indistinguishable + supernode_size[u_node] + += supernode_size[i_node]; + supernode_size[i_node] = 0; + numbering.indistinguishable( + i_node, u_node); + marker.mark_done(i_node); + degree_lists_marker.mark(i_node); + } + else // is outmatched + degree_lists_marker.mark(i_node); + } + } + else + { + marker.mark_tagged(i_node); + deg += supernode_size[i_node]; + } + } + } + else + deg += supernode_size[neighbor]; + + deg -= supernode_size[u_node]; + degree[u_node] = deg; // update degree + degreelists[deg].push(u_node); + // u_id has been pushed back into degreelists + degree_lists_marker.unmark(u_node); + if (min_degree > deg) + min_degree = deg; + q2list.pop(); + } // while (!q2list.empty()) + + while (!qxlist.empty()) + { + const size_type u_id = qxlist.top(); + const vertex_t u_node = get(index_vertex_map, u_id); + + // if u_id is outmatched by others, no need to update degree + if (degree_lists_marker.outmatched_or_done(u_node)) + { + qxlist.pop(); + continue; + } + marker.increment_tag(); + deg = deg0; + adj_iter i, ie; + for (boost::tie(i, ie) = adjacent_vertices(u_node, G); + i != ie; ++i) + { + vertex_t i_node = *i; + if (marker.is_tagged(i_node)) + continue; + marker.mark_tagged(i_node); + + if (numbering.is_numbered(i_node)) + { + adj_iter j, je; + for (boost::tie(j, je) + = adjacent_vertices(i_node, G); + j != je; ++j) + { + const vertex_t j_node = *j; + if (marker.is_not_tagged(j_node)) + { + marker.mark_tagged(j_node); + deg += supernode_size[j_node]; + } + } + } + else + deg += supernode_size[i_node]; + } // for adjacent vertices of u_node + deg -= supernode_size[u_node]; + degree[u_node] = deg; + degreelists[deg].push(u_node); + // u_id has been pushed back into degreelists + degree_lists_marker.unmark(u_node); + if (min_degree > deg) + min_degree = deg; + qxlist.pop(); + } // while (!qxlist.empty()) { + + marker.set_tag_as_multiple_tag(); + llist.pop(); + } // while (! llist.empty()) + + } // update() + + void build_permutation(InversePermutationMap next, PermutationMap prev) + { + // collect the permutation info + size_type i; + for (i = 0; i < n; ++i) + { + diff_t size = supernode_size[get(index_vertex_map, i)]; + if (size <= 0) + { + prev[i] = next[i]; + supernode_size[get(index_vertex_map, i)] + = next[i] + 1; // record the supernode info + } + else + prev[i] = -next[i]; + } + for (i = 1; i < n + 1; ++i) + { + if (prev[i - 1] > 0) + continue; + diff_t parent = i; + while (prev[parent - 1] < 0) + { + parent = -prev[parent - 1]; + } + + diff_t root = parent; + diff_t num = prev[root - 1] + 1; + next[i - 1] = -num; + prev[root - 1] = num; + + parent = i; + diff_t next_node = -prev[parent - 1]; + while (next_node > 0) + { + prev[parent - 1] = -root; + parent = next_node; + next_node = -prev[parent - 1]; + } + } + for (i = 0; i < n; i++) + { + diff_t num = -next[i] - 1; + next[i] = num; + prev[num] = i; + } + } // build_permutation() + }; + +} // namespace detail + +// MMD algorithm +// +// The implementation presently includes the enhancements for mass +// elimination, incomplete degree update, multiple elimination, and +// external degree. +// +// Important Note: This implementation requires the BGL graph to be +// directed. Therefore, nonzero entry (i, j) in a symmetrical matrix +// A coresponds to two directed edges (i->j and j->i). +// +// see Alan George and Joseph W. H. Liu, The Evolution of the Minimum +// Degree Ordering Algorithm, SIAM Review, 31, 1989, Page 1-19 +template < class Graph, class DegreeMap, class InversePermutationMap, + class PermutationMap, class SuperNodeMap, class VertexIndexMap > +void minimum_degree_ordering(Graph& G, DegreeMap degree, + InversePermutationMap inverse_perm, PermutationMap perm, + SuperNodeMap supernode_size, int delta, VertexIndexMap vertex_index_map) +{ + detail::mmd_impl< Graph, DegreeMap, InversePermutationMap, PermutationMap, + SuperNodeMap, VertexIndexMap > + impl(G, num_vertices(G), delta, degree, inverse_perm, perm, + supernode_size, vertex_index_map); + impl.do_mmd(); + impl.build_permutation(inverse_perm, perm); +} + +} // namespace boost + +#endif // BOOST_GRAPH_MINIMUM_DEGREE_ORDERING_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/neighbor_bfs.hpp b/contrib/restricted/boost/graph/include/boost/graph/neighbor_bfs.hpp new file mode 100644 index 0000000000..bfe87a998b --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/neighbor_bfs.hpp @@ -0,0 +1,326 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP +#define BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP + +/* + Neighbor Breadth First Search + Like BFS, but traverses in-edges as well as out-edges. + (for directed graphs only. use normal BFS for undirected graphs) +*/ +#include <boost/config.hpp> +#include <boost/ref.hpp> +#include <vector> +#include <boost/pending/queue.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/visitors.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +template < class Visitor, class Graph > struct NeighborBFSVisitorConcept +{ + void constraints() + { + BOOST_CONCEPT_ASSERT((CopyConstructibleConcept< Visitor >)); + vis.initialize_vertex(u, g); + vis.discover_vertex(u, g); + vis.examine_vertex(u, g); + vis.examine_out_edge(e, g); + vis.examine_in_edge(e, g); + vis.tree_out_edge(e, g); + vis.tree_in_edge(e, g); + vis.non_tree_out_edge(e, g); + vis.non_tree_in_edge(e, g); + vis.gray_target(e, g); + vis.black_target(e, g); + vis.gray_source(e, g); + vis.black_source(e, g); + vis.finish_vertex(u, g); + } + Visitor vis; + Graph g; + typename graph_traits< Graph >::vertex_descriptor u; + typename graph_traits< Graph >::edge_descriptor e; +}; + +template < class Visitors = null_visitor > class neighbor_bfs_visitor +{ +public: + neighbor_bfs_visitor(Visitors vis = Visitors()) : m_vis(vis) {} + + template < class Vertex, class Graph > + void initialize_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_initialize_vertex()); + } + template < class Vertex, class Graph > + void discover_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_discover_vertex()); + } + template < class Vertex, class Graph > + void examine_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_examine_vertex()); + } + template < class Edge, class Graph > void examine_out_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_examine_edge()); + } + template < class Edge, class Graph > void tree_out_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_tree_edge()); + } + template < class Edge, class Graph > + void non_tree_out_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_non_tree_edge()); + } + template < class Edge, class Graph > void gray_target(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_gray_target()); + } + template < class Edge, class Graph > void black_target(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_black_target()); + } + template < class Edge, class Graph > void examine_in_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_examine_edge()); + } + template < class Edge, class Graph > void tree_in_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_tree_edge()); + } + template < class Edge, class Graph > void non_tree_in_edge(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_non_tree_edge()); + } + template < class Edge, class Graph > void gray_source(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_gray_target()); + } + template < class Edge, class Graph > void black_source(Edge e, Graph& g) + { + invoke_visitors(m_vis, e, g, on_black_target()); + } + template < class Vertex, class Graph > + void finish_vertex(Vertex u, Graph& g) + { + invoke_visitors(m_vis, u, g, on_finish_vertex()); + } + +protected: + Visitors m_vis; +}; + +template < class Visitors > +neighbor_bfs_visitor< Visitors > make_neighbor_bfs_visitor(Visitors vis) +{ + return neighbor_bfs_visitor< Visitors >(vis); +} + +namespace detail +{ + + template < class BidirectionalGraph, class Buffer, class BFSVisitor, + class ColorMap > + void neighbor_bfs_impl(const BidirectionalGraph& g, + typename graph_traits< BidirectionalGraph >::vertex_descriptor s, + Buffer& Q, BFSVisitor vis, ColorMap color) + + { + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< BidirectionalGraph >)); + typedef graph_traits< BidirectionalGraph > GTraits; + typedef typename GTraits::vertex_descriptor Vertex; + typedef typename GTraits::edge_descriptor Edge; + BOOST_CONCEPT_ASSERT( + (NeighborBFSVisitorConcept< BFSVisitor, BidirectionalGraph >)); + BOOST_CONCEPT_ASSERT((ReadWritePropertyMapConcept< ColorMap, Vertex >)); + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + + put(color, s, Color::gray()); + vis.discover_vertex(s, g); + Q.push(s); + while (!Q.empty()) + { + Vertex u = Q.top(); + Q.pop(); // pop before push to avoid problem if Q is priority_queue. + vis.examine_vertex(u, g); + + typename GTraits::out_edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) + { + Edge e = *ei; + vis.examine_out_edge(e, g); + Vertex v = target(e, g); + ColorValue v_color = get(color, v); + if (v_color == Color::white()) + { + vis.tree_out_edge(e, g); + put(color, v, Color::gray()); + vis.discover_vertex(v, g); + Q.push(v); + } + else + { + vis.non_tree_out_edge(e, g); + if (v_color == Color::gray()) + vis.gray_target(e, g); + else + vis.black_target(e, g); + } + } // for out-edges + + typename GTraits::in_edge_iterator in_ei, in_ei_end; + for (boost::tie(in_ei, in_ei_end) = in_edges(u, g); + in_ei != in_ei_end; ++in_ei) + { + Edge e = *in_ei; + vis.examine_in_edge(e, g); + Vertex v = source(e, g); + ColorValue v_color = get(color, v); + if (v_color == Color::white()) + { + vis.tree_in_edge(e, g); + put(color, v, Color::gray()); + vis.discover_vertex(v, g); + Q.push(v); + } + else + { + vis.non_tree_in_edge(e, g); + if (v_color == Color::gray()) + vis.gray_source(e, g); + else + vis.black_source(e, g); + } + } // for in-edges + + put(color, u, Color::black()); + vis.finish_vertex(u, g); + } // while + } + + template < class VertexListGraph, class ColorMap, class BFSVisitor, class P, + class T, class R > + void neighbor_bfs_helper(VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + ColorMap color, BFSVisitor vis, + const bgl_named_params< P, T, R >& params) + { + typedef graph_traits< VertexListGraph > Traits; + // Buffer default + typedef typename Traits::vertex_descriptor Vertex; + typedef boost::queue< Vertex > queue_t; + queue_t Q; + // Initialization + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + typename boost::graph_traits< VertexListGraph >::vertex_iterator i, + i_end; + for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i) + { + put(color, *i, Color::white()); + vis.initialize_vertex(*i, g); + } + neighbor_bfs_impl(g, s, + choose_param(get_param(params, buffer_param_t()), boost::ref(Q)) + .get(), + vis, color); + } + + //------------------------------------------------------------------------- + // Choose between default color and color parameters. Using + // function dispatching so that we don't require vertex index if + // the color default is not being used. + + template < class ColorMap > struct neighbor_bfs_dispatch + { + template < class VertexListGraph, class P, class T, class R > + static void apply(VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + const bgl_named_params< P, T, R >& params, ColorMap color) + { + neighbor_bfs_helper(g, s, color, + choose_param(get_param(params, graph_visitor), + make_neighbor_bfs_visitor(null_visitor())), + params); + } + }; + + template <> struct neighbor_bfs_dispatch< param_not_found > + { + template < class VertexListGraph, class P, class T, class R > + static void apply(VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + const bgl_named_params< P, T, R >& params, param_not_found) + { + std::vector< default_color_type > color_vec(num_vertices(g)); + null_visitor null_vis; + + neighbor_bfs_helper(g, s, + make_iterator_property_map(color_vec.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index), + color_vec[0]), + choose_param(get_param(params, graph_visitor), + make_neighbor_bfs_visitor(null_vis)), + params); + } + }; + +} // namespace detail + +// Named Parameter Variant +template < class VertexListGraph, class P, class T, class R > +void neighbor_breadth_first_search(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + const bgl_named_params< P, T, R >& params) +{ + // The graph is passed by *const* reference so that graph adaptors + // (temporaries) can be passed into this function. However, the + // graph is not really const since we may write to property maps + // of the graph. + VertexListGraph& ng = const_cast< VertexListGraph& >(g); + typedef typename get_param_type< vertex_color_t, + bgl_named_params< P, T, R > >::type C; + detail::neighbor_bfs_dispatch< C >::apply( + ng, s, params, get_param(params, vertex_color)); +} + +// This version does not initialize colors, user has to. + +template < class IncidenceGraph, class P, class T, class R > +void neighbor_breadth_first_visit(IncidenceGraph& g, + typename graph_traits< IncidenceGraph >::vertex_descriptor s, + const bgl_named_params< P, T, R >& params) +{ + typedef graph_traits< IncidenceGraph > Traits; + // Buffer default + typedef boost::queue< typename Traits::vertex_descriptor > queue_t; + queue_t Q; + + detail::neighbor_bfs_impl(g, s, + choose_param(get_param(params, buffer_param_t()), boost::ref(Q)).get(), + choose_param(get_param(params, graph_visitor), + make_neighbor_bfs_visitor(null_visitor())), + choose_pmap(get_param(params, vertex_color), g, vertex_color)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_NEIGHBOR_BREADTH_FIRST_SEARCH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/one_bit_color_map.hpp b/contrib/restricted/boost/graph/include/boost/graph/one_bit_color_map.hpp new file mode 100644 index 0000000000..b11f16f684 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/one_bit_color_map.hpp @@ -0,0 +1,104 @@ +// Copyright (C) 2005-2010 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine + +// One bit per color property map (gray and black are the same, green is not +// supported) + +#ifndef BOOST_ONE_BIT_COLOR_MAP_HPP +#define BOOST_ONE_BIT_COLOR_MAP_HPP + +#include <boost/property_map/property_map.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/detail/mpi_include.hpp> +#include <boost/shared_array.hpp> +#include <boost/config.hpp> +#include <boost/assert.hpp> +#include <algorithm> +#include <limits> + +namespace boost +{ + +enum one_bit_color_type +{ + one_bit_white = 0, + one_bit_not_white = 1 +}; + +template <> struct color_traits< one_bit_color_type > +{ + static one_bit_color_type white() { return one_bit_white; } + static one_bit_color_type gray() { return one_bit_not_white; } + static one_bit_color_type black() { return one_bit_not_white; } +}; + +template < typename IndexMap = identity_property_map > struct one_bit_color_map +{ + BOOST_STATIC_CONSTANT( + int, bits_per_char = std::numeric_limits< unsigned char >::digits); + std::size_t n; + IndexMap index; + shared_array< unsigned char > data; + + typedef typename property_traits< IndexMap >::key_type key_type; + typedef one_bit_color_type value_type; + typedef void reference; + typedef read_write_property_map_tag category; + + explicit one_bit_color_map( + std::size_t n, const IndexMap& index = IndexMap()) + : n(n) + , index(index) + , data(new unsigned char[(n + bits_per_char - 1) / bits_per_char]()) + { + } +}; + +template < typename IndexMap > +inline one_bit_color_type get(const one_bit_color_map< IndexMap >& pm, + typename property_traits< IndexMap >::key_type key) +{ + BOOST_STATIC_CONSTANT( + int, bits_per_char = one_bit_color_map< IndexMap >::bits_per_char); + typename property_traits< IndexMap >::value_type i = get(pm.index, key); + BOOST_ASSERT((std::size_t)i < pm.n); + return one_bit_color_type( + (pm.data.get()[i / bits_per_char] >> (i % bits_per_char)) & 1); +} + +template < typename IndexMap > +inline void put(const one_bit_color_map< IndexMap >& pm, + typename property_traits< IndexMap >::key_type key, + one_bit_color_type value) +{ + BOOST_STATIC_CONSTANT( + int, bits_per_char = one_bit_color_map< IndexMap >::bits_per_char); + typename property_traits< IndexMap >::value_type i = get(pm.index, key); + BOOST_ASSERT((std::size_t)i < pm.n); + BOOST_ASSERT(value >= 0 && value < 2); + std::size_t byte_num = i / bits_per_char; + std::size_t bit_position = (i % bits_per_char); + pm.data.get()[byte_num] + = (unsigned char)((pm.data.get()[byte_num] & ~(1 << bit_position)) + | (value << bit_position)); +} + +template < typename IndexMap > +inline one_bit_color_map< IndexMap > make_one_bit_color_map( + std::size_t n, const IndexMap& index_map) +{ + return one_bit_color_map< IndexMap >(n, index_map); +} + +} // end namespace boost + + + +#endif // BOOST_ONE_BIT_COLOR_MAP_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/page_rank.hpp b/contrib/restricted/boost/graph/include/boost/graph/page_rank.hpp new file mode 100644 index 0000000000..94ae0f3409 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/page_rank.hpp @@ -0,0 +1,179 @@ +// Copyright 2004-5 The Trustees of Indiana University. +// Copyright 2002 Brad King and Douglas Gregor + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +#ifndef BOOST_GRAPH_PAGE_RANK_HPP +#define BOOST_GRAPH_PAGE_RANK_HPP + +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/overloading.hpp> +#include <boost/graph/detail/mpi_include.hpp> +#include <vector> + +namespace boost +{ +namespace graph +{ + + struct n_iterations + { + explicit n_iterations(std::size_t n) : n(n) {} + + template < typename RankMap, typename Graph > + bool operator()(const RankMap&, const Graph&) + { + return n-- == 0; + } + + private: + std::size_t n; + }; + + namespace detail + { + template < typename Graph, typename RankMap, typename RankMap2 > + void page_rank_step(const Graph& g, RankMap from_rank, RankMap2 to_rank, + typename property_traits< RankMap >::value_type damping, + incidence_graph_tag) + { + typedef typename property_traits< RankMap >::value_type rank_type; + + // Set new rank maps + BGL_FORALL_VERTICES_T(v, g, Graph) + put(to_rank, v, rank_type(1 - damping)); + + BGL_FORALL_VERTICES_T(u, g, Graph) + { + rank_type u_rank_out + = damping * get(from_rank, u) / out_degree(u, g); + BGL_FORALL_ADJ_T(u, v, g, Graph) + put(to_rank, v, get(to_rank, v) + u_rank_out); + } + } + + template < typename Graph, typename RankMap, typename RankMap2 > + void page_rank_step(const Graph& g, RankMap from_rank, RankMap2 to_rank, + typename property_traits< RankMap >::value_type damping, + bidirectional_graph_tag) + { + typedef + typename property_traits< RankMap >::value_type damping_type; + BGL_FORALL_VERTICES_T(v, g, Graph) + { + typename property_traits< RankMap >::value_type rank(0); + BGL_FORALL_INEDGES_T(v, e, g, Graph) + rank += get(from_rank, source(e, g)) + / out_degree(source(e, g), g); + put(to_rank, v, (damping_type(1) - damping) + damping * rank); + } + } + } // end namespace detail + + template < typename Graph, typename RankMap, typename Done, + typename RankMap2 > + void page_rank(const Graph& g, RankMap rank_map, Done done, + typename property_traits< RankMap >::value_type damping, + typename graph_traits< Graph >::vertices_size_type n, + RankMap2 rank_map2 BOOST_GRAPH_ENABLE_IF_MODELS_PARM( + Graph, vertex_list_graph_tag)) + { + typedef typename property_traits< RankMap >::value_type rank_type; + + rank_type initial_rank = rank_type(rank_type(1) / n); + BGL_FORALL_VERTICES_T(v, g, Graph) put(rank_map, v, initial_rank); + + bool to_map_2 = true; + while ((to_map_2 && !done(rank_map, g)) + || (!to_map_2 && !done(rank_map2, g))) + { + typedef typename graph_traits< Graph >::traversal_category category; + + if (to_map_2) + { + detail::page_rank_step( + g, rank_map, rank_map2, damping, category()); + } + else + { + detail::page_rank_step( + g, rank_map2, rank_map, damping, category()); + } + to_map_2 = !to_map_2; + } + + if (!to_map_2) + { + BGL_FORALL_VERTICES_T(v, g, Graph) + put(rank_map, v, get(rank_map2, v)); + } + } + + template < typename Graph, typename RankMap, typename Done > + void page_rank(const Graph& g, RankMap rank_map, Done done, + typename property_traits< RankMap >::value_type damping, + typename graph_traits< Graph >::vertices_size_type n) + { + typedef typename property_traits< RankMap >::value_type rank_type; + + std::vector< rank_type > ranks2(num_vertices(g)); + page_rank(g, rank_map, done, damping, n, + make_iterator_property_map(ranks2.begin(), get(vertex_index, g))); + } + + template < typename Graph, typename RankMap, typename Done > + inline void page_rank(const Graph& g, RankMap rank_map, Done done, + typename property_traits< RankMap >::value_type damping = 0.85) + { + page_rank(g, rank_map, done, damping, num_vertices(g)); + } + + template < typename Graph, typename RankMap > + inline void page_rank(const Graph& g, RankMap rank_map) + { + page_rank(g, rank_map, n_iterations(20)); + } + + // TBD: this could be _much_ more efficient, using a queue to store + // the vertices that should be reprocessed and keeping track of which + // vertices are in the queue with a property map. Baah, this only + // applies when we have a bidirectional graph. + template < typename MutableGraph > + void remove_dangling_links( + MutableGraph& g BOOST_GRAPH_ENABLE_IF_MODELS_PARM( + MutableGraph, vertex_list_graph_tag)) + { + typename graph_traits< MutableGraph >::vertices_size_type old_n; + do + { + old_n = num_vertices(g); + + typename graph_traits< MutableGraph >::vertex_iterator vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; + /* in loop */) + { + typename graph_traits< MutableGraph >::vertex_descriptor v + = *vi++; + if (out_degree(v, g) == 0) + { + clear_vertex(v, g); + remove_vertex(v, g); + } + } + } while (num_vertices(g) < old_n); + } + +} +} // end namespace boost::graph + + + +#endif // BOOST_GRAPH_PAGE_RANK_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/planar_canonical_ordering.hpp b/contrib/restricted/boost/graph/include/boost/graph/planar_canonical_ordering.hpp new file mode 100644 index 0000000000..61f2797a14 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/planar_canonical_ordering.hpp @@ -0,0 +1,205 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __PLANAR_CANONICAL_ORDERING_HPP__ +#define __PLANAR_CANONICAL_ORDERING_HPP__ + +#include <vector> +#include <list> +#include <boost/config.hpp> +#include <boost/next_prior.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +namespace detail +{ + enum planar_canonical_ordering_state + { + PCO_PROCESSED, + PCO_UNPROCESSED, + PCO_ONE_NEIGHBOR_PROCESSED, + PCO_READY_TO_BE_PROCESSED + }; +} + +template < typename Graph, typename PlanarEmbedding, typename OutputIterator, + typename VertexIndexMap > +void planar_canonical_ordering(const Graph& g, PlanarEmbedding embedding, + OutputIterator ordering, VertexIndexMap vm) +{ + + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef + typename graph_traits< Graph >::adjacency_iterator adjacency_iterator_t; + typedef typename property_traits< PlanarEmbedding >::value_type + embedding_value_t; + typedef typename embedding_value_t::const_iterator embedding_iterator_t; + typedef iterator_property_map< typename std::vector< vertex_t >::iterator, + VertexIndexMap > + vertex_to_vertex_map_t; + typedef iterator_property_map< + typename std::vector< std::size_t >::iterator, VertexIndexMap > + vertex_to_size_t_map_t; + + std::vector< vertex_t > processed_neighbor_vector(num_vertices(g)); + vertex_to_vertex_map_t processed_neighbor( + processed_neighbor_vector.begin(), vm); + + std::vector< std::size_t > status_vector( + num_vertices(g), detail::PCO_UNPROCESSED); + vertex_to_size_t_map_t status(status_vector.begin(), vm); + + std::list< vertex_t > ready_to_be_processed; + + vertex_t first_vertex = *vertices(g).first; + vertex_t second_vertex = first_vertex; + adjacency_iterator_t ai, ai_end; + for (boost::tie(ai, ai_end) = adjacent_vertices(first_vertex, g); + ai != ai_end; ++ai) + { + if (*ai == first_vertex) + continue; + second_vertex = *ai; + break; + } + + ready_to_be_processed.push_back(first_vertex); + status[first_vertex] = detail::PCO_READY_TO_BE_PROCESSED; + ready_to_be_processed.push_back(second_vertex); + status[second_vertex] = detail::PCO_READY_TO_BE_PROCESSED; + + while (!ready_to_be_processed.empty()) + { + vertex_t u = ready_to_be_processed.front(); + ready_to_be_processed.pop_front(); + + if (status[u] != detail::PCO_READY_TO_BE_PROCESSED + && u != second_vertex) + continue; + + embedding_iterator_t ei, ei_start, ei_end; + embedding_iterator_t next_edge_itr, prior_edge_itr; + + ei_start = embedding[u].begin(); + ei_end = embedding[u].end(); + prior_edge_itr = prior(ei_end); + while (source(*prior_edge_itr, g) == target(*prior_edge_itr, g)) + prior_edge_itr = prior(prior_edge_itr); + + for (ei = ei_start; ei != ei_end; ++ei) + { + + edge_t e(*ei); // e = (u,v) + next_edge_itr + = boost::next(ei) == ei_end ? ei_start : boost::next(ei); + vertex_t v = source(e, g) == u ? target(e, g) : source(e, g); + + vertex_t prior_vertex = source(*prior_edge_itr, g) == u + ? target(*prior_edge_itr, g) + : source(*prior_edge_itr, g); + vertex_t next_vertex = source(*next_edge_itr, g) == u + ? target(*next_edge_itr, g) + : source(*next_edge_itr, g); + + // Need prior_vertex, u, v, and next_vertex to all be + // distinct. This is possible, since the input graph is + // triangulated. It'll be true all the time in a simple + // graph, but loops and parallel edges cause some complications. + if (prior_vertex == v || prior_vertex == u) + { + prior_edge_itr = ei; + continue; + } + + // Skip any self-loops + if (u == v) + continue; + + // Move next_edge_itr (and next_vertex) forwards + // past any loops or parallel edges + while (next_vertex == v || next_vertex == u) + { + next_edge_itr = boost::next(next_edge_itr) == ei_end + ? ei_start + : boost::next(next_edge_itr); + next_vertex = source(*next_edge_itr, g) == u + ? target(*next_edge_itr, g) + : source(*next_edge_itr, g); + } + + if (status[v] == detail::PCO_UNPROCESSED) + { + status[v] = detail::PCO_ONE_NEIGHBOR_PROCESSED; + processed_neighbor[v] = u; + } + else if (status[v] == detail::PCO_ONE_NEIGHBOR_PROCESSED) + { + vertex_t x = processed_neighbor[v]; + // are edges (v,u) and (v,x) adjacent in the planar + // embedding? if so, set status[v] = 1. otherwise, set + // status[v] = 2. + + if ((next_vertex == x + && !(first_vertex == u && second_vertex == x)) + || (prior_vertex == x + && !(first_vertex == x && second_vertex == u))) + { + status[v] = detail::PCO_READY_TO_BE_PROCESSED; + } + else + { + status[v] = detail::PCO_READY_TO_BE_PROCESSED + 1; + } + } + else if (status[v] > detail::PCO_ONE_NEIGHBOR_PROCESSED) + { + // check the two edges before and after (v,u) in the planar + // embedding, and update status[v] accordingly + + bool processed_before = false; + if (status[prior_vertex] == detail::PCO_PROCESSED) + processed_before = true; + + bool processed_after = false; + if (status[next_vertex] == detail::PCO_PROCESSED) + processed_after = true; + + if (!processed_before && !processed_after) + ++status[v]; + + else if (processed_before && processed_after) + --status[v]; + } + + if (status[v] == detail::PCO_READY_TO_BE_PROCESSED) + ready_to_be_processed.push_back(v); + + prior_edge_itr = ei; + } + + status[u] = detail::PCO_PROCESSED; + *ordering = u; + ++ordering; + } +} + +template < typename Graph, typename PlanarEmbedding, typename OutputIterator > +void planar_canonical_ordering( + const Graph& g, PlanarEmbedding embedding, OutputIterator ordering) +{ + planar_canonical_ordering(g, embedding, ordering, get(vertex_index, g)); +} + +} // namespace boost + +#endif //__PLANAR_CANONICAL_ORDERING_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/planar_detail/add_edge_visitors.hpp b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/add_edge_visitors.hpp new file mode 100644 index 0000000000..7ea34f479d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/add_edge_visitors.hpp @@ -0,0 +1,54 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __ADD_EDGE_VISITORS_HPP__ +#define __ADD_EDGE_VISITORS_HPP__ + +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +struct default_add_edge_visitor +{ + + template < typename Graph, typename Vertex > + void visit_vertex_pair(Vertex u, Vertex v, Graph& g) + { + add_edge(u, v, g); + } +}; + +template < typename EdgeIndexMap > struct edge_index_update_visitor +{ + + typedef + typename property_traits< EdgeIndexMap >::value_type edge_index_value_t; + + edge_index_update_visitor( + EdgeIndexMap em, edge_index_value_t next_index_available) + : m_em(em), m_next_index(next_index_available) + { + } + + template < typename Graph, typename Vertex > + void visit_vertex_pair(Vertex u, Vertex v, Graph& g) + { + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + std::pair< edge_t, bool > return_value = add_edge(u, v, g); + if (return_value.second) + put(m_em, return_value.first, m_next_index++); + } + +private: + EdgeIndexMap m_em; + edge_index_value_t m_next_index; +}; + +} // namespace boost + +#endif //__ADD_EDGE_VISITORS_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp new file mode 100644 index 0000000000..c2797c1d81 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/boyer_myrvold_impl.hpp @@ -0,0 +1,1813 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __BOYER_MYRVOLD_IMPL_HPP__ +#define __BOYER_MYRVOLD_IMPL_HPP__ + +#include <vector> +#include <list> +#include <boost/next_prior.hpp> +#include <boost/config.hpp> //for std::min macros +#include <boost/shared_ptr.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/depth_first_search.hpp> +#include <boost/graph/planar_detail/face_handles.hpp> +#include <boost/graph/planar_detail/face_iterators.hpp> +#include <boost/graph/planar_detail/bucket_sort.hpp> + +namespace boost +{ +namespace detail +{ + enum bm_case_t + { + BM_NO_CASE_CHOSEN, + BM_CASE_A, + BM_CASE_B, + BM_CASE_C, + BM_CASE_D, + BM_CASE_E + }; +} + +template < typename LowPointMap, typename DFSParentMap, typename DFSNumberMap, + typename LeastAncestorMap, typename DFSParentEdgeMap, typename SizeType > +struct planar_dfs_visitor : public dfs_visitor<> +{ + planar_dfs_visitor(LowPointMap lpm, DFSParentMap dfs_p, DFSNumberMap dfs_n, + LeastAncestorMap lam, DFSParentEdgeMap dfs_edge) + : low(lpm) + , parent(dfs_p) + , df_number(dfs_n) + , least_ancestor(lam) + , df_edge(dfs_edge) + , count(0) + { + } + + template < typename Vertex, typename Graph > + void start_vertex(const Vertex& u, Graph&) + { + put(parent, u, u); + put(least_ancestor, u, count); + } + + template < typename Vertex, typename Graph > + void discover_vertex(const Vertex& u, Graph&) + { + put(low, u, count); + put(df_number, u, count); + ++count; + } + + template < typename Edge, typename Graph > + void tree_edge(const Edge& e, Graph& g) + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + vertex_t s(source(e, g)); + vertex_t t(target(e, g)); + + put(parent, t, s); + put(df_edge, t, e); + put(least_ancestor, t, get(df_number, s)); + } + + template < typename Edge, typename Graph > + void back_edge(const Edge& e, Graph& g) + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + + vertex_t s(source(e, g)); + vertex_t t(target(e, g)); + BOOST_USING_STD_MIN(); + + if (t != get(parent, s)) + { + v_size_t s_low_df_number = get(low, s); + v_size_t t_df_number = get(df_number, t); + v_size_t s_least_ancestor_df_number = get(least_ancestor, s); + + put(low, s, + min BOOST_PREVENT_MACRO_SUBSTITUTION( + s_low_df_number, t_df_number)); + + put(least_ancestor, s, + min BOOST_PREVENT_MACRO_SUBSTITUTION( + s_least_ancestor_df_number, t_df_number)); + } + } + + template < typename Vertex, typename Graph > + void finish_vertex(const Vertex& u, Graph&) + { + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + + Vertex u_parent = get(parent, u); + v_size_t u_parent_lowpoint = get(low, u_parent); + v_size_t u_lowpoint = get(low, u); + BOOST_USING_STD_MIN(); + + if (u_parent != u) + { + put(low, u_parent, + min BOOST_PREVENT_MACRO_SUBSTITUTION( + u_lowpoint, u_parent_lowpoint)); + } + } + + LowPointMap low; + DFSParentMap parent; + DFSNumberMap df_number; + LeastAncestorMap least_ancestor; + DFSParentEdgeMap df_edge; + SizeType count; +}; + +template < typename Graph, typename VertexIndexMap, + typename StoreOldHandlesPolicy = graph::detail::store_old_handles, + typename StoreEmbeddingPolicy = graph::detail::recursive_lazy_list > +class boyer_myrvold_impl +{ + + typedef typename graph_traits< Graph >::vertices_size_type v_size_t; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + typedef + typename graph_traits< Graph >::out_edge_iterator out_edge_iterator_t; + typedef graph::detail::face_handle< Graph, StoreOldHandlesPolicy, + StoreEmbeddingPolicy > + face_handle_t; + typedef std::vector< vertex_t > vertex_vector_t; + typedef std::vector< edge_t > edge_vector_t; + typedef std::list< vertex_t > vertex_list_t; + typedef std::list< face_handle_t > face_handle_list_t; + typedef boost::shared_ptr< face_handle_list_t > face_handle_list_ptr_t; + typedef boost::shared_ptr< vertex_list_t > vertex_list_ptr_t; + typedef boost::tuple< vertex_t, bool, bool > merge_stack_frame_t; + typedef std::vector< merge_stack_frame_t > merge_stack_t; + + template < typename T > struct map_vertex_to_ + { + typedef iterator_property_map< typename std::vector< T >::iterator, + VertexIndexMap > + type; + }; + + typedef typename map_vertex_to_< v_size_t >::type vertex_to_v_size_map_t; + typedef typename map_vertex_to_< vertex_t >::type vertex_to_vertex_map_t; + typedef typename map_vertex_to_< edge_t >::type vertex_to_edge_map_t; + typedef typename map_vertex_to_< vertex_list_ptr_t >::type + vertex_to_vertex_list_ptr_map_t; + typedef typename map_vertex_to_< edge_vector_t >::type + vertex_to_edge_vector_map_t; + typedef typename map_vertex_to_< bool >::type vertex_to_bool_map_t; + typedef typename map_vertex_to_< face_handle_t >::type + vertex_to_face_handle_map_t; + typedef typename map_vertex_to_< face_handle_list_ptr_t >::type + vertex_to_face_handle_list_ptr_map_t; + typedef typename map_vertex_to_< typename vertex_list_t::iterator >::type + vertex_to_separated_node_map_t; + + template < typename BicompSideToTraverse = single_side, + typename VisitorType = lead_visitor, typename Time = current_iteration > + struct face_vertex_iterator + { + typedef face_iterator< Graph, vertex_to_face_handle_map_t, vertex_t, + BicompSideToTraverse, VisitorType, Time > + type; + }; + + template < typename BicompSideToTraverse = single_side, + typename Time = current_iteration > + struct face_edge_iterator + { + typedef face_iterator< Graph, vertex_to_face_handle_map_t, edge_t, + BicompSideToTraverse, lead_visitor, Time > + type; + }; + +public: + boyer_myrvold_impl(const Graph& arg_g, VertexIndexMap arg_vm) + : g(arg_g) + , vm(arg_vm) + , + + low_point_vector(num_vertices(g)) + , dfs_parent_vector(num_vertices(g)) + , dfs_number_vector(num_vertices(g)) + , least_ancestor_vector(num_vertices(g)) + , pertinent_roots_vector(num_vertices(g)) + , backedge_flag_vector(num_vertices(g), num_vertices(g) + 1) + , visited_vector(num_vertices(g), num_vertices(g) + 1) + , face_handles_vector(num_vertices(g)) + , dfs_child_handles_vector(num_vertices(g)) + , separated_dfs_child_list_vector(num_vertices(g)) + , separated_node_in_parent_list_vector(num_vertices(g)) + , canonical_dfs_child_vector(num_vertices(g)) + , flipped_vector(num_vertices(g), false) + , backedges_vector(num_vertices(g)) + , dfs_parent_edge_vector(num_vertices(g)) + , + + vertices_by_dfs_num(num_vertices(g)) + , + + low_point(low_point_vector.begin(), vm) + , dfs_parent(dfs_parent_vector.begin(), vm) + , dfs_number(dfs_number_vector.begin(), vm) + , least_ancestor(least_ancestor_vector.begin(), vm) + , pertinent_roots(pertinent_roots_vector.begin(), vm) + , backedge_flag(backedge_flag_vector.begin(), vm) + , visited(visited_vector.begin(), vm) + , face_handles(face_handles_vector.begin(), vm) + , dfs_child_handles(dfs_child_handles_vector.begin(), vm) + , separated_dfs_child_list(separated_dfs_child_list_vector.begin(), vm) + , separated_node_in_parent_list( + separated_node_in_parent_list_vector.begin(), vm) + , canonical_dfs_child(canonical_dfs_child_vector.begin(), vm) + , flipped(flipped_vector.begin(), vm) + , backedges(backedges_vector.begin(), vm) + , dfs_parent_edge(dfs_parent_edge_vector.begin(), vm) + + { + + planar_dfs_visitor< vertex_to_v_size_map_t, vertex_to_vertex_map_t, + vertex_to_v_size_map_t, vertex_to_v_size_map_t, + vertex_to_edge_map_t, v_size_t > + vis(low_point, dfs_parent, dfs_number, least_ancestor, + dfs_parent_edge); + + // Perform a depth-first search to find each vertex's low point, least + // ancestor, and dfs tree information + depth_first_search(g, visitor(vis).vertex_index_map(vm)); + + // Sort vertices by their lowpoint - need this later in the constructor + vertex_vector_t vertices_by_lowpoint(num_vertices(g)); + std::copy(vertices(g).first, vertices(g).second, + vertices_by_lowpoint.begin()); + bucket_sort(vertices_by_lowpoint.begin(), vertices_by_lowpoint.end(), + low_point, num_vertices(g)); + + // Sort vertices by their dfs number - need this to iterate by reverse + // DFS number in the main loop. + std::copy( + vertices(g).first, vertices(g).second, vertices_by_dfs_num.begin()); + bucket_sort(vertices_by_dfs_num.begin(), vertices_by_dfs_num.end(), + dfs_number, num_vertices(g)); + + // Initialize face handles. A face handle is an abstraction that serves + // two uses in our implementation - it allows us to efficiently move + // along the outer face of embedded bicomps in a partially embedded + // graph, and it provides storage for the planar embedding. Face + // handles are implemented by a sequence of edges and are associated + // with a particular vertex - the sequence of edges represents the + // current embedding of edges around that vertex, and the first and + // last edges in the sequence represent the pair of edges on the outer + // face that are adjacent to the associated vertex. This lets us embed + // edges in the graph by just pushing them on the front or back of the + // sequence of edges held by the face handles. + // + // Our algorithm starts with a DFS tree of edges (where every vertex is + // an articulation point and every edge is a singleton bicomp) and + // repeatedly merges bicomps by embedding additional edges. Note that + // any bicomp at any point in the algorithm can be associated with a + // unique edge connecting the vertex of that bicomp with the lowest DFS + // number (which we refer to as the "root" of the bicomp) with its DFS + // child in the bicomp: the existence of two such edges would contradict + // the properties of a DFS tree. We refer to the DFS child of the root + // of a bicomp as the "canonical DFS child" of the bicomp. Note that a + // vertex can be the root of more than one bicomp. + // + // We move around the external faces of a bicomp using a few property + // maps, which we'll initialize presently: + // + // - face_handles: maps a vertex to a face handle that can be used to + // move "up" a bicomp. For a vertex that isn't an articulation point, + // this holds the face handles that can be used to move around that + // vertex's unique bicomp. For a vertex that is an articulation point, + // this holds the face handles associated with the unique bicomp that + // the vertex is NOT the root of. These handles can therefore be used + // to move from any point on the outer face of the tree of bicomps + // around the current outer face towards the root of the DFS tree. + // + // - dfs_child_handles: these are used to hold face handles for + // vertices that are articulation points - dfs_child_handles[v] holds + // the face handles corresponding to vertex u in the bicomp with root + // u and canonical DFS child v. + // + // - canonical_dfs_child: this property map allows one to determine the + // canonical DFS child of a bicomp while traversing the outer face. + // This property map is only valid when applied to one of the two + // vertices adjacent to the root of the bicomp on the outer face. To + // be more precise, if v is the canonical DFS child of a bicomp, + // canonical_dfs_child[dfs_child_handles[v].first_vertex()] == v and + // canonical_dfs_child[dfs_child_handles[v].second_vertex()] == v. + // + // - pertinent_roots: given a vertex v, pertinent_roots[v] contains a + // list of face handles pointing to the top of bicomps that need to + // be visited by the current walkdown traversal (since they lead to + // backedges that need to be embedded). These lists are populated by + // the walkup and consumed by the walkdown. + + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + vertex_t parent = dfs_parent[v]; + + if (parent != v) + { + edge_t parent_edge = dfs_parent_edge[v]; + add_to_embedded_edges(parent_edge, StoreOldHandlesPolicy()); + face_handles[v] = face_handle_t(v, parent_edge, g); + dfs_child_handles[v] = face_handle_t(parent, parent_edge, g); + } + else + { + face_handles[v] = face_handle_t(v); + dfs_child_handles[v] = face_handle_t(parent); + } + + canonical_dfs_child[v] = v; + pertinent_roots[v] = face_handle_list_ptr_t(new face_handle_list_t); + separated_dfs_child_list[v] = vertex_list_ptr_t(new vertex_list_t); + } + + // We need to create a list of not-yet-merged depth-first children for + // each vertex that will be updated as bicomps get merged. We sort each + // list by ascending lowpoint, which allows the externally_active + // function to run in constant time, and we keep a pointer to each + // vertex's representation in its parent's list, which allows merging + // in constant time. + + for (typename vertex_vector_t::iterator itr + = vertices_by_lowpoint.begin(); + itr != vertices_by_lowpoint.end(); ++itr) + { + vertex_t v(*itr); + vertex_t parent(dfs_parent[v]); + if (v != parent) + { + separated_node_in_parent_list[v] + = separated_dfs_child_list[parent]->insert( + separated_dfs_child_list[parent]->end(), v); + } + } + + // The merge stack holds path information during a walkdown iteration + merge_stack.reserve(num_vertices(g)); + } + + bool is_planar() + { + + // This is the main algorithm: starting with a DFS tree of embedded + // edges (which, since it's a tree, is planar), iterate through all + // vertices by reverse DFS number, attempting to embed all backedges + // connecting the current vertex to vertices with higher DFS numbers. + // + // The walkup is a procedure that examines all such backedges and sets + // up the required data structures so that they can be searched by the + // walkdown in linear time. The walkdown does the actual work of + // embedding edges and flipping bicomps, and can identify when it has + // come across a kuratowski subgraph. + // + // store_old_face_handles caches face handles from the previous + // iteration - this is used only for the kuratowski subgraph isolation, + // and is therefore dispatched based on the StoreOldHandlesPolicy. + // + // clean_up_embedding does some clean-up and fills in values that have + // to be computed lazily during the actual execution of the algorithm + // (for instance, whether or not a bicomp is flipped in the final + // embedding). It's dispatched on the the StoreEmbeddingPolicy, since + // it's not needed if an embedding isn't desired. + + typename vertex_vector_t::reverse_iterator vi, vi_end; + + vi_end = vertices_by_dfs_num.rend(); + for (vi = vertices_by_dfs_num.rbegin(); vi != vi_end; ++vi) + { + + store_old_face_handles(StoreOldHandlesPolicy()); + + vertex_t v(*vi); + + walkup(v); + + if (!walkdown(v)) + return false; + } + + clean_up_embedding(StoreEmbeddingPolicy()); + + return true; + } + +private: + void walkup(vertex_t v) + { + + // The point of the walkup is to follow all backedges from v to + // vertices with higher DFS numbers, and update pertinent_roots + // for the bicomp roots on the path from backedge endpoints up + // to v. This will set the stage for the walkdown to efficiently + // traverse the graph of bicomps down from v. + + typedef + typename face_vertex_iterator< both_sides >::type walkup_iterator_t; + + out_edge_iterator_t oi, oi_end; + for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi) + { + edge_t e(*oi); + vertex_t e_source(source(e, g)); + vertex_t e_target(target(e, g)); + + if (e_source == e_target) + { + self_loops.push_back(e); + continue; + } + + vertex_t w(e_source == v ? e_target : e_source); + + // continue if not a back edge or already embedded + if (dfs_number[w] < dfs_number[v] || e == dfs_parent_edge[w]) + continue; + + backedges[w].push_back(e); + + v_size_t timestamp = dfs_number[v]; + backedge_flag[w] = timestamp; + + walkup_iterator_t walkup_itr(w, face_handles); + walkup_iterator_t walkup_end; + vertex_t lead_vertex = w; + + while (true) + { + + // Move to the root of the current bicomp or the first visited + // vertex on the bicomp by going up each side in parallel + + while (walkup_itr != walkup_end + && visited[*walkup_itr] != timestamp) + { + lead_vertex = *walkup_itr; + visited[lead_vertex] = timestamp; + ++walkup_itr; + } + + // If we've found the root of a bicomp through a path we haven't + // seen before, update pertinent_roots with a handle to the + // current bicomp. Otherwise, we've just seen a path we've been + // up before, so break out of the main while loop. + + if (walkup_itr == walkup_end) + { + vertex_t dfs_child = canonical_dfs_child[lead_vertex]; + vertex_t parent = dfs_parent[dfs_child]; + + visited[dfs_child_handles[dfs_child].first_vertex()] + = timestamp; + visited[dfs_child_handles[dfs_child].second_vertex()] + = timestamp; + + if (low_point[dfs_child] < dfs_number[v] + || least_ancestor[dfs_child] < dfs_number[v]) + { + pertinent_roots[parent]->push_back( + dfs_child_handles[dfs_child]); + } + else + { + pertinent_roots[parent]->push_front( + dfs_child_handles[dfs_child]); + } + + if (parent != v && visited[parent] != timestamp) + { + walkup_itr = walkup_iterator_t(parent, face_handles); + lead_vertex = parent; + } + else + break; + } + else + break; + } + } + } + + bool walkdown(vertex_t v) + { + // This procedure is where all of the action is - pertinent_roots + // has already been set up by the walkup, so we just need to move + // down bicomps from v until we find vertices that have been + // labeled as backedge endpoints. Once we find such a vertex, we + // embed the corresponding edge and glue together the bicomps on + // the path connecting the two vertices in the edge. This may + // involve flipping bicomps along the way. + + vertex_t w; // the other endpoint of the edge we're embedding + + while (!pertinent_roots[v]->empty()) + { + + face_handle_t root_face_handle = pertinent_roots[v]->front(); + face_handle_t curr_face_handle = root_face_handle; + pertinent_roots[v]->pop_front(); + + merge_stack.clear(); + + while (true) + { + + typename face_vertex_iterator<>::type first_face_itr, + second_face_itr, face_end; + vertex_t first_side_vertex + = graph_traits< Graph >::null_vertex(); + vertex_t second_side_vertex + = graph_traits< Graph >::null_vertex(); + vertex_t first_tail, second_tail; + + first_tail = second_tail = curr_face_handle.get_anchor(); + first_face_itr = typename face_vertex_iterator<>::type( + curr_face_handle, face_handles, first_side()); + second_face_itr = typename face_vertex_iterator<>::type( + curr_face_handle, face_handles, second_side()); + + for (; first_face_itr != face_end; ++first_face_itr) + { + vertex_t face_vertex(*first_face_itr); + if (pertinent(face_vertex, v) + || externally_active(face_vertex, v)) + { + first_side_vertex = face_vertex; + second_side_vertex = face_vertex; + break; + } + first_tail = face_vertex; + } + + if (first_side_vertex == graph_traits< Graph >::null_vertex() + || first_side_vertex == curr_face_handle.get_anchor()) + break; + + for (; second_face_itr != face_end; ++second_face_itr) + { + vertex_t face_vertex(*second_face_itr); + if (pertinent(face_vertex, v) + || externally_active(face_vertex, v)) + { + second_side_vertex = face_vertex; + break; + } + second_tail = face_vertex; + } + + vertex_t chosen; + bool chose_first_upper_path; + if (internally_active(first_side_vertex, v)) + { + chosen = first_side_vertex; + chose_first_upper_path = true; + } + else if (internally_active(second_side_vertex, v)) + { + chosen = second_side_vertex; + chose_first_upper_path = false; + } + else if (pertinent(first_side_vertex, v)) + { + chosen = first_side_vertex; + chose_first_upper_path = true; + } + else if (pertinent(second_side_vertex, v)) + { + chosen = second_side_vertex; + chose_first_upper_path = false; + } + else + { + + // If there's a pertinent vertex on the lower face + // between the first_face_itr and the second_face_itr, + // this graph isn't planar. + for (; *first_face_itr != second_side_vertex; + ++first_face_itr) + { + vertex_t p(*first_face_itr); + if (pertinent(p, v)) + { + // Found a Kuratowski subgraph + kuratowski_v = v; + kuratowski_x = first_side_vertex; + kuratowski_y = second_side_vertex; + return false; + } + } + + // Otherwise, the fact that we didn't find a pertinent + // vertex on this face is fine - we should set the + // short-circuit edges and break out of this loop to + // start looking at a different pertinent root. + + if (first_side_vertex == second_side_vertex) + { + if (first_tail != v) + { + vertex_t first + = face_handles[first_tail].first_vertex(); + vertex_t second + = face_handles[first_tail].second_vertex(); + boost::tie(first_side_vertex, first_tail) + = make_tuple(first_tail, + first == first_side_vertex ? second + : first); + } + else if (second_tail != v) + { + vertex_t first + = face_handles[second_tail].first_vertex(); + vertex_t second + = face_handles[second_tail].second_vertex(); + boost::tie(second_side_vertex, second_tail) + = make_tuple(second_tail, + first == second_side_vertex ? second + : first); + } + else + break; + } + + canonical_dfs_child[first_side_vertex] + = canonical_dfs_child[root_face_handle.first_vertex()]; + canonical_dfs_child[second_side_vertex] + = canonical_dfs_child[root_face_handle.second_vertex()]; + root_face_handle.set_first_vertex(first_side_vertex); + root_face_handle.set_second_vertex(second_side_vertex); + + if (face_handles[first_side_vertex].first_vertex() + == first_tail) + face_handles[first_side_vertex].set_first_vertex(v); + else + face_handles[first_side_vertex].set_second_vertex(v); + + if (face_handles[second_side_vertex].first_vertex() + == second_tail) + face_handles[second_side_vertex].set_first_vertex(v); + else + face_handles[second_side_vertex].set_second_vertex(v); + + break; + } + + // When we unwind the stack, we need to know which direction + // we came down from on the top face handle + + bool chose_first_lower_path + = (chose_first_upper_path + && face_handles[chosen].first_vertex() == first_tail) + || (!chose_first_upper_path + && face_handles[chosen].first_vertex() == second_tail); + + // If there's a backedge at the chosen vertex, embed it now + if (backedge_flag[chosen] == dfs_number[v]) + { + w = chosen; + + backedge_flag[chosen] = num_vertices(g) + 1; + add_to_merge_points(chosen, StoreOldHandlesPolicy()); + + typename edge_vector_t::iterator ei, ei_end; + ei_end = backedges[chosen].end(); + for (ei = backedges[chosen].begin(); ei != ei_end; ++ei) + { + edge_t e(*ei); + add_to_embedded_edges(e, StoreOldHandlesPolicy()); + + if (chose_first_lower_path) + face_handles[chosen].push_first(e, g); + else + face_handles[chosen].push_second(e, g); + } + } + else + { + merge_stack.push_back(make_tuple(chosen, + chose_first_upper_path, chose_first_lower_path)); + curr_face_handle = *pertinent_roots[chosen]->begin(); + continue; + } + + // Unwind the merge stack to the root, merging all bicomps + + bool bottom_path_follows_first; + bool top_path_follows_first; + bool next_bottom_follows_first = chose_first_upper_path; + + vertex_t merge_point = chosen; + + while (!merge_stack.empty()) + { + + bottom_path_follows_first = next_bottom_follows_first; + boost::tie(merge_point, next_bottom_follows_first, + top_path_follows_first) + = merge_stack.back(); + merge_stack.pop_back(); + + face_handle_t top_handle(face_handles[merge_point]); + face_handle_t bottom_handle( + *pertinent_roots[merge_point]->begin()); + + vertex_t bottom_dfs_child = canonical_dfs_child + [pertinent_roots[merge_point]->begin()->first_vertex()]; + + remove_vertex_from_separated_dfs_child_list( + canonical_dfs_child[pertinent_roots[merge_point] + ->begin() + ->first_vertex()]); + + pertinent_roots[merge_point]->pop_front(); + + add_to_merge_points( + top_handle.get_anchor(), StoreOldHandlesPolicy()); + + if (top_path_follows_first && bottom_path_follows_first) + { + bottom_handle.flip(); + top_handle.glue_first_to_second(bottom_handle); + } + else if (!top_path_follows_first + && bottom_path_follows_first) + { + flipped[bottom_dfs_child] = true; + top_handle.glue_second_to_first(bottom_handle); + } + else if (top_path_follows_first + && !bottom_path_follows_first) + { + flipped[bottom_dfs_child] = true; + top_handle.glue_first_to_second(bottom_handle); + } + else //! top_path_follows_first && + //! !bottom_path_follows_first + { + bottom_handle.flip(); + top_handle.glue_second_to_first(bottom_handle); + } + } + + // Finally, embed all edges (v,w) at their upper end points + canonical_dfs_child[w] + = canonical_dfs_child[root_face_handle.first_vertex()]; + + add_to_merge_points( + root_face_handle.get_anchor(), StoreOldHandlesPolicy()); + + typename edge_vector_t::iterator ei, ei_end; + ei_end = backedges[chosen].end(); + for (ei = backedges[chosen].begin(); ei != ei_end; ++ei) + { + if (next_bottom_follows_first) + root_face_handle.push_first(*ei, g); + else + root_face_handle.push_second(*ei, g); + } + + backedges[chosen].clear(); + curr_face_handle = root_face_handle; + + } // while(true) + + } // while(!pertinent_roots[v]->empty()) + + return true; + } + + void store_old_face_handles(graph::detail::no_old_handles) {} + + void store_old_face_handles(graph::detail::store_old_handles) + { + for (typename std::vector< vertex_t >::iterator mp_itr + = current_merge_points.begin(); + mp_itr != current_merge_points.end(); ++mp_itr) + { + face_handles[*mp_itr].store_old_face_handles(); + } + current_merge_points.clear(); + } + + void add_to_merge_points(vertex_t, graph::detail::no_old_handles) {} + + void add_to_merge_points(vertex_t v, graph::detail::store_old_handles) + { + current_merge_points.push_back(v); + } + + void add_to_embedded_edges(edge_t, graph::detail::no_old_handles) {} + + void add_to_embedded_edges(edge_t e, graph::detail::store_old_handles) + { + embedded_edges.push_back(e); + } + + void clean_up_embedding(graph::detail::no_embedding) {} + + void clean_up_embedding(graph::detail::store_embedding) + { + + // If the graph isn't biconnected, we'll still have entries + // in the separated_dfs_child_list for some vertices. Since + // these represent articulation points, we can obtain a + // planar embedding no matter what order we embed them in. + + vertex_iterator_t xi, xi_end; + for (boost::tie(xi, xi_end) = vertices(g); xi != xi_end; ++xi) + { + if (!separated_dfs_child_list[*xi]->empty()) + { + typename vertex_list_t::iterator yi, yi_end; + yi_end = separated_dfs_child_list[*xi]->end(); + for (yi = separated_dfs_child_list[*xi]->begin(); yi != yi_end; + ++yi) + { + dfs_child_handles[*yi].flip(); + face_handles[*xi].glue_first_to_second( + dfs_child_handles[*yi]); + } + } + } + + // Up until this point, we've flipped bicomps lazily by setting + // flipped[v] to true if the bicomp rooted at v was flipped (the + // lazy aspect of this flip is that all descendents of that vertex + // need to have their orientations reversed as well). Now, we + // traverse the DFS tree by DFS number and perform the actual + // flipping as needed + + typedef typename vertex_vector_t::iterator vertex_vector_itr_t; + vertex_vector_itr_t vi_end = vertices_by_dfs_num.end(); + for (vertex_vector_itr_t vi = vertices_by_dfs_num.begin(); vi != vi_end; + ++vi) + { + vertex_t v(*vi); + bool v_flipped = flipped[v]; + bool p_flipped = flipped[dfs_parent[v]]; + if (v_flipped && !p_flipped) + { + face_handles[v].flip(); + } + else if (p_flipped && !v_flipped) + { + face_handles[v].flip(); + flipped[v] = true; + } + else + { + flipped[v] = false; + } + } + + // If there are any self-loops in the graph, they were flagged + // during the walkup, and we should add them to the embedding now. + // Adding a self loop anywhere in the embedding could never + // invalidate the embedding, but they would complicate the traversal + // if they were added during the walkup/walkdown. + + typename edge_vector_t::iterator ei, ei_end; + ei_end = self_loops.end(); + for (ei = self_loops.begin(); ei != ei_end; ++ei) + { + edge_t e(*ei); + face_handles[source(e, g)].push_second(e, g); + } + } + + bool pertinent(vertex_t w, vertex_t v) + { + // w is pertinent with respect to v if there is a backedge (v,w) or if + // w is the root of a bicomp that contains a pertinent vertex. + + return backedge_flag[w] == dfs_number[v] + || !pertinent_roots[w]->empty(); + } + + bool externally_active(vertex_t w, vertex_t v) + { + // Let a be any proper depth-first search ancestor of v. w is externally + // active with respect to v if there exists a backedge (a,w) or a + // backedge (a,w_0) for some w_0 in a descendent bicomp of w. + + v_size_t dfs_number_of_v = dfs_number[v]; + return (least_ancestor[w] < dfs_number_of_v) + || (!separated_dfs_child_list[w]->empty() + && low_point[separated_dfs_child_list[w]->front()] + < dfs_number_of_v); + } + + bool internally_active(vertex_t w, vertex_t v) + { + return pertinent(w, v) && !externally_active(w, v); + } + + void remove_vertex_from_separated_dfs_child_list(vertex_t v) + { + typename vertex_list_t::iterator to_delete + = separated_node_in_parent_list[v]; + garbage.splice(garbage.end(), *separated_dfs_child_list[dfs_parent[v]], + to_delete, boost::next(to_delete)); + } + + // End of the implementation of the basic Boyer-Myrvold Algorithm. The rest + // of the code below implements the isolation of a Kuratowski subgraph in + // the case that the input graph is not planar. This is by far the most + // complicated part of the implementation. + +public: + template < typename EdgeToBoolPropertyMap, typename EdgeContainer > + vertex_t kuratowski_walkup(vertex_t v, EdgeToBoolPropertyMap forbidden_edge, + EdgeToBoolPropertyMap goal_edge, EdgeToBoolPropertyMap is_embedded, + EdgeContainer& path_edges) + { + vertex_t current_endpoint; + bool seen_goal_edge = false; + out_edge_iterator_t oi, oi_end; + + for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi) + forbidden_edge[*oi] = true; + + for (boost::tie(oi, oi_end) = out_edges(v, g); oi != oi_end; ++oi) + { + path_edges.clear(); + + edge_t e(*oi); + current_endpoint + = target(*oi, g) == v ? source(*oi, g) : target(*oi, g); + + if (dfs_number[current_endpoint] < dfs_number[v] || is_embedded[e] + || v == current_endpoint // self-loop + ) + { + // Not a backedge + continue; + } + + path_edges.push_back(e); + if (goal_edge[e]) + { + return current_endpoint; + } + + typedef typename face_edge_iterator<>::type walkup_itr_t; + + walkup_itr_t walkup_itr( + current_endpoint, face_handles, first_side()); + walkup_itr_t walkup_end; + + seen_goal_edge = false; + + while (true) + { + + if (walkup_itr != walkup_end && forbidden_edge[*walkup_itr]) + break; + + while (walkup_itr != walkup_end && !goal_edge[*walkup_itr] + && !forbidden_edge[*walkup_itr]) + { + edge_t f(*walkup_itr); + forbidden_edge[f] = true; + path_edges.push_back(f); + current_endpoint = source(f, g) == current_endpoint + ? target(f, g) + : source(f, g); + ++walkup_itr; + } + + if (walkup_itr != walkup_end && goal_edge[*walkup_itr]) + { + path_edges.push_back(*walkup_itr); + seen_goal_edge = true; + break; + } + + walkup_itr = walkup_itr_t( + current_endpoint, face_handles, first_side()); + } + + if (seen_goal_edge) + break; + } + + if (seen_goal_edge) + return current_endpoint; + else + return graph_traits< Graph >::null_vertex(); + } + + template < typename OutputIterator, typename EdgeIndexMap > + void extract_kuratowski_subgraph(OutputIterator o_itr, EdgeIndexMap em) + { + + // If the main algorithm has failed to embed one of the back-edges from + // a vertex v, we can use the current state of the algorithm to isolate + // a Kuratowksi subgraph. The isolation process breaks down into five + // cases, A - E. The general configuration of all five cases is shown in + // figure 1. There is a vertex v from which the planar + // v embedding process could not proceed. This means that + // | there exists some bicomp containing three vertices + // ----- x,y, and z as shown such that x and y are externally + // | | active with respect to v (which means that there are + // x y two vertices x_0 and y_0 such that (1) both x_0 and + // | | y_0 are proper depth-first search ancestors of v and + // --z-- (2) there are two disjoint paths, one connecting x + // and x_0 and one connecting y and y_0, both + // consisting + // fig. 1 entirely of unembedded edges). Furthermore, there + // exists a vertex z_0 such that z is a depth-first + // search ancestor of z_0 and (v,z_0) is an unembedded back-edge from v. + // x,y and z all exist on the same bicomp, which consists entirely of + // embedded edges. The five subcases break down as follows, and are + // handled by the algorithm logically in the order A-E: First, if v is + // not on the same bicomp as x,y, and z, a K_3_3 can be isolated - this + // is case A. So, we'll assume that v is on the same bicomp as x,y, and + // z. If z_0 is on a different bicomp than x,y, and z, a K_3_3 can also + // be isolated - this is a case B - so we'll assume from now on that v + // is on the same bicomp as x, y, and z=z_0. In this case, one can use + // properties of the Boyer-Myrvold algorithm to show the existence of an + // "x-y path" connecting some vertex on the "left side" of the x,y,z + // bicomp with some vertex on the "right side" of the bicomp (where the + // left and right are split by a line drawn through v and z.If either of + // the endpoints of the x-y path is above x or y on the bicomp, a K_3_3 + // can be isolated - this is a case C. Otherwise, both endpoints are at + // or below x and y on the bicomp. If there is a vertex alpha on the x-y + // path such that alpha is not x or y and there's a path from alpha to v + // that's disjoint from any of the edges on the bicomp and the x-y path, + // a K_3_3 can be isolated - this is a case D. Otherwise, properties of + // the Boyer-Myrvold algorithm can be used to show that another vertex + // w exists on the lower half of the bicomp such that w is externally + // active with respect to v. w can then be used to isolate a K_5 - this + // is the configuration of case E. + + vertex_iterator_t vi, vi_end; + edge_iterator_t ei, ei_end; + out_edge_iterator_t oei, oei_end; + typename std::vector< edge_t >::iterator xi, xi_end; + + // Clear the short-circuit edges - these are needed for the planar + // testing/embedding algorithm to run in linear time, but they'll + // complicate the kuratowski subgraph isolation + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + face_handles[*vi].reset_vertex_cache(); + dfs_child_handles[*vi].reset_vertex_cache(); + } + + vertex_t v = kuratowski_v; + vertex_t x = kuratowski_x; + vertex_t y = kuratowski_y; + + typedef iterator_property_map< typename std::vector< bool >::iterator, + EdgeIndexMap > + edge_to_bool_map_t; + + std::vector< bool > is_in_subgraph_vector(num_edges(g), false); + edge_to_bool_map_t is_in_subgraph(is_in_subgraph_vector.begin(), em); + + std::vector< bool > is_embedded_vector(num_edges(g), false); + edge_to_bool_map_t is_embedded(is_embedded_vector.begin(), em); + + typename std::vector< edge_t >::iterator embedded_itr, embedded_end; + embedded_end = embedded_edges.end(); + for (embedded_itr = embedded_edges.begin(); + embedded_itr != embedded_end; ++embedded_itr) + is_embedded[*embedded_itr] = true; + + // upper_face_vertex is true for x,y, and all vertices above x and y in + // the bicomp + std::vector< bool > upper_face_vertex_vector(num_vertices(g), false); + vertex_to_bool_map_t upper_face_vertex( + upper_face_vertex_vector.begin(), vm); + + std::vector< bool > lower_face_vertex_vector(num_vertices(g), false); + vertex_to_bool_map_t lower_face_vertex( + lower_face_vertex_vector.begin(), vm); + + // These next few variable declarations are all things that we need + // to find. + vertex_t z = graph_traits< Graph >::null_vertex(); + vertex_t bicomp_root; + vertex_t w = graph_traits< Graph >::null_vertex(); + face_handle_t w_handle; + face_handle_t v_dfchild_handle; + vertex_t first_x_y_path_endpoint = graph_traits< Graph >::null_vertex(); + vertex_t second_x_y_path_endpoint + = graph_traits< Graph >::null_vertex(); + vertex_t w_ancestor = v; + + detail::bm_case_t chosen_case = detail::BM_NO_CASE_CHOSEN; + + std::vector< edge_t > x_external_path; + std::vector< edge_t > y_external_path; + std::vector< edge_t > case_d_edges; + + std::vector< edge_t > z_v_path; + std::vector< edge_t > w_path; + + // first, use a walkup to find a path from V that starts with a + // backedge from V, then goes up until it hits either X or Y + //(but doesn't find X or Y as the root of a bicomp) + + typename face_vertex_iterator<>::type x_upper_itr( + x, face_handles, first_side()); + typename face_vertex_iterator<>::type x_lower_itr( + x, face_handles, second_side()); + typename face_vertex_iterator<>::type face_itr, face_end; + + // Don't know which path from x is the upper or lower path - + // we'll find out here + for (face_itr = x_upper_itr; face_itr != face_end; ++face_itr) + { + if (*face_itr == y) + { + std::swap(x_upper_itr, x_lower_itr); + break; + } + } + + upper_face_vertex[x] = true; + + vertex_t current_vertex = x; + vertex_t previous_vertex; + for (face_itr = x_upper_itr; face_itr != face_end; ++face_itr) + { + previous_vertex = current_vertex; + current_vertex = *face_itr; + upper_face_vertex[current_vertex] = true; + } + + v_dfchild_handle + = dfs_child_handles[canonical_dfs_child[previous_vertex]]; + + for (face_itr = x_lower_itr; *face_itr != y; ++face_itr) + { + vertex_t current_vertex(*face_itr); + lower_face_vertex[current_vertex] = true; + + typename face_handle_list_t::iterator roots_itr, roots_end; + + if (w == graph_traits< Graph >::null_vertex()) // haven't found a w + // yet + { + roots_end = pertinent_roots[current_vertex]->end(); + for (roots_itr = pertinent_roots[current_vertex]->begin(); + roots_itr != roots_end; ++roots_itr) + { + if (low_point + [canonical_dfs_child[roots_itr->first_vertex()]] + < dfs_number[v]) + { + w = current_vertex; + w_handle = *roots_itr; + break; + } + } + } + } + + for (; face_itr != face_end; ++face_itr) + { + vertex_t current_vertex(*face_itr); + upper_face_vertex[current_vertex] = true; + bicomp_root = current_vertex; + } + + typedef typename face_edge_iterator<>::type walkup_itr_t; + + std::vector< bool > outer_face_edge_vector(num_edges(g), false); + edge_to_bool_map_t outer_face_edge(outer_face_edge_vector.begin(), em); + + walkup_itr_t walkup_end; + for (walkup_itr_t walkup_itr(x, face_handles, first_side()); + walkup_itr != walkup_end; ++walkup_itr) + { + outer_face_edge[*walkup_itr] = true; + is_in_subgraph[*walkup_itr] = true; + } + + for (walkup_itr_t walkup_itr(x, face_handles, second_side()); + walkup_itr != walkup_end; ++walkup_itr) + { + outer_face_edge[*walkup_itr] = true; + is_in_subgraph[*walkup_itr] = true; + } + + std::vector< bool > forbidden_edge_vector(num_edges(g), false); + edge_to_bool_map_t forbidden_edge(forbidden_edge_vector.begin(), em); + + std::vector< bool > goal_edge_vector(num_edges(g), false); + edge_to_bool_map_t goal_edge(goal_edge_vector.begin(), em); + + // Find external path to x and to y + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] = !outer_face_edge[e] + && (source(e, g) == x || target(e, g) == x); + forbidden_edge[*ei] = outer_face_edge[*ei]; + } + + vertex_t x_ancestor = v; + vertex_t x_endpoint = graph_traits< Graph >::null_vertex(); + + while (x_endpoint == graph_traits< Graph >::null_vertex()) + { + x_ancestor = dfs_parent[x_ancestor]; + x_endpoint = kuratowski_walkup(x_ancestor, forbidden_edge, + goal_edge, is_embedded, x_external_path); + } + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] = !outer_face_edge[e] + && (source(e, g) == y || target(e, g) == y); + forbidden_edge[*ei] = outer_face_edge[*ei]; + } + + vertex_t y_ancestor = v; + vertex_t y_endpoint = graph_traits< Graph >::null_vertex(); + + while (y_endpoint == graph_traits< Graph >::null_vertex()) + { + y_ancestor = dfs_parent[y_ancestor]; + y_endpoint = kuratowski_walkup(y_ancestor, forbidden_edge, + goal_edge, is_embedded, y_external_path); + } + + vertex_t parent, child; + + // If v isn't on the same bicomp as x and y, it's a case A + if (bicomp_root != v) + { + chosen_case = detail::BM_CASE_A; + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + if (lower_face_vertex[*vi]) + for (boost::tie(oei, oei_end) = out_edges(*vi, g); + oei != oei_end; ++oei) + if (!outer_face_edge[*oei]) + goal_edge[*oei] = true; + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + forbidden_edge[*ei] = outer_face_edge[*ei]; + + z = kuratowski_walkup( + v, forbidden_edge, goal_edge, is_embedded, z_v_path); + } + else if (w != graph_traits< Graph >::null_vertex()) + { + chosen_case = detail::BM_CASE_B; + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] = false; + forbidden_edge[e] = outer_face_edge[e]; + } + + goal_edge[w_handle.first_edge()] = true; + goal_edge[w_handle.second_edge()] = true; + + z = kuratowski_walkup( + v, forbidden_edge, goal_edge, is_embedded, z_v_path); + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + forbidden_edge[*ei] = outer_face_edge[*ei]; + } + + typename std::vector< edge_t >::iterator pi, pi_end; + pi_end = z_v_path.end(); + for (pi = z_v_path.begin(); pi != pi_end; ++pi) + { + goal_edge[*pi] = true; + } + + w_ancestor = v; + vertex_t w_endpoint = graph_traits< Graph >::null_vertex(); + + while (w_endpoint == graph_traits< Graph >::null_vertex()) + { + w_ancestor = dfs_parent[w_ancestor]; + w_endpoint = kuratowski_walkup( + w_ancestor, forbidden_edge, goal_edge, is_embedded, w_path); + } + + // We really want both the w walkup and the z walkup to finish on + // exactly the same edge, but for convenience (since we don't have + // control over which side of a bicomp a walkup moves up) we've + // defined the walkup to either end at w_handle.first_edge() or + // w_handle.second_edge(). If both walkups ended at different edges, + // we'll do a little surgery on the w walkup path to make it follow + // the other side of the final bicomp. + + if ((w_path.back() == w_handle.first_edge() + && z_v_path.back() == w_handle.second_edge()) + || (w_path.back() == w_handle.second_edge() + && z_v_path.back() == w_handle.first_edge())) + { + walkup_itr_t wi, wi_end; + edge_t final_edge = w_path.back(); + vertex_t anchor = source(final_edge, g) == w_handle.get_anchor() + ? target(final_edge, g) + : source(final_edge, g); + if (face_handles[anchor].first_edge() == final_edge) + wi = walkup_itr_t(anchor, face_handles, second_side()); + else + wi = walkup_itr_t(anchor, face_handles, first_side()); + + w_path.pop_back(); + + for (; wi != wi_end; ++wi) + { + edge_t e(*wi); + if (w_path.back() == e) + w_path.pop_back(); + else + w_path.push_back(e); + } + } + } + else + { + + // We need to find a valid z, since the x-y path re-defines the + // lower face, and the z we found earlier may now be on the upper + // face. + + chosen_case = detail::BM_CASE_E; + + // The z we've used so far is just an externally active vertex on + // the lower face path, but may not be the z we need for a case C, + // D, or E subgraph. the z we need now is any externally active + // vertex on the lower face path with both old_face_handles edges on + // the outer face. Since we know an x-y path exists, such a z must + // also exist. + + // TODO: find this z in the first place. + + // find the new z + + for (face_itr = x_lower_itr; *face_itr != y; ++face_itr) + { + vertex_t possible_z(*face_itr); + if (pertinent(possible_z, v) + && outer_face_edge[face_handles[possible_z] + .old_first_edge()] + && outer_face_edge[face_handles[possible_z] + .old_second_edge()]) + { + z = possible_z; + break; + } + } + + // find x-y path, and a w if one exists. + + if (externally_active(z, v)) + w = z; + + typedef typename face_edge_iterator< single_side, + previous_iteration >::type old_face_iterator_t; + + old_face_iterator_t first_old_face_itr( + z, face_handles, first_side()); + old_face_iterator_t second_old_face_itr( + z, face_handles, second_side()); + old_face_iterator_t old_face_itr, old_face_end; + + std::vector< old_face_iterator_t > old_face_iterators; + old_face_iterators.push_back(first_old_face_itr); + old_face_iterators.push_back(second_old_face_itr); + + std::vector< bool > x_y_path_vertex_vector(num_vertices(g), false); + vertex_to_bool_map_t x_y_path_vertex( + x_y_path_vertex_vector.begin(), vm); + + typename std::vector< old_face_iterator_t >::iterator of_itr, + of_itr_end; + of_itr_end = old_face_iterators.end(); + for (of_itr = old_face_iterators.begin(); of_itr != of_itr_end; + ++of_itr) + { + + old_face_itr = *of_itr; + + vertex_t previous_vertex; + bool seen_x_or_y = false; + vertex_t current_vertex = z; + for (; old_face_itr != old_face_end; ++old_face_itr) + { + edge_t e(*old_face_itr); + previous_vertex = current_vertex; + current_vertex = source(e, g) == current_vertex + ? target(e, g) + : source(e, g); + + if (current_vertex == x || current_vertex == y) + seen_x_or_y = true; + + if (w == graph_traits< Graph >::null_vertex() + && externally_active(current_vertex, v) + && outer_face_edge[e] + && outer_face_edge[*boost::next(old_face_itr)] + && !seen_x_or_y) + { + w = current_vertex; + } + + if (!outer_face_edge[e]) + { + if (!upper_face_vertex[current_vertex] + && !lower_face_vertex[current_vertex]) + { + x_y_path_vertex[current_vertex] = true; + } + + is_in_subgraph[e] = true; + if (upper_face_vertex[source(e, g)] + || lower_face_vertex[source(e, g)]) + { + if (first_x_y_path_endpoint + == graph_traits< Graph >::null_vertex()) + first_x_y_path_endpoint = source(e, g); + else + second_x_y_path_endpoint = source(e, g); + } + if (upper_face_vertex[target(e, g)] + || lower_face_vertex[target(e, g)]) + { + if (first_x_y_path_endpoint + == graph_traits< Graph >::null_vertex()) + first_x_y_path_endpoint = target(e, g); + else + second_x_y_path_endpoint = target(e, g); + } + } + else if (previous_vertex == x || previous_vertex == y) + { + chosen_case = detail::BM_CASE_C; + } + } + } + + // Look for a case D - one of v's embedded edges will connect to the + // x-y path along an inner face path. + + // First, get a list of all of v's embedded child edges + + out_edge_iterator_t v_edge_itr, v_edge_end; + for (boost::tie(v_edge_itr, v_edge_end) = out_edges(v, g); + v_edge_itr != v_edge_end; ++v_edge_itr) + { + edge_t embedded_edge(*v_edge_itr); + + if (!is_embedded[embedded_edge] + || embedded_edge == dfs_parent_edge[v]) + continue; + + case_d_edges.push_back(embedded_edge); + + vertex_t current_vertex = source(embedded_edge, g) == v + ? target(embedded_edge, g) + : source(embedded_edge, g); + + typename face_edge_iterator<>::type internal_face_itr, + internal_face_end; + if (face_handles[current_vertex].first_vertex() == v) + { + internal_face_itr = typename face_edge_iterator<>::type( + current_vertex, face_handles, second_side()); + } + else + { + internal_face_itr = typename face_edge_iterator<>::type( + current_vertex, face_handles, first_side()); + } + + while (internal_face_itr != internal_face_end + && !outer_face_edge[*internal_face_itr] + && !x_y_path_vertex[current_vertex]) + { + edge_t e(*internal_face_itr); + case_d_edges.push_back(e); + current_vertex = source(e, g) == current_vertex + ? target(e, g) + : source(e, g); + ++internal_face_itr; + } + + if (x_y_path_vertex[current_vertex]) + { + chosen_case = detail::BM_CASE_D; + break; + } + else + { + case_d_edges.clear(); + } + } + } + + if (chosen_case != detail::BM_CASE_B + && chosen_case != detail::BM_CASE_A) + { + + // Finding z and w. + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + edge_t e(*ei); + goal_edge[e] = !outer_face_edge[e] + && (source(e, g) == z || target(e, g) == z); + forbidden_edge[e] = outer_face_edge[e]; + } + + kuratowski_walkup( + v, forbidden_edge, goal_edge, is_embedded, z_v_path); + + if (chosen_case == detail::BM_CASE_E) + { + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + { + forbidden_edge[*ei] = outer_face_edge[*ei]; + goal_edge[*ei] = !outer_face_edge[*ei] + && (source(*ei, g) == w || target(*ei, g) == w); + } + + for (boost::tie(oei, oei_end) = out_edges(w, g); oei != oei_end; + ++oei) + { + if (!outer_face_edge[*oei]) + goal_edge[*oei] = true; + } + + typename std::vector< edge_t >::iterator pi, pi_end; + pi_end = z_v_path.end(); + for (pi = z_v_path.begin(); pi != pi_end; ++pi) + { + goal_edge[*pi] = true; + } + + w_ancestor = v; + vertex_t w_endpoint = graph_traits< Graph >::null_vertex(); + + while (w_endpoint == graph_traits< Graph >::null_vertex()) + { + w_ancestor = dfs_parent[w_ancestor]; + w_endpoint = kuratowski_walkup(w_ancestor, forbidden_edge, + goal_edge, is_embedded, w_path); + } + } + } + + // We're done isolating the Kuratowski subgraph at this point - + // but there's still some cleaning up to do. + + // Update is_in_subgraph with the paths we just found + + xi_end = x_external_path.end(); + for (xi = x_external_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = y_external_path.end(); + for (xi = y_external_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = z_v_path.end(); + for (xi = z_v_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = case_d_edges.end(); + for (xi = case_d_edges.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + xi_end = w_path.end(); + for (xi = w_path.begin(); xi != xi_end; ++xi) + is_in_subgraph[*xi] = true; + + child = bicomp_root; + parent = dfs_parent[child]; + while (child != parent) + { + is_in_subgraph[dfs_parent_edge[child]] = true; + boost::tie(parent, child) + = std::make_pair(dfs_parent[parent], parent); + } + + // At this point, we've already isolated the Kuratowski subgraph and + // collected all of the edges that compose it in the is_in_subgraph + // property map. But we want the verification of such a subgraph to be + // a deterministic process, and we can simplify the function + // is_kuratowski_subgraph by cleaning up some edges here. + + if (chosen_case == detail::BM_CASE_B) + { + is_in_subgraph[dfs_parent_edge[v]] = false; + } + else if (chosen_case == detail::BM_CASE_C) + { + // In a case C subgraph, at least one of the x-y path endpoints + // (call it alpha) is above either x or y on the outer face. The + // other endpoint may be attached at x or y OR above OR below. In + // any of these three cases, we can form a K_3_3 by removing the + // edge attached to v on the outer face that is NOT on the path to + // alpha. + + typename face_vertex_iterator< single_side, follow_visitor >::type + face_itr, + face_end; + if (face_handles[v_dfchild_handle.first_vertex()].first_edge() + == v_dfchild_handle.first_edge()) + { + face_itr = typename face_vertex_iterator< single_side, + follow_visitor >::type(v_dfchild_handle.first_vertex(), + face_handles, second_side()); + } + else + { + face_itr = typename face_vertex_iterator< single_side, + follow_visitor >::type(v_dfchild_handle.first_vertex(), + face_handles, first_side()); + } + + for (; true; ++face_itr) + { + vertex_t current_vertex(*face_itr); + if (current_vertex == x || current_vertex == y) + { + is_in_subgraph[v_dfchild_handle.first_edge()] = false; + break; + } + else if (current_vertex == first_x_y_path_endpoint + || current_vertex == second_x_y_path_endpoint) + { + is_in_subgraph[v_dfchild_handle.second_edge()] = false; + break; + } + } + } + else if (chosen_case == detail::BM_CASE_D) + { + // Need to remove both of the edges adjacent to v on the outer face. + // remove the connecting edges from v to bicomp, then + // is_kuratowski_subgraph will shrink vertices of degree 1 + // automatically... + + is_in_subgraph[v_dfchild_handle.first_edge()] = false; + is_in_subgraph[v_dfchild_handle.second_edge()] = false; + } + else if (chosen_case == detail::BM_CASE_E) + { + // Similarly to case C, if the endpoints of the x-y path are both + // below x and y, we should remove an edge to allow the subgraph to + // contract to a K_3_3. + + if ((first_x_y_path_endpoint != x && first_x_y_path_endpoint != y) + || (second_x_y_path_endpoint != x + && second_x_y_path_endpoint != y)) + { + is_in_subgraph[dfs_parent_edge[v]] = false; + + vertex_t deletion_endpoint, other_endpoint; + if (lower_face_vertex[first_x_y_path_endpoint]) + { + deletion_endpoint = second_x_y_path_endpoint; + other_endpoint = first_x_y_path_endpoint; + } + else + { + deletion_endpoint = first_x_y_path_endpoint; + other_endpoint = second_x_y_path_endpoint; + } + + typename face_edge_iterator<>::type face_itr, face_end; + + bool found_other_endpoint = false; + for (face_itr = typename face_edge_iterator<>::type( + deletion_endpoint, face_handles, first_side()); + face_itr != face_end; ++face_itr) + { + edge_t e(*face_itr); + if (source(e, g) == other_endpoint + || target(e, g) == other_endpoint) + { + found_other_endpoint = true; + break; + } + } + + if (found_other_endpoint) + { + is_in_subgraph[face_handles[deletion_endpoint].first_edge()] + = false; + } + else + { + is_in_subgraph[face_handles[deletion_endpoint] + .second_edge()] + = false; + } + } + } + + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + if (is_in_subgraph[*ei]) + *o_itr = *ei; + } + + template < typename EdgePermutation > + void make_edge_permutation(EdgePermutation perm) + { + vertex_iterator_t vi, vi_end; + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + perm[v].clear(); + face_handles[v].get_list(std::back_inserter(perm[v])); + } + } + +private: + const Graph& g; + VertexIndexMap vm; + + vertex_t kuratowski_v; + vertex_t kuratowski_x; + vertex_t kuratowski_y; + + vertex_list_t garbage; // we delete items from linked lists by + // splicing them into garbage + + // only need these two for kuratowski subgraph isolation + std::vector< vertex_t > current_merge_points; + std::vector< edge_t > embedded_edges; + + // property map storage + std::vector< v_size_t > low_point_vector; + std::vector< vertex_t > dfs_parent_vector; + std::vector< v_size_t > dfs_number_vector; + std::vector< v_size_t > least_ancestor_vector; + std::vector< face_handle_list_ptr_t > pertinent_roots_vector; + std::vector< v_size_t > backedge_flag_vector; + std::vector< v_size_t > visited_vector; + std::vector< face_handle_t > face_handles_vector; + std::vector< face_handle_t > dfs_child_handles_vector; + std::vector< vertex_list_ptr_t > separated_dfs_child_list_vector; + std::vector< typename vertex_list_t::iterator > + separated_node_in_parent_list_vector; + std::vector< vertex_t > canonical_dfs_child_vector; + std::vector< bool > flipped_vector; + std::vector< edge_vector_t > backedges_vector; + edge_vector_t self_loops; + std::vector< edge_t > dfs_parent_edge_vector; + vertex_vector_t vertices_by_dfs_num; + + // property maps + vertex_to_v_size_map_t low_point; + vertex_to_vertex_map_t dfs_parent; + vertex_to_v_size_map_t dfs_number; + vertex_to_v_size_map_t least_ancestor; + vertex_to_face_handle_list_ptr_map_t pertinent_roots; + vertex_to_v_size_map_t backedge_flag; + vertex_to_v_size_map_t visited; + vertex_to_face_handle_map_t face_handles; + vertex_to_face_handle_map_t dfs_child_handles; + vertex_to_vertex_list_ptr_map_t separated_dfs_child_list; + vertex_to_separated_node_map_t separated_node_in_parent_list; + vertex_to_vertex_map_t canonical_dfs_child; + vertex_to_bool_map_t flipped; + vertex_to_edge_vector_map_t backedges; + vertex_to_edge_map_t dfs_parent_edge; // only need for kuratowski + + merge_stack_t merge_stack; +}; + +} // namespace boost + +#endif //__BOYER_MYRVOLD_IMPL_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/planar_detail/bucket_sort.hpp b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/bucket_sort.hpp new file mode 100644 index 0000000000..15b932b9fd --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/bucket_sort.hpp @@ -0,0 +1,118 @@ +//======================================================================= +// Copyright 2007 Aaron Windsor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef __BUCKET_SORT_HPP__ +#define __BUCKET_SORT_HPP__ + +#include <vector> +#include <algorithm> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +template < typename ItemToRankMap > struct rank_comparison +{ + rank_comparison(ItemToRankMap arg_itrm) : itrm(arg_itrm) {} + + template < typename Item > bool operator()(Item x, Item y) const + { + return get(itrm, x) < get(itrm, y); + } + +private: + ItemToRankMap itrm; +}; + +template < typename TupleType, int N, + typename PropertyMapWrapper = identity_property_map > +struct property_map_tuple_adaptor +: public put_get_helper< typename PropertyMapWrapper::value_type, + property_map_tuple_adaptor< TupleType, N, PropertyMapWrapper > > +{ + typedef typename PropertyMapWrapper::reference reference; + typedef typename PropertyMapWrapper::value_type value_type; + typedef TupleType key_type; + typedef readable_property_map_tag category; + + property_map_tuple_adaptor() {} + + property_map_tuple_adaptor(PropertyMapWrapper wrapper_map) + : m_wrapper_map(wrapper_map) + { + } + + inline value_type operator[](const key_type& x) const + { + return get(m_wrapper_map, get< n >(x)); + } + + static const int n = N; + PropertyMapWrapper m_wrapper_map; +}; + +// This function sorts a sequence of n items by their ranks in linear time, +// given that all ranks are in the range [0, range). This sort is stable. +template < typename ForwardIterator, typename ItemToRankMap, typename SizeType > +void bucket_sort(ForwardIterator begin, ForwardIterator end, ItemToRankMap rank, + SizeType range = 0) +{ +#ifdef BOOST_GRAPH_PREFER_STD_LIB + std::stable_sort(begin, end, rank_comparison< ItemToRankMap >(rank)); +#else + typedef std::vector< + typename boost::property_traits< ItemToRankMap >::key_type > + vector_of_values_t; + typedef std::vector< vector_of_values_t > vector_of_vectors_t; + + if (!range) + { + rank_comparison< ItemToRankMap > cmp(rank); + ForwardIterator max_by_rank = std::max_element(begin, end, cmp); + if (max_by_rank == end) + return; + range = get(rank, *max_by_rank) + 1; + } + + vector_of_vectors_t temp_values(range); + + for (ForwardIterator itr = begin; itr != end; ++itr) + { + temp_values[get(rank, *itr)].push_back(*itr); + } + + ForwardIterator orig_seq_itr = begin; + typename vector_of_vectors_t::iterator itr_end = temp_values.end(); + for (typename vector_of_vectors_t::iterator itr = temp_values.begin(); + itr != itr_end; ++itr) + { + typename vector_of_values_t::iterator jtr_end = itr->end(); + for (typename vector_of_values_t::iterator jtr = itr->begin(); + jtr != jtr_end; ++jtr) + { + *orig_seq_itr = *jtr; + ++orig_seq_itr; + } + } +#endif +} + +template < typename ForwardIterator, typename ItemToRankMap > +void bucket_sort(ForwardIterator begin, ForwardIterator end, ItemToRankMap rank) +{ + bucket_sort(begin, end, rank, 0); +} + +template < typename ForwardIterator > +void bucket_sort(ForwardIterator begin, ForwardIterator end) +{ + bucket_sort(begin, end, identity_property_map()); +} + +} // namespace boost + +#endif //__BUCKET_SORT_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/planar_detail/face_handles.hpp b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/face_handles.hpp new file mode 100644 index 0000000000..1ea7efcb46 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/face_handles.hpp @@ -0,0 +1,453 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __FACE_HANDLES_HPP__ +#define __FACE_HANDLES_HPP__ + +#include <list> +#include <boost/graph/graph_traits.hpp> +#include <boost/shared_ptr.hpp> + +// A "face handle" is an optimization meant to serve two purposes in +// the implementation of the Boyer-Myrvold planarity test: (1) it holds +// the partial planar embedding of a particular vertex as it's being +// constructed, and (2) it allows for efficient traversal around the +// outer face of the partial embedding at that particular vertex. A face +// handle is lightweight, just a shared pointer to the actual implementation, +// since it is passed around/copied liberally in the algorithm. It consists +// of an "anchor" (the actual vertex it's associated with) as well as a +// sequence of edges. The functions first_vertex/second_vertex and +// first_edge/second_edge allow fast access to the beginning and end of the +// stored sequence, which allows one to traverse the outer face of the partial +// planar embedding as it's being created. +// +// There are some policies below that define the contents of the face handles: +// in the case no embedding is needed (for example, if one just wants to use +// the Boyer-Myrvold algorithm as a true/false test for planarity, the +// no_embedding class can be passed as the StoreEmbedding policy. Otherwise, +// either std_list (which uses as std::list) or recursive_lazy_list can be +// passed as this policy. recursive_lazy_list has the best theoretical +// performance (O(n) for a sequence of interleaved concatenations and reversals +// of the underlying list), but I've noticed little difference between std_list +// and recursive_lazy_list in my tests, even though using std_list changes +// the worst-case complexity of the planarity test to O(n^2) +// +// Another policy is StoreOldHandlesPolicy, which specifies whether or not +// to keep a record of the previous first/second vertex/edge - this is needed +// if a Kuratowski subgraph needs to be isolated. + +namespace boost +{ +namespace graph +{ + namespace detail + { + + // face handle policies + + // EmbeddingStorage policy + struct store_embedding + { + }; + struct recursive_lazy_list : public store_embedding + { + }; + struct std_list : public store_embedding + { + }; + struct no_embedding + { + }; + + // StoreOldHandlesPolicy + struct store_old_handles + { + }; + struct no_old_handles + { + }; + + template < typename DataType > struct lazy_list_node + { + typedef shared_ptr< lazy_list_node< DataType > > ptr_t; + + lazy_list_node(const DataType& data) + : m_reversed(false), m_data(data), m_has_data(true) + { + } + + lazy_list_node(ptr_t left_child, ptr_t right_child) + : m_reversed(false) + , m_has_data(false) + , m_left_child(left_child) + , m_right_child(right_child) + { + } + + bool m_reversed; + DataType m_data; + bool m_has_data; + shared_ptr< lazy_list_node > m_left_child; + shared_ptr< lazy_list_node > m_right_child; + }; + + template < typename StoreOldHandlesPolicy, typename Vertex, + typename Edge > + struct old_handles_storage; + + template < typename Vertex, typename Edge > + struct old_handles_storage< store_old_handles, Vertex, Edge > + { + Vertex first_vertex; + Vertex second_vertex; + Edge first_edge; + Edge second_edge; + }; + + template < typename Vertex, typename Edge > + struct old_handles_storage< no_old_handles, Vertex, Edge > + { + }; + + template < typename StoreEmbeddingPolicy, typename Edge > + struct edge_list_storage; + + template < typename Edge > + struct edge_list_storage< no_embedding, Edge > + { + typedef void type; + + void push_back(Edge) {} + void push_front(Edge) {} + void reverse() {} + void concat_front(edge_list_storage< no_embedding, Edge >) {} + void concat_back(edge_list_storage< no_embedding, Edge >) {} + template < typename OutputIterator > void get_list(OutputIterator) + { + } + }; + + template < typename Edge > + struct edge_list_storage< recursive_lazy_list, Edge > + { + typedef lazy_list_node< Edge > node_type; + typedef shared_ptr< node_type > type; + type value; + + void push_back(Edge e) + { + type new_node(new node_type(e)); + value = type(new node_type(value, new_node)); + } + + void push_front(Edge e) + { + type new_node(new node_type(e)); + value = type(new node_type(new_node, value)); + } + + void reverse() { value->m_reversed = !value->m_reversed; } + + void concat_front( + edge_list_storage< recursive_lazy_list, Edge > other) + { + value = type(new node_type(other.value, value)); + } + + void concat_back( + edge_list_storage< recursive_lazy_list, Edge > other) + { + value = type(new node_type(value, other.value)); + } + + template < typename OutputIterator > + void get_list(OutputIterator out) + { + get_list_helper(out, value); + } + + private: + template < typename OutputIterator > + void get_list_helper( + OutputIterator o_itr, type root, bool flipped = false) + { + if (!root) + return; + + if (root->m_has_data) + *o_itr = root->m_data; + + if ((flipped && !root->m_reversed) + || (!flipped && root->m_reversed)) + { + get_list_helper(o_itr, root->m_right_child, true); + get_list_helper(o_itr, root->m_left_child, true); + } + else + { + get_list_helper(o_itr, root->m_left_child, false); + get_list_helper(o_itr, root->m_right_child, false); + } + } + }; + + template < typename Edge > struct edge_list_storage< std_list, Edge > + { + typedef std::list< Edge > type; + type value; + + void push_back(Edge e) { value.push_back(e); } + + void push_front(Edge e) { value.push_front(e); } + + void reverse() { value.reverse(); } + + void concat_front(edge_list_storage< std_list, Edge > other) + { + value.splice(value.begin(), other.value); + } + + void concat_back(edge_list_storage< std_list, Edge > other) + { + value.splice(value.end(), other.value); + } + + template < typename OutputIterator > + void get_list(OutputIterator out) + { + std::copy(value.begin(), value.end(), out); + } + }; + + template < typename Graph, typename StoreOldHandlesPolicy, + typename StoreEmbeddingPolicy > + struct face_handle_impl + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef + typename edge_list_storage< StoreEmbeddingPolicy, edge_t >::type + edge_list_storage_t; + + face_handle_impl() + : cached_first_vertex(graph_traits< Graph >::null_vertex()) + , cached_second_vertex(graph_traits< Graph >::null_vertex()) + , true_first_vertex(graph_traits< Graph >::null_vertex()) + , true_second_vertex(graph_traits< Graph >::null_vertex()) + , anchor(graph_traits< Graph >::null_vertex()) + { + initialize_old_vertices_dispatch(StoreOldHandlesPolicy()); + } + + void initialize_old_vertices_dispatch(store_old_handles) + { + old_handles.first_vertex = graph_traits< Graph >::null_vertex(); + old_handles.second_vertex + = graph_traits< Graph >::null_vertex(); + } + + void initialize_old_vertices_dispatch(no_old_handles) {} + + vertex_t cached_first_vertex; + vertex_t cached_second_vertex; + vertex_t true_first_vertex; + vertex_t true_second_vertex; + vertex_t anchor; + edge_t cached_first_edge; + edge_t cached_second_edge; + + edge_list_storage< StoreEmbeddingPolicy, edge_t > edge_list; + old_handles_storage< StoreOldHandlesPolicy, vertex_t, edge_t > + old_handles; + }; + + template < typename Graph, + typename StoreOldHandlesPolicy = store_old_handles, + typename StoreEmbeddingPolicy = recursive_lazy_list > + class face_handle + { + public: + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef face_handle_impl< Graph, StoreOldHandlesPolicy, + StoreEmbeddingPolicy > + impl_t; + typedef face_handle< Graph, StoreOldHandlesPolicy, + StoreEmbeddingPolicy > + self_t; + + face_handle(vertex_t anchor = graph_traits< Graph >::null_vertex()) + : pimpl(new impl_t()) + { + pimpl->anchor = anchor; + } + + face_handle(vertex_t anchor, edge_t initial_edge, const Graph& g) + : pimpl(new impl_t()) + { + vertex_t s(source(initial_edge, g)); + vertex_t t(target(initial_edge, g)); + vertex_t other_vertex = s == anchor ? t : s; + pimpl->anchor = anchor; + pimpl->cached_first_edge = initial_edge; + pimpl->cached_second_edge = initial_edge; + pimpl->cached_first_vertex = other_vertex; + pimpl->cached_second_vertex = other_vertex; + pimpl->true_first_vertex = other_vertex; + pimpl->true_second_vertex = other_vertex; + + pimpl->edge_list.push_back(initial_edge); + store_old_face_handles_dispatch(StoreOldHandlesPolicy()); + } + + // default copy construction, assignment okay. + + void push_first(edge_t e, const Graph& g) + { + pimpl->edge_list.push_front(e); + pimpl->cached_first_vertex = pimpl->true_first_vertex + = source(e, g) == pimpl->anchor ? target(e, g) + : source(e, g); + pimpl->cached_first_edge = e; + } + + void push_second(edge_t e, const Graph& g) + { + pimpl->edge_list.push_back(e); + pimpl->cached_second_vertex = pimpl->true_second_vertex + = source(e, g) == pimpl->anchor ? target(e, g) + : source(e, g); + pimpl->cached_second_edge = e; + } + + inline void store_old_face_handles() + { + store_old_face_handles_dispatch(StoreOldHandlesPolicy()); + } + + inline vertex_t first_vertex() const + { + return pimpl->cached_first_vertex; + } + + inline vertex_t second_vertex() const + { + return pimpl->cached_second_vertex; + } + + inline vertex_t true_first_vertex() const + { + return pimpl->true_first_vertex; + } + + inline vertex_t true_second_vertex() const + { + return pimpl->true_second_vertex; + } + + inline vertex_t old_first_vertex() const + { + return pimpl->old_handles.first_vertex; + } + + inline vertex_t old_second_vertex() const + { + return pimpl->old_handles.second_vertex; + } + + inline edge_t old_first_edge() const + { + return pimpl->old_handles.first_edge; + } + + inline edge_t old_second_edge() const + { + return pimpl->old_handles.second_edge; + } + + inline edge_t first_edge() const + { + return pimpl->cached_first_edge; + } + + inline edge_t second_edge() const + { + return pimpl->cached_second_edge; + } + + inline vertex_t get_anchor() const { return pimpl->anchor; } + + void glue_first_to_second(face_handle< Graph, StoreOldHandlesPolicy, + StoreEmbeddingPolicy >& bottom) + { + pimpl->edge_list.concat_front(bottom.pimpl->edge_list); + pimpl->true_first_vertex = bottom.pimpl->true_first_vertex; + pimpl->cached_first_vertex = bottom.pimpl->cached_first_vertex; + pimpl->cached_first_edge = bottom.pimpl->cached_first_edge; + } + + void glue_second_to_first(face_handle< Graph, StoreOldHandlesPolicy, + StoreEmbeddingPolicy >& bottom) + { + pimpl->edge_list.concat_back(bottom.pimpl->edge_list); + pimpl->true_second_vertex = bottom.pimpl->true_second_vertex; + pimpl->cached_second_vertex + = bottom.pimpl->cached_second_vertex; + pimpl->cached_second_edge = bottom.pimpl->cached_second_edge; + } + + void flip() + { + pimpl->edge_list.reverse(); + std::swap(pimpl->true_first_vertex, pimpl->true_second_vertex); + std::swap( + pimpl->cached_first_vertex, pimpl->cached_second_vertex); + std::swap(pimpl->cached_first_edge, pimpl->cached_second_edge); + } + + template < typename OutputIterator > + void get_list(OutputIterator o_itr) + { + pimpl->edge_list.get_list(o_itr); + } + + void reset_vertex_cache() + { + pimpl->cached_first_vertex = pimpl->true_first_vertex; + pimpl->cached_second_vertex = pimpl->true_second_vertex; + } + + inline void set_first_vertex(vertex_t v) + { + pimpl->cached_first_vertex = v; + } + + inline void set_second_vertex(vertex_t v) + { + pimpl->cached_second_vertex = v; + } + + private: + void store_old_face_handles_dispatch(store_old_handles) + { + pimpl->old_handles.first_vertex = pimpl->true_first_vertex; + pimpl->old_handles.second_vertex = pimpl->true_second_vertex; + pimpl->old_handles.first_edge = pimpl->cached_first_edge; + pimpl->old_handles.second_edge = pimpl->cached_second_edge; + } + + void store_old_face_handles_dispatch(no_old_handles) {} + + boost::shared_ptr< impl_t > pimpl; + }; + + } /* namespace detail */ +} /* namespace graph */ +} /* namespace boost */ + +#endif //__FACE_HANDLES_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/planar_detail/face_iterators.hpp b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/face_iterators.hpp new file mode 100644 index 0000000000..f1a1c333ce --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/planar_detail/face_iterators.hpp @@ -0,0 +1,332 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __FACE_ITERATORS_HPP__ +#define __FACE_ITERATORS_HPP__ + +#include <boost/iterator/iterator_facade.hpp> +#include <boost/mpl/bool.hpp> +#include <boost/graph/graph_traits.hpp> + +namespace boost +{ + +// tags for defining traversal properties + +// VisitorType +struct lead_visitor +{ +}; +struct follow_visitor +{ +}; + +// TraversalType +struct single_side +{ +}; +struct both_sides +{ +}; + +// TraversalSubType +struct first_side +{ +}; // for single_side +struct second_side +{ +}; // for single_side +struct alternating +{ +}; // for both_sides + +// Time +struct current_iteration +{ +}; +struct previous_iteration +{ +}; + +// Why TraversalType AND TraversalSubType? TraversalSubType is a function +// template parameter passed in to the constructor of the face iterator, +// whereas TraversalType is a class template parameter. This lets us decide +// at runtime whether to move along the first or second side of a bicomp (by +// assigning a face_iterator that has been constructed with TraversalSubType +// = first_side or second_side to a face_iterator variable) without any of +// the virtual function overhead that comes with implementing this +// functionality as a more structured form of type erasure. It also allows +// a single face_iterator to be the end iterator of two iterators traversing +// both sides of a bicomp. + +// ValueType is either graph_traits<Graph>::vertex_descriptor +// or graph_traits<Graph>::edge_descriptor + +// forward declaration (defining defaults) +template < typename Graph, typename FaceHandlesMap, typename ValueType, + typename BicompSideToTraverse = single_side, + typename VisitorType = lead_visitor, typename Time = current_iteration > +class face_iterator; + +template < typename Graph, bool StoreEdge > struct edge_storage +{ +}; + +template < typename Graph > struct edge_storage< Graph, true > +{ + typename graph_traits< Graph >::edge_descriptor value; +}; + +// specialization for TraversalType = traverse_vertices +template < typename Graph, typename FaceHandlesMap, typename ValueType, + typename TraversalType, typename VisitorType, typename Time > + +class face_iterator : public boost::iterator_facade< + face_iterator< Graph, FaceHandlesMap, ValueType, + TraversalType, VisitorType, Time >, + ValueType, boost::forward_traversal_tag, ValueType > +{ +public: + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef face_iterator< Graph, FaceHandlesMap, ValueType, TraversalType, + VisitorType, Time > + self; + typedef typename FaceHandlesMap::value_type face_handle_t; + + face_iterator() + : m_lead(graph_traits< Graph >::null_vertex()) + , m_follow(graph_traits< Graph >::null_vertex()) + { + } + + template < typename TraversalSubType > + face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles, + TraversalSubType traversal_type) + : m_follow(anchor_handle.get_anchor()), m_face_handles(face_handles) + { + set_lead_dispatch(anchor_handle, traversal_type); + } + + template < typename TraversalSubType > + face_iterator(vertex_t anchor, FaceHandlesMap face_handles, + TraversalSubType traversal_type) + : m_follow(anchor), m_face_handles(face_handles) + { + set_lead_dispatch(m_face_handles[anchor], traversal_type); + } + +private: + friend class boost::iterator_core_access; + + inline vertex_t get_first_vertex( + face_handle_t anchor_handle, current_iteration) + { + return anchor_handle.first_vertex(); + } + + inline vertex_t get_second_vertex( + face_handle_t anchor_handle, current_iteration) + { + return anchor_handle.second_vertex(); + } + + inline vertex_t get_first_vertex( + face_handle_t anchor_handle, previous_iteration) + { + return anchor_handle.old_first_vertex(); + } + + inline vertex_t get_second_vertex( + face_handle_t anchor_handle, previous_iteration) + { + return anchor_handle.old_second_vertex(); + } + + inline void set_lead_dispatch(face_handle_t anchor_handle, first_side) + { + m_lead = get_first_vertex(anchor_handle, Time()); + set_edge_to_first_dispatch(anchor_handle, ValueType(), Time()); + } + + inline void set_lead_dispatch(face_handle_t anchor_handle, second_side) + { + m_lead = get_second_vertex(anchor_handle, Time()); + set_edge_to_second_dispatch(anchor_handle, ValueType(), Time()); + } + + inline void set_edge_to_first_dispatch( + face_handle_t anchor_handle, edge_t, current_iteration) + { + m_edge.value = anchor_handle.first_edge(); + } + + inline void set_edge_to_second_dispatch( + face_handle_t anchor_handle, edge_t, current_iteration) + { + m_edge.value = anchor_handle.second_edge(); + } + + inline void set_edge_to_first_dispatch( + face_handle_t anchor_handle, edge_t, previous_iteration) + { + m_edge.value = anchor_handle.old_first_edge(); + } + + inline void set_edge_to_second_dispatch( + face_handle_t anchor_handle, edge_t, previous_iteration) + { + m_edge.value = anchor_handle.old_second_edge(); + } + + template < typename T > + inline void set_edge_to_first_dispatch(face_handle_t, vertex_t, T) + { + } + + template < typename T > + inline void set_edge_to_second_dispatch(face_handle_t, vertex_t, T) + { + } + + void increment() + { + face_handle_t curr_face_handle(m_face_handles[m_lead]); + vertex_t first = get_first_vertex(curr_face_handle, Time()); + vertex_t second = get_second_vertex(curr_face_handle, Time()); + if (first == m_follow) + { + m_follow = m_lead; + set_edge_to_second_dispatch(curr_face_handle, ValueType(), Time()); + m_lead = second; + } + else if (second == m_follow) + { + m_follow = m_lead; + set_edge_to_first_dispatch(curr_face_handle, ValueType(), Time()); + m_lead = first; + } + else + m_lead = m_follow = graph_traits< Graph >::null_vertex(); + } + + bool equal(self const& other) const + { + return m_lead == other.m_lead && m_follow == other.m_follow; + } + + ValueType dereference() const + { + return dereference_dispatch(VisitorType(), ValueType()); + } + + inline ValueType dereference_dispatch(lead_visitor, vertex_t) const + { + return m_lead; + } + + inline ValueType dereference_dispatch(follow_visitor, vertex_t) const + { + return m_follow; + } + + inline ValueType dereference_dispatch(lead_visitor, edge_t) const + { + return m_edge.value; + } + + inline ValueType dereference_dispatch(follow_visitor, edge_t) const + { + return m_edge.value; + } + + vertex_t m_lead; + vertex_t m_follow; + edge_storage< Graph, boost::is_same< ValueType, edge_t >::value > m_edge; + FaceHandlesMap m_face_handles; +}; + +template < typename Graph, typename FaceHandlesMap, typename ValueType, + typename VisitorType, typename Time > +class face_iterator< Graph, FaceHandlesMap, ValueType, both_sides, VisitorType, + Time > +: public boost::iterator_facade< face_iterator< Graph, FaceHandlesMap, + ValueType, both_sides, VisitorType, Time >, + ValueType, boost::forward_traversal_tag, ValueType > +{ +public: + typedef face_iterator< Graph, FaceHandlesMap, ValueType, both_sides, + VisitorType, Time > + self; + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename FaceHandlesMap::value_type face_handle_t; + + face_iterator() {} + + face_iterator(face_handle_t anchor_handle, FaceHandlesMap face_handles) + : first_itr(anchor_handle, face_handles, first_side()) + , second_itr(anchor_handle, face_handles, second_side()) + , first_is_active(true) + , first_increment(true) + { + } + + face_iterator(vertex_t anchor, FaceHandlesMap face_handles) + : first_itr(face_handles[anchor], face_handles, first_side()) + , second_itr(face_handles[anchor], face_handles, second_side()) + , first_is_active(true) + , first_increment(true) + { + } + +private: + friend class boost::iterator_core_access; + + typedef face_iterator< Graph, FaceHandlesMap, ValueType, single_side, + follow_visitor, Time > + inner_itr_t; + + void increment() + { + if (first_increment) + { + ++first_itr; + ++second_itr; + first_increment = false; + } + else if (first_is_active) + ++first_itr; + else + ++second_itr; + first_is_active = !first_is_active; + } + + bool equal(self const& other) const + { + // Want this iterator to be equal to the "end" iterator when at least + // one of the iterators has reached the root of the current bicomp. + // This isn't ideal, but it works. + + return (first_itr == other.first_itr || second_itr == other.second_itr); + } + + ValueType dereference() const + { + return first_is_active ? *first_itr : *second_itr; + } + + inner_itr_t first_itr; + inner_itr_t second_itr; + inner_itr_t face_end; + bool first_is_active; + bool first_increment; +}; + +} /* namespace boost */ + +#endif //__FACE_ITERATORS_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/planar_face_traversal.hpp b/contrib/restricted/boost/graph/include/boost/graph/planar_face_traversal.hpp new file mode 100644 index 0000000000..00e5b3895a --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/planar_face_traversal.hpp @@ -0,0 +1,178 @@ +//======================================================================= +// Copyright (c) Aaron Windsor 2007 +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef __PLANAR_FACE_TRAVERSAL_HPP__ +#define __PLANAR_FACE_TRAVERSAL_HPP__ + +#include <vector> +#include <set> +#include <map> +#include <boost/next_prior.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> + +namespace boost +{ + +struct planar_face_traversal_visitor +{ + void begin_traversal() {} + + void begin_face() {} + + template < typename Edge > void next_edge(Edge) {} + + template < typename Vertex > void next_vertex(Vertex) {} + + void end_face() {} + + void end_traversal() {} +}; + +template < typename Graph, typename PlanarEmbedding, typename Visitor, + typename EdgeIndexMap > +void planar_face_traversal(const Graph& g, PlanarEmbedding embedding, + Visitor& visitor, EdgeIndexMap em) +{ + typedef typename graph_traits< Graph >::vertex_descriptor vertex_t; + typedef typename graph_traits< Graph >::edge_descriptor edge_t; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator_t; + typedef typename graph_traits< Graph >::edge_iterator edge_iterator_t; + typedef typename property_traits< PlanarEmbedding >::value_type + embedding_value_t; + typedef typename embedding_value_t::const_iterator embedding_iterator_t; + + typedef typename std::vector< std::set< vertex_t > > + distinguished_edge_storage_t; + typedef typename std::vector< std::map< vertex_t, edge_t > > + distinguished_edge_to_edge_storage_t; + + typedef typename boost::iterator_property_map< + typename distinguished_edge_storage_t::iterator, EdgeIndexMap > + distinguished_edge_map_t; + + typedef typename boost::iterator_property_map< + typename distinguished_edge_to_edge_storage_t::iterator, EdgeIndexMap > + distinguished_edge_to_edge_map_t; + + distinguished_edge_storage_t visited_vector(num_edges(g)); + distinguished_edge_to_edge_storage_t next_edge_vector(num_edges(g)); + + distinguished_edge_map_t visited(visited_vector.begin(), em); + distinguished_edge_to_edge_map_t next_edge(next_edge_vector.begin(), em); + + vertex_iterator_t vi, vi_end; + typename std::vector< edge_t >::iterator ei, ei_end; + edge_iterator_t fi, fi_end; + embedding_iterator_t pi, pi_begin, pi_end; + + visitor.begin_traversal(); + + // Initialize the next_edge property map. This map is initialized from the + // PlanarEmbedding so that get(next_edge, e)[v] is the edge that comes + // after e in the clockwise embedding around vertex v. + + for (boost::tie(vi, vi_end) = vertices(g); vi != vi_end; ++vi) + { + vertex_t v(*vi); + pi_begin = embedding[v].begin(); + pi_end = embedding[v].end(); + for (pi = pi_begin; pi != pi_end; ++pi) + { + edge_t e(*pi); + std::map< vertex_t, edge_t > m = get(next_edge, e); + m[v] = boost::next(pi) == pi_end ? *pi_begin : *boost::next(pi); + put(next_edge, e, m); + } + } + + // Take a copy of the edges in the graph here, since we want to accomodate + // face traversals that add edges to the graph (for triangulation, in + // particular) and don't want to use invalidated edge iterators. + // Also, while iterating over all edges in the graph, we single out + // any self-loops, which need some special treatment in the face traversal. + + std::vector< edge_t > self_loops; + std::vector< edge_t > edges_cache; + std::vector< vertex_t > vertices_in_edge; + + for (boost::tie(fi, fi_end) = edges(g); fi != fi_end; ++fi) + { + edge_t e(*fi); + edges_cache.push_back(e); + if (source(e, g) == target(e, g)) + self_loops.push_back(e); + } + + // Iterate over all edges in the graph + ei_end = edges_cache.end(); + for (ei = edges_cache.begin(); ei != ei_end; ++ei) + { + + edge_t e(*ei); + vertices_in_edge.clear(); + vertices_in_edge.push_back(source(e, g)); + vertices_in_edge.push_back(target(e, g)); + + typename std::vector< vertex_t >::iterator vi, vi_end; + vi_end = vertices_in_edge.end(); + + // Iterate over both vertices in the current edge + for (vi = vertices_in_edge.begin(); vi != vi_end; ++vi) + { + + vertex_t v(*vi); + std::set< vertex_t > e_visited = get(visited, e); + typename std::set< vertex_t >::iterator e_visited_found + = e_visited.find(v); + + if (e_visited_found == e_visited.end()) + visitor.begin_face(); + + while (e_visited.find(v) == e_visited.end()) + { + visitor.next_vertex(v); + visitor.next_edge(e); + e_visited.insert(v); + put(visited, e, e_visited); + v = source(e, g) == v ? target(e, g) : source(e, g); + e = get(next_edge, e)[v]; + e_visited = get(visited, e); + } + + if (e_visited_found == e_visited.end()) + visitor.end_face(); + } + } + + // Iterate over all self-loops, visiting them once separately + // (they've already been visited once, this visitation is for + // the "inside" of the self-loop) + + ei_end = self_loops.end(); + for (ei = self_loops.begin(); ei != ei_end; ++ei) + { + visitor.begin_face(); + visitor.next_edge(*ei); + visitor.next_vertex(source(*ei, g)); + visitor.end_face(); + } + + visitor.end_traversal(); +} + +template < typename Graph, typename PlanarEmbedding, typename Visitor > +inline void planar_face_traversal( + const Graph& g, PlanarEmbedding embedding, Visitor& visitor) +{ + planar_face_traversal(g, embedding, visitor, get(edge_index, g)); +} + +} // namespace boost + +#endif //__PLANAR_FACE_TRAVERSAL_HPP__ diff --git a/contrib/restricted/boost/graph/include/boost/graph/plod_generator.hpp b/contrib/restricted/boost/graph/include/boost/graph/plod_generator.hpp new file mode 100644 index 0000000000..1f22d39190 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/plod_generator.hpp @@ -0,0 +1,275 @@ +// Copyright 2004-2006 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_PLOD_GENERATOR_HPP +#define BOOST_GRAPH_PLOD_GENERATOR_HPP + +#include <iterator> +#include <utility> +#include <boost/random/uniform_int.hpp> +#include <boost/shared_ptr.hpp> +#include <boost/graph/graph_traits.hpp> +#include <vector> +#include <map> +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ +template < typename RandomGenerator > class out_directed_plod_iterator +{ +public: + typedef std::forward_iterator_tag iterator_category; + typedef std::pair< std::size_t, std::size_t > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; + + out_directed_plod_iterator() : gen(0), at_end(true) {} + + out_directed_plod_iterator(RandomGenerator& gen, std::size_t n, + double alpha, double beta, bool allow_self_loops) + : gen(&gen) + , n(n) + , alpha(alpha) + , beta(beta) + , allow_self_loops(allow_self_loops) + , at_end(false) + , degree(0) + , current(0, 0) + { + using std::pow; + + uniform_int< std::size_t > x(0, n - 1); + std::size_t xv = x(gen); + degree = (xv == 0 ? 0 : std::size_t(beta * pow(xv, -alpha))); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + out_directed_plod_iterator& operator++() + { + using std::pow; + + uniform_int< std::size_t > x(0, n - 1); + + // Continue stepping through source nodes until the + // (out)degree is > 0 + while (degree == 0) + { + // Step to the next source node. If we've gone past the + // number of nodes we're responsible for, we're done. + if (++current.first >= n) + { + at_end = true; + return *this; + } + + std::size_t xv = x(*gen); + degree = (xv == 0 ? 0 : std::size_t(beta * pow(xv, -alpha))); + } + + do + { + current.second = x(*gen); + } while (current.first == current.second && !allow_self_loops); + --degree; + + return *this; + } + + out_directed_plod_iterator operator++(int) + { + out_directed_plod_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const out_directed_plod_iterator& other) const + { + return at_end == other.at_end; + } + + bool operator!=(const out_directed_plod_iterator& other) const + { + return !(*this == other); + } + +private: + RandomGenerator* gen; + std::size_t n; + double alpha; + double beta; + bool allow_self_loops; + bool at_end; + std::size_t degree; + value_type current; +}; + +template < typename RandomGenerator > class undirected_plod_iterator +{ + typedef std::vector< std::pair< std::size_t, std::size_t > > out_degrees_t; + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< std::size_t, std::size_t > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; + + undirected_plod_iterator() + : gen(0), out_degrees(), degrees_left(0), allow_self_loops(false) + { + } + + undirected_plod_iterator(RandomGenerator& gen, std::size_t n, double alpha, + double beta, bool allow_self_loops = false) + : gen(&gen) + , n(n) + , out_degrees(new out_degrees_t) + , degrees_left(0) + , allow_self_loops(allow_self_loops) + { + using std::pow; + + uniform_int< std::size_t > x(0, n - 1); + for (std::size_t i = 0; i != n; ++i) + { + std::size_t xv = x(gen); + std::size_t degree + = (xv == 0 ? 0 : std::size_t(beta * pow(xv, -alpha))); + if (degree == 0) + degree = 1; + else if (degree >= n) + degree = n - 1; + out_degrees->push_back(std::make_pair(i, degree)); + degrees_left += degree; + } + + next(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + undirected_plod_iterator& operator++() + { + next(); + return *this; + } + + undirected_plod_iterator operator++(int) + { + undirected_plod_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const undirected_plod_iterator& other) const + { + return degrees_left == other.degrees_left; + } + + bool operator!=(const undirected_plod_iterator& other) const + { + return !(*this == other); + } + +private: + void next() + { + std::size_t source, target; + while (true) + { + /* We may get to the point where we can't actually find any + new edges, so we just add some random edge and set the + degrees left = 0 to signal termination. */ + if (out_degrees->size() < 2) + { + uniform_int< std::size_t > x(0, n - 1); + current.first = x(*gen); + do + { + current.second = x(*gen); + } while (current.first == current.second && !allow_self_loops); + degrees_left = 0; + out_degrees->clear(); + return; + } + + uniform_int< std::size_t > x(0, out_degrees->size() - 1); + + // Select source vertex + source = x(*gen); + if ((*out_degrees)[source].second == 0) + { + (*out_degrees)[source] = out_degrees->back(); + out_degrees->pop_back(); + continue; + } + + // Select target vertex + target = x(*gen); + if ((*out_degrees)[target].second == 0) + { + (*out_degrees)[target] = out_degrees->back(); + out_degrees->pop_back(); + continue; + } + else if (source != target + || (allow_self_loops && (*out_degrees)[source].second > 2)) + { + break; + } + } + + // Update degree counts + --(*out_degrees)[source].second; + --degrees_left; + --(*out_degrees)[target].second; + --degrees_left; + current.first = (*out_degrees)[source].first; + current.second = (*out_degrees)[target].first; + } + + RandomGenerator* gen; + std::size_t n; + shared_ptr< out_degrees_t > out_degrees; + std::size_t degrees_left; + bool allow_self_loops; + value_type current; +}; + +template < typename RandomGenerator, typename Graph > +class plod_iterator +: public mpl::if_< + is_convertible< typename graph_traits< Graph >::directed_category, + directed_tag >, + out_directed_plod_iterator< RandomGenerator >, + undirected_plod_iterator< RandomGenerator > >::type +{ + typedef typename mpl::if_< + is_convertible< typename graph_traits< Graph >::directed_category, + directed_tag >, + out_directed_plod_iterator< RandomGenerator >, + undirected_plod_iterator< RandomGenerator > >::type inherited; + +public: + plod_iterator() : inherited() {} + + plod_iterator(RandomGenerator& gen, std::size_t n, double alpha, + double beta, bool allow_self_loops = false) + : inherited(gen, n, alpha, beta, allow_self_loops) + { + } +}; + +} // end namespace boost + +#endif // BOOST_GRAPH_PLOD_GENERATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/point_traits.hpp b/contrib/restricted/boost/graph/include/boost/graph/point_traits.hpp new file mode 100644 index 0000000000..c81b9ed6f5 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/point_traits.hpp @@ -0,0 +1,31 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_POINT_TRAITS_HPP +#define BOOST_GRAPH_POINT_TRAITS_HPP + +#include <cstddef> + +namespace boost +{ +namespace graph +{ + + template < typename Point > struct point_traits + { + // The type of each component of the point + typedef typename Point::component_type component_type; + + // The number of dimensions in the point + static std::size_t dimensions(const Point& point); + }; + +} +} // end namespace boost::graph + +#endif // BOOST_GRAPH_POINT_TRAITS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/prim_minimum_spanning_tree.hpp b/contrib/restricted/boost/graph/include/boost/graph/prim_minimum_spanning_tree.hpp new file mode 100644 index 0000000000..1f26f2ef54 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/prim_minimum_spanning_tree.hpp @@ -0,0 +1,84 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_MST_PRIM_HPP +#define BOOST_GRAPH_MST_PRIM_HPP + +#include <functional> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/dijkstra_shortest_paths.hpp> + +namespace boost +{ + +namespace detail +{ + // this should be somewhere else in boost... + template < class U, class V > struct _project2nd + { + V operator()(U, V v) const { return v; } + }; +} + +namespace detail +{ + + // This is Prim's algorithm to calculate the Minimum Spanning Tree + // for an undirected graph with weighted edges. + + template < class Graph, class P, class T, class R, class Weight > + inline void prim_mst_impl(const Graph& G, + typename graph_traits< Graph >::vertex_descriptor s, + const bgl_named_params< P, T, R >& params, Weight) + { + typedef typename property_traits< Weight >::value_type W; + std::less< W > compare; + detail::_project2nd< W, W > combine; + dijkstra_shortest_paths( + G, s, params.distance_compare(compare).distance_combine(combine)); + } +} // namespace detail + +template < class VertexListGraph, class DijkstraVisitor, class PredecessorMap, + class DistanceMap, class WeightMap, class IndexMap > +inline void prim_minimum_spanning_tree(const VertexListGraph& g, + typename graph_traits< VertexListGraph >::vertex_descriptor s, + PredecessorMap predecessor, DistanceMap distance, WeightMap weight, + IndexMap index_map, DijkstraVisitor vis) +{ + typedef typename property_traits< WeightMap >::value_type W; + std::less< W > compare; + detail::_project2nd< W, W > combine; + dijkstra_shortest_paths(g, s, predecessor, distance, weight, index_map, + compare, combine, (std::numeric_limits< W >::max)(), 0, vis); +} + +template < class VertexListGraph, class PredecessorMap, class P, class T, + class R > +inline void prim_minimum_spanning_tree(const VertexListGraph& g, + PredecessorMap p_map, const bgl_named_params< P, T, R >& params) +{ + detail::prim_mst_impl(g, + choose_param(get_param(params, root_vertex_t()), *vertices(g).first), + params.predecessor_map(p_map), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight)); +} + +template < class VertexListGraph, class PredecessorMap > +inline void prim_minimum_spanning_tree( + const VertexListGraph& g, PredecessorMap p_map) +{ + detail::prim_mst_impl(g, *vertices(g).first, + predecessor_map(p_map).weight_map(get(edge_weight, g)), + get(edge_weight, g)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_MST_PRIM_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/profile.hpp b/contrib/restricted/boost/graph/include/boost/graph/profile.hpp new file mode 100644 index 0000000000..c06200cb71 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/profile.hpp @@ -0,0 +1,44 @@ +// +//======================================================================= +// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) +// ETH Zurich, Center of Structure Technologies +// (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_GRAPH_PROFILE_HPP +#define BOOST_GRAPH_PROFILE_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/detail/numeric_traits.hpp> +#include <boost/graph/bandwidth.hpp> + +namespace boost +{ + +template < typename Graph, typename VertexIndexMap > +typename graph_traits< Graph >::vertices_size_type profile( + const Graph& g, VertexIndexMap index) +{ + typename graph_traits< Graph >::vertices_size_type b = 0; + typename graph_traits< Graph >::vertex_iterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + b += ith_bandwidth(*i, g, index) + 1; + } + + return b; +} + +template < typename Graph > +typename graph_traits< Graph >::vertices_size_type profile(const Graph& g) +{ + return profile(g, get(vertex_index, g)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_PROFILE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/property_iter_range.hpp b/contrib/restricted/boost/graph/include/boost/graph/property_iter_range.hpp new file mode 100644 index 0000000000..aa8780b37d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/property_iter_range.hpp @@ -0,0 +1,120 @@ + +// (C) Copyright Francois Faure, iMAGIS-GRAVIR / UJF, 2001. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +// +// Revision History: +// 03 May 2001 Jeremy Siek +// Generalized the property map iterator and moved that +// part to boost/property_map.hpp. Also modified to +// differentiate between const/mutable graphs and +// added a workaround to avoid partial specialization. + +// 02 May 2001 Francois Faure +// Initial version. + +#ifndef BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP +#define BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP + +#include <boost/property_map/property_map_iterator.hpp> +#include <boost/graph/properties.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/same_traits.hpp> + +namespace boost +{ + +//====================================================================== +// graph property iterator range + +template < class Graph, class PropertyTag > class graph_property_iter_range +{ + typedef typename property_map< Graph, PropertyTag >::type map_type; + typedef + typename property_map< Graph, PropertyTag >::const_type const_map_type; + typedef typename property_kind< PropertyTag >::type Kind; + typedef typename mpl::if_c< is_same< Kind, vertex_property_tag >::value, + typename graph_traits< Graph >::vertex_iterator, + typename graph_traits< Graph >::edge_iterator >::type iter; + +public: + typedef typename property_map_iterator_generator< map_type, iter >::type + iterator; + typedef + typename property_map_iterator_generator< const_map_type, iter >::type + const_iterator; + typedef std::pair< iterator, iterator > type; + typedef std::pair< const_iterator, const_iterator > const_type; +}; + +namespace detail +{ + + template < class Graph, class Tag > + typename graph_property_iter_range< Graph, Tag >::type + get_property_iter_range_kind( + Graph& graph, const Tag& tag, const vertex_property_tag&) + { + typedef typename graph_property_iter_range< Graph, Tag >::iterator iter; + return std::make_pair(iter(vertices(graph).first, get(tag, graph)), + iter(vertices(graph).second, get(tag, graph))); + } + + template < class Graph, class Tag > + typename graph_property_iter_range< Graph, Tag >::const_type + get_property_iter_range_kind( + const Graph& graph, const Tag& tag, const vertex_property_tag&) + { + typedef typename graph_property_iter_range< Graph, Tag >::const_iterator + iter; + return std::make_pair(iter(vertices(graph).first, get(tag, graph)), + iter(vertices(graph).second, get(tag, graph))); + } + + template < class Graph, class Tag > + typename graph_property_iter_range< Graph, Tag >::type + get_property_iter_range_kind( + Graph& graph, const Tag& tag, const edge_property_tag&) + { + typedef typename graph_property_iter_range< Graph, Tag >::iterator iter; + return std::make_pair(iter(edges(graph).first, get(tag, graph)), + iter(edges(graph).second, get(tag, graph))); + } + + template < class Graph, class Tag > + typename graph_property_iter_range< Graph, Tag >::const_type + get_property_iter_range_kind( + const Graph& graph, const Tag& tag, const edge_property_tag&) + { + typedef typename graph_property_iter_range< Graph, Tag >::const_iterator + iter; + return std::make_pair(iter(edges(graph).first, get(tag, graph)), + iter(edges(graph).second, get(tag, graph))); + } + +} // namespace detail + +//====================================================================== +// get an iterator range of properties + +template < class Graph, class Tag > +typename graph_property_iter_range< Graph, Tag >::type get_property_iter_range( + Graph& graph, const Tag& tag) +{ + typedef typename property_kind< Tag >::type Kind; + return detail::get_property_iter_range_kind(graph, tag, Kind()); +} + +template < class Graph, class Tag > +typename graph_property_iter_range< Graph, Tag >::const_type +get_property_iter_range(const Graph& graph, const Tag& tag) +{ + typedef typename property_kind< Tag >::type Kind; + return detail::get_property_iter_range_kind(graph, tag, Kind()); +} + +} // namespace boost + +#endif // BOOST_GRAPH_PROPERTY_ITER_RANGE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/property_maps/container_property_map.hpp b/contrib/restricted/boost/graph/include/boost/graph/property_maps/container_property_map.hpp new file mode 100644 index 0000000000..6a565c2e9d --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/property_maps/container_property_map.hpp @@ -0,0 +1,70 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_CONTAINER_PROPERTY_MAP_HPP +#define BOOST_GRAPH_CONTAINER_PROPERTY_MAP_HPP + +#include <boost/graph/detail/index.hpp> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ +// This is an adapter built over the iterator property map with +// more useful uniform construction semantics. Specifically, this +// requires the container rather than the iterator and the graph +// rather than the optional index map. +template < typename Graph, typename Key, typename Container > +struct container_property_map +: public boost::put_get_helper< + typename iterator_property_map< typename Container::iterator, + typename property_map< Graph, + typename detail::choose_indexer< Graph, + Key >::index_type >::type >::reference, + container_property_map< Graph, Key, Container > > +{ + typedef typename detail::choose_indexer< Graph, Key >::indexer_type + indexer_type; + typedef typename indexer_type::index_type index_type; + typedef iterator_property_map< typename Container::iterator, + typename property_map< Graph, index_type >::type > + map_type; + typedef typename map_type::key_type key_type; + typedef typename map_type::value_type value_type; + typedef typename map_type::reference reference; + typedef typename map_type::category category; + + // The default constructor will *probably* crash if its actually + // used for referencing vertices since the underlying iterator + // map points past the end of an unknown container. + inline container_property_map() : m_map() {} + + // This is the preferred constructor. It is invoked over the container + // and the graph explicitly. This requires that the underlying iterator + // map use the indices of the vertices in g rather than the default + // identity map. + // + // Note the const-cast this ensures the reference type of the + // vertex index map is non-const, which happens to be an + // artifact of passing const graph references. + inline container_property_map(Container& c, const Graph& g) + : m_map(c.begin(), indexer_type::index_map(const_cast< Graph& >(g))) + { + } + + // Typical copy constructor. + inline container_property_map(const container_property_map& x) + : m_map(x.m_map) + { + } + + // The [] operator delegates to the underlying map/ + inline reference operator[](const key_type& k) const { return m_map[k]; } + + map_type m_map; +}; +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/property_maps/matrix_property_map.hpp b/contrib/restricted/boost/graph/include/boost/graph/property_maps/matrix_property_map.hpp new file mode 100644 index 0000000000..f33f137464 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/property_maps/matrix_property_map.hpp @@ -0,0 +1,68 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_MATRIX_PROPERTY_MAP_HPP +#define BOOST_GRAPH_MATRIX_PROPERTY_MAP_HPP + +#include <boost/graph/property_maps/container_property_map.hpp> + +namespace boost +{ +// This property map is built specifically for property maps over +// matrices. Like the basic property map over a container, this builds +// the property abstraction over a matrix (usually a vector of vectors) +// and returns property maps over the nested containers. +template < typename Graph, typename Key, typename Matrix > +struct matrix_property_map +: boost::put_get_helper< + container_property_map< Graph, Key, typename Matrix::value_type >, + matrix_property_map< Graph, Key, Matrix > > +{ + // abstract the indexing keys + typedef typename detail::choose_indexer< Graph, Key >::indexer_type + indexer_type; + + // aliases for the nested container and its corresponding map + typedef typename Matrix::value_type container_type; + typedef container_property_map< Graph, Key, container_type > map_type; + + typedef Key key_type; + + // This property map doesn't really provide access to nested containers, + // but returns property maps over them. Since property maps are all + // copy-constructible (or should be anyways), we never return references. + // As such, this property is only readable, but not writable. Curiously, + // the inner property map is actually an lvalue pmap. + typedef map_type value_type; + typedef map_type reference; + typedef readable_property_map_tag category; + + matrix_property_map() : m_matrix(0), m_graph(0) {} + + matrix_property_map(Matrix& m, const Graph& g) + : m_matrix(&m), m_graph(const_cast< Graph* >(&g)) + { + } + + matrix_property_map(const matrix_property_map& x) + : m_matrix(x.m_matrix), m_graph(x.m_graph) + { + } + + inline reference operator[](key_type k) const + { + typedef typename indexer_type::value_type Index; + Index x = indexer_type::index(k, *m_graph); + return map_type((*m_matrix)[x], *m_graph); + } + +private: + mutable Matrix* m_matrix; + mutable Graph* m_graph; +}; +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/push_relabel_max_flow.hpp b/contrib/restricted/boost/graph/include/boost/graph/push_relabel_max_flow.hpp new file mode 100644 index 0000000000..a243f56487 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/push_relabel_max_flow.hpp @@ -0,0 +1,860 @@ +//======================================================================= +// Copyright 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +#ifndef BOOST_PUSH_RELABEL_MAX_FLOW_HPP +#define BOOST_PUSH_RELABEL_MAX_FLOW_HPP + +#include <boost/config.hpp> +#include <boost/assert.hpp> +#include <vector> +#include <list> +#include <iosfwd> +#include <algorithm> // for std::min and std::max + +#include <boost/pending/queue.hpp> +#include <boost/limits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/named_function_params.hpp> + +namespace boost +{ + +namespace detail +{ + + // This implementation is based on Goldberg's + // "On Implementing Push-Relabel Method for the Maximum Flow Problem" + // by B.V. Cherkassky and A.V. Goldberg, IPCO '95, pp. 157--171 + // and on the h_prf.c and hi_pr.c code written by the above authors. + + // This implements the highest-label version of the push-relabel method + // with the global relabeling and gap relabeling heuristics. + + // The terms "rank", "distance", "height" are synonyms in + // Goldberg's implementation, paper and in the CLR. A "layer" is a + // group of vertices with the same distance. The vertices in each + // layer are categorized as active or inactive. An active vertex + // has positive excess flow and its distance is less than n (it is + // not blocked). + + template < class Vertex > struct preflow_layer + { + std::list< Vertex > active_vertices; + std::list< Vertex > inactive_vertices; + }; + + template < class Graph, + class EdgeCapacityMap, // integer value type + class ResidualCapacityEdgeMap, class ReverseEdgeMap, + class VertexIndexMap, // vertex_descriptor -> integer + class FlowValue > + class push_relabel + { + public: + typedef graph_traits< Graph > Traits; + typedef typename Traits::vertex_descriptor vertex_descriptor; + typedef typename Traits::edge_descriptor edge_descriptor; + typedef typename Traits::vertex_iterator vertex_iterator; + typedef typename Traits::out_edge_iterator out_edge_iterator; + typedef typename Traits::vertices_size_type vertices_size_type; + typedef typename Traits::edges_size_type edges_size_type; + + typedef preflow_layer< vertex_descriptor > Layer; + typedef std::vector< Layer > LayerArray; + typedef typename LayerArray::iterator layer_iterator; + typedef typename LayerArray::size_type distance_size_type; + + typedef color_traits< default_color_type > ColorTraits; + + //======================================================================= + // Some helper predicates + + inline bool is_admissible(vertex_descriptor u, vertex_descriptor v) + { + return get(distance, u) == get(distance, v) + 1; + } + inline bool is_residual_edge(edge_descriptor a) + { + return 0 < get(residual_capacity, a); + } + inline bool is_saturated(edge_descriptor a) + { + return get(residual_capacity, a) == 0; + } + + //======================================================================= + // Layer List Management Functions + + typedef typename std::list< vertex_descriptor >::iterator list_iterator; + + void add_to_active_list(vertex_descriptor u, Layer& layer) + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + layer.active_vertices.push_front(u); + max_active = max BOOST_PREVENT_MACRO_SUBSTITUTION( + get(distance, u), max_active); + min_active = min BOOST_PREVENT_MACRO_SUBSTITUTION( + get(distance, u), min_active); + layer_list_ptr[u] = layer.active_vertices.begin(); + } + void remove_from_active_list(vertex_descriptor u) + { + layers[get(distance, u)].active_vertices.erase(layer_list_ptr[u]); + } + + void add_to_inactive_list(vertex_descriptor u, Layer& layer) + { + layer.inactive_vertices.push_front(u); + layer_list_ptr[u] = layer.inactive_vertices.begin(); + } + void remove_from_inactive_list(vertex_descriptor u) + { + layers[get(distance, u)].inactive_vertices.erase(layer_list_ptr[u]); + } + + //======================================================================= + // initialization + push_relabel(Graph& g_, EdgeCapacityMap cap, + ResidualCapacityEdgeMap res, ReverseEdgeMap rev, + vertex_descriptor src_, vertex_descriptor sink_, VertexIndexMap idx) + : g(g_) + , n(num_vertices(g_)) + , capacity(cap) + , src(src_) + , sink(sink_) + , index(idx) + , excess_flow_data(num_vertices(g_)) + , excess_flow(excess_flow_data.begin(), idx) + , current_data(num_vertices(g_), out_edges(*vertices(g_).first, g_)) + , current(current_data.begin(), idx) + , distance_data(num_vertices(g_)) + , distance(distance_data.begin(), idx) + , color_data(num_vertices(g_)) + , color(color_data.begin(), idx) + , reverse_edge(rev) + , residual_capacity(res) + , layers(num_vertices(g_)) + , layer_list_ptr_data( + num_vertices(g_), layers.front().inactive_vertices.end()) + , layer_list_ptr(layer_list_ptr_data.begin(), idx) + , push_count(0) + , update_count(0) + , relabel_count(0) + , gap_count(0) + , gap_node_count(0) + , work_since_last_update(0) + { + vertex_iterator u_iter, u_end; + // Don't count the reverse edges + edges_size_type m = num_edges(g) / 2; + nm = alpha() * n + m; + + // Initialize flow to zero which means initializing + // the residual capacity to equal the capacity. + out_edge_iterator ei, e_end; + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; + ++ei) + { + put(residual_capacity, *ei, get(capacity, *ei)); + } + + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + { + vertex_descriptor u = *u_iter; + put(excess_flow, u, 0); + current[u] = out_edges(u, g); + } + + bool overflow_detected = false; + FlowValue test_excess = 0; + + out_edge_iterator a_iter, a_end; + for (boost::tie(a_iter, a_end) = out_edges(src, g); a_iter != a_end; + ++a_iter) + if (target(*a_iter, g) != src) + test_excess += get(residual_capacity, *a_iter); + if (test_excess > (std::numeric_limits< FlowValue >::max)()) + overflow_detected = true; + + if (overflow_detected) + put(excess_flow, src, + (std::numeric_limits< FlowValue >::max)()); + else + { + put(excess_flow, src, 0); + for (boost::tie(a_iter, a_end) = out_edges(src, g); + a_iter != a_end; ++a_iter) + { + edge_descriptor a = *a_iter; + vertex_descriptor tgt = target(a, g); + if (tgt != src) + { + ++push_count; + FlowValue delta = get(residual_capacity, a); + put(residual_capacity, a, + get(residual_capacity, a) - delta); + edge_descriptor rev = get(reverse_edge, a); + put(residual_capacity, rev, + get(residual_capacity, rev) + delta); + put(excess_flow, tgt, get(excess_flow, tgt) + delta); + } + } + } + max_distance = num_vertices(g) - 1; + max_active = 0; + min_active = n; + + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + { + vertex_descriptor u = *u_iter; + if (u == sink) + { + put(distance, u, 0); + continue; + } + else if (u == src && !overflow_detected) + put(distance, u, n); + else + put(distance, u, 1); + + if (get(excess_flow, u) > 0) + add_to_active_list(u, layers[1]); + else if (get(distance, u) < n) + add_to_inactive_list(u, layers[1]); + } + + } // push_relabel constructor + + //======================================================================= + // This is a breadth-first search over the residual graph + // (well, actually the reverse of the residual graph). + // Would be cool to have a graph view adaptor for hiding certain + // edges, like the saturated (non-residual) edges in this case. + // Goldberg's implementation abused "distance" for the coloring. + void global_distance_update() + { + BOOST_USING_STD_MAX(); + ++update_count; + vertex_iterator u_iter, u_end; + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + { + put(color, *u_iter, ColorTraits::white()); + put(distance, *u_iter, n); + } + put(color, sink, ColorTraits::gray()); + put(distance, sink, 0); + + for (distance_size_type l = 0; l <= max_distance; ++l) + { + layers[l].active_vertices.clear(); + layers[l].inactive_vertices.clear(); + } + + max_distance = max_active = 0; + min_active = n; + + Q.push(sink); + while (!Q.empty()) + { + vertex_descriptor u = Q.top(); + Q.pop(); + distance_size_type d_v = get(distance, u) + 1; + + out_edge_iterator ai, a_end; + for (boost::tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) + { + edge_descriptor a = *ai; + vertex_descriptor v = target(a, g); + if (get(color, v) == ColorTraits::white() + && is_residual_edge(get(reverse_edge, a))) + { + put(distance, v, d_v); + put(color, v, ColorTraits::gray()); + current[v] = out_edges(v, g); + max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION( + d_v, max_distance); + + if (get(excess_flow, v) > 0) + add_to_active_list(v, layers[d_v]); + else + add_to_inactive_list(v, layers[d_v]); + + Q.push(v); + } + } + } + } // global_distance_update() + + //======================================================================= + // This function is called "push" in Goldberg's h_prf implementation, + // but it is called "discharge" in the paper and in hi_pr.c. + void discharge(vertex_descriptor u) + { + BOOST_ASSERT(get(excess_flow, u) > 0); + while (1) + { + out_edge_iterator ai, ai_end; + for (boost::tie(ai, ai_end) = current[u]; ai != ai_end; ++ai) + { + edge_descriptor a = *ai; + if (is_residual_edge(a)) + { + vertex_descriptor v = target(a, g); + if (is_admissible(u, v)) + { + ++push_count; + if (v != sink && get(excess_flow, v) == 0) + { + remove_from_inactive_list(v); + add_to_active_list(v, layers[get(distance, v)]); + } + push_flow(a); + if (get(excess_flow, u) == 0) + break; + } + } + } // for out_edges of i starting from current + + Layer& layer = layers[get(distance, u)]; + distance_size_type du = get(distance, u); + + if (ai == ai_end) + { // i must be relabeled + relabel_distance(u); + if (layer.active_vertices.empty() + && layer.inactive_vertices.empty()) + gap(du); + if (get(distance, u) == n) + break; + } + else + { // i is no longer active + current[u].first = ai; + add_to_inactive_list(u, layer); + break; + } + } // while (1) + } // discharge() + + //======================================================================= + // This corresponds to the "push" update operation of the paper, + // not the "push" function in Goldberg's h_prf.c implementation. + // The idea is to push the excess flow from from vertex u to v. + void push_flow(edge_descriptor u_v) + { + vertex_descriptor u = source(u_v, g), v = target(u_v, g); + + BOOST_USING_STD_MIN(); + FlowValue flow_delta = min BOOST_PREVENT_MACRO_SUBSTITUTION( + get(excess_flow, u), get(residual_capacity, u_v)); + + put(residual_capacity, u_v, + get(residual_capacity, u_v) - flow_delta); + edge_descriptor rev = get(reverse_edge, u_v); + put(residual_capacity, rev, + get(residual_capacity, rev) + flow_delta); + + put(excess_flow, u, get(excess_flow, u) - flow_delta); + put(excess_flow, v, get(excess_flow, v) + flow_delta); + } // push_flow() + + //======================================================================= + // The main purpose of this routine is to set distance[v] + // to the smallest value allowed by the valid labeling constraints, + // which are: + // distance[t] = 0 + // distance[u] <= distance[v] + 1 for every residual edge (u,v) + // + distance_size_type relabel_distance(vertex_descriptor u) + { + BOOST_USING_STD_MAX(); + ++relabel_count; + work_since_last_update += beta(); + + distance_size_type min_distance = num_vertices(g); + put(distance, u, min_distance); + + // Examine the residual out-edges of vertex i, choosing the + // edge whose target vertex has the minimal distance. + out_edge_iterator ai, a_end, min_edge_iter; + for (boost::tie(ai, a_end) = out_edges(u, g); ai != a_end; ++ai) + { + ++work_since_last_update; + edge_descriptor a = *ai; + vertex_descriptor v = target(a, g); + if (is_residual_edge(a) && get(distance, v) < min_distance) + { + min_distance = get(distance, v); + min_edge_iter = ai; + } + } + ++min_distance; + if (min_distance < n) + { + put(distance, u, min_distance); // this is the main action + current[u].first = min_edge_iter; + max_distance = max BOOST_PREVENT_MACRO_SUBSTITUTION( + min_distance, max_distance); + } + return min_distance; + } // relabel_distance() + + //======================================================================= + // cleanup beyond the gap + void gap(distance_size_type empty_distance) + { + ++gap_count; + + distance_size_type r; // distance of layer before the current layer + r = empty_distance - 1; + + // Set the distance for the vertices beyond the gap to "infinity". + for (layer_iterator l = layers.begin() + empty_distance + 1; + l < layers.begin() + max_distance; ++l) + { + list_iterator i; + for (i = l->inactive_vertices.begin(); + i != l->inactive_vertices.end(); ++i) + { + put(distance, *i, n); + ++gap_node_count; + } + l->inactive_vertices.clear(); + } + max_distance = r; + max_active = r; + } + + //======================================================================= + // This is the core part of the algorithm, "phase one". + FlowValue maximum_preflow() + { + work_since_last_update = 0; + + while (max_active >= min_active) + { // "main" loop + + Layer& layer = layers[max_active]; + list_iterator u_iter = layer.active_vertices.begin(); + + if (u_iter == layer.active_vertices.end()) + --max_active; + else + { + vertex_descriptor u = *u_iter; + remove_from_active_list(u); + + discharge(u); + + if (work_since_last_update * global_update_frequency() > nm) + { + global_distance_update(); + work_since_last_update = 0; + } + } + } // while (max_active >= min_active) + + return get(excess_flow, sink); + } // maximum_preflow() + + //======================================================================= + // remove excess flow, the "second phase" + // This does a DFS on the reverse flow graph of nodes with excess flow. + // If a cycle is found, cancel it. + // Return the nodes with excess flow in topological order. + // + // Unlike the prefl_to_flow() implementation, we use + // "color" instead of "distance" for the DFS labels + // "parent" instead of nl_prev for the DFS tree + // "topo_next" instead of nl_next for the topological ordering + void convert_preflow_to_flow() + { + vertex_iterator u_iter, u_end; + out_edge_iterator ai, a_end; + + vertex_descriptor r, restart, u; + + std::vector< vertex_descriptor > parent(n); + std::vector< vertex_descriptor > topo_next(n); + + vertex_descriptor tos(parent[0]), + bos(parent[0]); // bogus initialization, just to avoid warning + bool bos_null = true; + + // handle self-loops + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + for (boost::tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; + ++ai) + if (target(*ai, g) == *u_iter) + put(residual_capacity, *ai, get(capacity, *ai)); + + // initialize + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + { + u = *u_iter; + put(color, u, ColorTraits::white()); + parent[get(index, u)] = u; + current[u] = out_edges(u, g); + } + // eliminate flow cycles and topologically order the vertices + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + { + u = *u_iter; + if (get(color, u) == ColorTraits::white() + && get(excess_flow, u) > 0 && u != src && u != sink) + { + r = u; + put(color, r, ColorTraits::gray()); + while (1) + { + for (; current[u].first != current[u].second; + ++current[u].first) + { + edge_descriptor a = *current[u].first; + if (get(capacity, a) == 0 && is_residual_edge(a)) + { + vertex_descriptor v = target(a, g); + if (get(color, v) == ColorTraits::white()) + { + put(color, v, ColorTraits::gray()); + parent[get(index, v)] = u; + u = v; + break; + } + else if (get(color, v) == ColorTraits::gray()) + { + // find minimum flow on the cycle + FlowValue delta = get(residual_capacity, a); + while (1) + { + BOOST_USING_STD_MIN(); + delta = min + BOOST_PREVENT_MACRO_SUBSTITUTION( + delta, + get(residual_capacity, + *current[v].first)); + if (v == u) + break; + else + v = target(*current[v].first, g); + } + // remove delta flow units + v = u; + while (1) + { + a = *current[v].first; + put(residual_capacity, a, + get(residual_capacity, a) - delta); + edge_descriptor rev + = get(reverse_edge, a); + put(residual_capacity, rev, + get(residual_capacity, rev) + + delta); + v = target(a, g); + if (v == u) + break; + } + + // back-out of DFS to the first saturated + // edge + restart = u; + for (v = target(*current[u].first, g); + v != u; v = target(a, g)) + { + a = *current[v].first; + if (get(color, v) + == ColorTraits::white() + || is_saturated(a)) + { + put(color, + target(*current[v].first, g), + ColorTraits::white()); + if (get(color, v) + != ColorTraits::white()) + restart = v; + } + } + if (restart != u) + { + u = restart; + ++current[u].first; + break; + } + } // else if (color[v] == ColorTraits::gray()) + } // if (get(capacity, a) == 0 ... + } // for out_edges(u, g) (though "u" changes during + // loop) + + if (current[u].first == current[u].second) + { + // scan of i is complete + put(color, u, ColorTraits::black()); + if (u != src) + { + if (bos_null) + { + bos = u; + bos_null = false; + tos = u; + } + else + { + topo_next[get(index, u)] = tos; + tos = u; + } + } + if (u != r) + { + u = parent[get(index, u)]; + ++current[u].first; + } + else + break; + } + } // while (1) + } // if (color[u] == white && excess_flow[u] > 0 & ...) + } // for all vertices in g + + // return excess flows + // note that the sink is not on the stack + if (!bos_null) + { + for (u = tos; u != bos; u = topo_next[get(index, u)]) + { + boost::tie(ai, a_end) = out_edges(u, g); + while (get(excess_flow, u) > 0 && ai != a_end) + { + if (get(capacity, *ai) == 0 && is_residual_edge(*ai)) + push_flow(*ai); + ++ai; + } + } + // do the bottom + u = bos; + boost::tie(ai, a_end) = out_edges(u, g); + while (get(excess_flow, u) > 0 && ai != a_end) + { + if (get(capacity, *ai) == 0 && is_residual_edge(*ai)) + push_flow(*ai); + ++ai; + } + } + + } // convert_preflow_to_flow() + + //======================================================================= + inline bool is_flow() + { + vertex_iterator u_iter, u_end; + out_edge_iterator ai, a_end; + + // check edge flow values + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + { + for (boost::tie(ai, a_end) = out_edges(*u_iter, g); ai != a_end; + ++ai) + { + edge_descriptor a = *ai; + if (get(capacity, a) > 0) + if ((get(residual_capacity, a) + + get( + residual_capacity, get(reverse_edge, a)) + != get(capacity, a) + + get(capacity, get(reverse_edge, a))) + || (get(residual_capacity, a) < 0) + || (get(residual_capacity, get(reverse_edge, a)) + < 0)) + return false; + } + } + + // check conservation + FlowValue sum; + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + { + vertex_descriptor u = *u_iter; + if (u != src && u != sink) + { + if (get(excess_flow, u) != 0) + return false; + sum = 0; + for (boost::tie(ai, a_end) = out_edges(u, g); ai != a_end; + ++ai) + if (get(capacity, *ai) > 0) + sum -= get(capacity, *ai) + - get(residual_capacity, *ai); + else + sum += get(residual_capacity, *ai); + + if (get(excess_flow, u) != sum) + return false; + } + } + + return true; + } // is_flow() + + bool is_optimal() + { + // check if mincut is saturated... + global_distance_update(); + return get(distance, src) >= n; + } + + void print_statistics(std::ostream& os) const + { + os << "pushes: " << push_count << std::endl + << "relabels: " << relabel_count << std::endl + << "updates: " << update_count << std::endl + << "gaps: " << gap_count << std::endl + << "gap nodes: " << gap_node_count << std::endl + << std::endl; + } + + void print_flow_values(std::ostream& os) const + { + os << "flow values" << std::endl; + vertex_iterator u_iter, u_end; + out_edge_iterator ei, e_end; + for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; + ++u_iter) + for (boost::tie(ei, e_end) = out_edges(*u_iter, g); ei != e_end; + ++ei) + if (get(capacity, *ei) > 0) + os << *u_iter << " " << target(*ei, g) << " " + << (get(capacity, *ei) - get(residual_capacity, *ei)) + << std::endl; + os << std::endl; + } + + //======================================================================= + + Graph& g; + vertices_size_type n; + vertices_size_type nm; + EdgeCapacityMap capacity; + vertex_descriptor src; + vertex_descriptor sink; + VertexIndexMap index; + + // will need to use random_access_property_map with these + std::vector< FlowValue > excess_flow_data; + iterator_property_map< typename std::vector< FlowValue >::iterator, + VertexIndexMap > + excess_flow; + std::vector< std::pair< out_edge_iterator, out_edge_iterator > > + current_data; + iterator_property_map< + typename std::vector< + std::pair< out_edge_iterator, out_edge_iterator > >::iterator, + VertexIndexMap > + current; + std::vector< distance_size_type > distance_data; + iterator_property_map< + typename std::vector< distance_size_type >::iterator, + VertexIndexMap > + distance; + std::vector< default_color_type > color_data; + iterator_property_map< std::vector< default_color_type >::iterator, + VertexIndexMap > + color; + + // Edge Property Maps that must be interior to the graph + ReverseEdgeMap reverse_edge; + ResidualCapacityEdgeMap residual_capacity; + + LayerArray layers; + std::vector< list_iterator > layer_list_ptr_data; + iterator_property_map< typename std::vector< list_iterator >::iterator, + VertexIndexMap > + layer_list_ptr; + distance_size_type max_distance; // maximal distance + distance_size_type max_active; // maximal distance with active node + distance_size_type min_active; // minimal distance with active node + boost::queue< vertex_descriptor > Q; + + // Statistics counters + long push_count; + long update_count; + long relabel_count; + long gap_count; + long gap_node_count; + + inline double global_update_frequency() { return 0.5; } + inline vertices_size_type alpha() { return 6; } + inline long beta() { return 12; } + + long work_since_last_update; + }; + +} // namespace detail + +template < class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap, + class ReverseEdgeMap, class VertexIndexMap > +typename property_traits< CapacityEdgeMap >::value_type push_relabel_max_flow( + Graph& g, typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, CapacityEdgeMap cap, + ResidualCapacityEdgeMap res, ReverseEdgeMap rev, VertexIndexMap index_map) +{ + typedef typename property_traits< CapacityEdgeMap >::value_type FlowValue; + + detail::push_relabel< Graph, CapacityEdgeMap, ResidualCapacityEdgeMap, + ReverseEdgeMap, VertexIndexMap, FlowValue > + algo(g, cap, res, rev, src, sink, index_map); + + FlowValue flow = algo.maximum_preflow(); + + algo.convert_preflow_to_flow(); + + BOOST_ASSERT(algo.is_flow()); + BOOST_ASSERT(algo.is_optimal()); + + return flow; +} // push_relabel_max_flow() + +template < class Graph, class P, class T, class R > +typename detail::edge_capacity_value< Graph, P, T, R >::type +push_relabel_max_flow(Graph& g, + typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, + const bgl_named_params< P, T, R >& params) +{ + return push_relabel_max_flow(g, src, sink, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), g, + edge_residual_capacity), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index)); +} + +template < class Graph > +typename property_traits< + typename property_map< Graph, edge_capacity_t >::const_type >::value_type +push_relabel_max_flow(Graph& g, + typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink) +{ + bgl_named_params< int, buffer_param_t > params(0); // bogus empty param + return push_relabel_max_flow(g, src, sink, params); +} + +} // namespace boost + +#endif // BOOST_PUSH_RELABEL_MAX_FLOW_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/r_c_shortest_paths.hpp b/contrib/restricted/boost/graph/include/boost/graph/r_c_shortest_paths.hpp new file mode 100644 index 0000000000..12edb43dcf --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/r_c_shortest_paths.hpp @@ -0,0 +1,727 @@ +// r_c_shortest_paths.hpp header file + +// Copyright Michael Drexl 2005, 2006. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP +#define BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP + +#include <map> +#include <queue> +#include <vector> +#include <list> + +#include <boost/make_shared.hpp> +#include <boost/enable_shared_from_this.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +// r_c_shortest_paths_label struct +template < class Graph, class Resource_Container > +struct r_c_shortest_paths_label +: public boost::enable_shared_from_this< + r_c_shortest_paths_label< Graph, Resource_Container > > +{ + r_c_shortest_paths_label(const unsigned long n, + const Resource_Container& rc = Resource_Container(), + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > > + pl + = boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >(), + const typename graph_traits< Graph >::edge_descriptor& ed + = graph_traits< Graph >::edge_descriptor(), + const typename graph_traits< Graph >::vertex_descriptor& vd + = graph_traits< Graph >::vertex_descriptor()) + : num(n) + , cumulated_resource_consumption(rc) + , p_pred_label(pl) + , pred_edge(ed) + , resident_vertex(vd) + , b_is_dominated(false) + , b_is_processed(false) + { + } + + r_c_shortest_paths_label& operator=(const r_c_shortest_paths_label& other) + { + if (this == &other) + return *this; + this->~r_c_shortest_paths_label(); + new (this) r_c_shortest_paths_label(other); + return *this; + } + const unsigned long num; + Resource_Container cumulated_resource_consumption; + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > > + p_pred_label; + const typename graph_traits< Graph >::edge_descriptor pred_edge; + const typename graph_traits< Graph >::vertex_descriptor resident_vertex; + bool b_is_dominated; + bool b_is_processed; +}; // r_c_shortest_paths_label + +template < class Graph, class Resource_Container > +inline bool operator==( + const r_c_shortest_paths_label< Graph, Resource_Container >& l1, + const r_c_shortest_paths_label< Graph, Resource_Container >& l2) +{ + return l1.cumulated_resource_consumption + == l2.cumulated_resource_consumption; +} + +template < class Graph, class Resource_Container > +inline bool operator!=( + const r_c_shortest_paths_label< Graph, Resource_Container >& l1, + const r_c_shortest_paths_label< Graph, Resource_Container >& l2) +{ + return !(l1 == l2); +} + +template < class Graph, class Resource_Container > +inline bool operator<( + const r_c_shortest_paths_label< Graph, Resource_Container >& l1, + const r_c_shortest_paths_label< Graph, Resource_Container >& l2) +{ + return l1.cumulated_resource_consumption + < l2.cumulated_resource_consumption; +} + +template < class Graph, class Resource_Container > +inline bool operator>( + const r_c_shortest_paths_label< Graph, Resource_Container >& l1, + const r_c_shortest_paths_label< Graph, Resource_Container >& l2) +{ + return l2.cumulated_resource_consumption + < l1.cumulated_resource_consumption; +} + +template < class Graph, class Resource_Container > +inline bool operator<=( + const r_c_shortest_paths_label< Graph, Resource_Container >& l1, + const r_c_shortest_paths_label< Graph, Resource_Container >& l2) +{ + return l1 < l2 || l1 == l2; +} + +template < class Graph, class Resource_Container > +inline bool operator>=( + const r_c_shortest_paths_label< Graph, Resource_Container >& l1, + const r_c_shortest_paths_label< Graph, Resource_Container >& l2) +{ + return l2 < l1 || l1 == l2; +} + +template < typename Graph, typename Resource_Container > +inline bool operator<( + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& t, + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& u) +{ + return *t < *u; +} + +template < typename Graph, typename Resource_Container > +inline bool operator<=( + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& t, + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& u) +{ + return *t <= *u; +} + +template < typename Graph, typename Resource_Container > +inline bool operator>( + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& t, + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& u) +{ + return *t > *u; +} + +template < typename Graph, typename Resource_Container > +inline bool operator>=( + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& t, + const boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >& u) +{ + return *t >= *u; +} + +namespace detail +{ + + // r_c_shortest_paths_dispatch function (body/implementation) + template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function, class Label_Allocator, class Visitor > + void r_c_shortest_paths_dispatch(const Graph& g, + const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& /*edge_index_map*/, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + // each inner vector corresponds to a pareto-optimal path + std::vector< + std::vector< typename graph_traits< Graph >::edge_descriptor > >& + pareto_optimal_solutions, + std::vector< Resource_Container >& pareto_optimal_resource_containers, + bool b_all_pareto_optimal_solutions, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, Resource_Extension_Function& ref, + Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator /*la*/, Visitor vis) + { + pareto_optimal_resource_containers.clear(); + pareto_optimal_solutions.clear(); + + size_t i_label_num = 0; +#if defined(BOOST_NO_CXX11_ALLOCATOR) + typedef typename Label_Allocator::template rebind< + r_c_shortest_paths_label< Graph, Resource_Container > >::other + LAlloc; +#else + typedef typename std::allocator_traits< Label_Allocator >:: + template rebind_alloc< + r_c_shortest_paths_label< Graph, Resource_Container > > + LAlloc; + typedef std::allocator_traits< LAlloc > LTraits; +#endif + LAlloc l_alloc; + typedef boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > > + Splabel; + std::priority_queue< Splabel, std::vector< Splabel >, + std::greater< Splabel > > + unprocessed_labels; + + bool b_feasible = true; + Splabel splabel_first_label = boost::allocate_shared< + r_c_shortest_paths_label< Graph, Resource_Container > >(l_alloc, + i_label_num++, rc, + boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > >(), + typename graph_traits< Graph >::edge_descriptor(), s); + + unprocessed_labels.push(splabel_first_label); + std::vector< std::list< Splabel > > vec_vertex_labels_data( + num_vertices(g)); + iterator_property_map< + typename std::vector< std::list< Splabel > >::iterator, + VertexIndexMap > + vec_vertex_labels(vec_vertex_labels_data.begin(), vertex_index_map); + vec_vertex_labels[s].push_back(splabel_first_label); + typedef std::vector< typename std::list< Splabel >::iterator > + vec_last_valid_positions_for_dominance_data_type; + vec_last_valid_positions_for_dominance_data_type + vec_last_valid_positions_for_dominance_data(num_vertices(g)); + iterator_property_map< + typename vec_last_valid_positions_for_dominance_data_type::iterator, + VertexIndexMap > + vec_last_valid_positions_for_dominance( + vec_last_valid_positions_for_dominance_data.begin(), + vertex_index_map); + BGL_FORALL_VERTICES_T(v, g, Graph) + { + put(vec_last_valid_positions_for_dominance, v, + vec_vertex_labels[v].begin()); + } + std::vector< size_t > vec_last_valid_index_for_dominance_data( + num_vertices(g), 0); + iterator_property_map< std::vector< size_t >::iterator, VertexIndexMap > + vec_last_valid_index_for_dominance( + vec_last_valid_index_for_dominance_data.begin(), + vertex_index_map); + std::vector< bool > b_vec_vertex_already_checked_for_dominance_data( + num_vertices(g), false); + iterator_property_map< std::vector< bool >::iterator, VertexIndexMap > + b_vec_vertex_already_checked_for_dominance( + b_vec_vertex_already_checked_for_dominance_data.begin(), + vertex_index_map); + + while (!unprocessed_labels.empty() + && vis.on_enter_loop(unprocessed_labels, g)) + { + Splabel cur_label = unprocessed_labels.top(); + unprocessed_labels.pop(); + vis.on_label_popped(*cur_label, g); + // an Splabel object in unprocessed_labels and the respective + // Splabel object in the respective list<Splabel> of + // vec_vertex_labels share their embedded r_c_shortest_paths_label + // object to avoid memory leaks, dominated r_c_shortest_paths_label + // objects are marked and deleted when popped from + // unprocessed_labels, as they can no longer be deleted at the end + // of the function; only the Splabel object in unprocessed_labels + // still references the r_c_shortest_paths_label object this is also + // for efficiency, because the else branch is executed only if there + // is a chance that extending the label leads to new undominated + // labels, which in turn is possible only if the label to be + // extended is undominated + if (!cur_label->b_is_dominated) + { + typename boost::graph_traits< Graph >::vertex_descriptor + i_cur_resident_vertex + = cur_label->resident_vertex; + std::list< Splabel >& list_labels_cur_vertex + = get(vec_vertex_labels, i_cur_resident_vertex); + if (list_labels_cur_vertex.size() >= 2 + && vec_last_valid_index_for_dominance[i_cur_resident_vertex] + < list_labels_cur_vertex.size()) + { + typename std::list< Splabel >::iterator outer_iter + = list_labels_cur_vertex.begin(); + bool b_outer_iter_at_or_beyond_last_valid_pos_for_dominance + = false; + while (outer_iter != list_labels_cur_vertex.end()) + { + Splabel cur_outer_splabel = *outer_iter; + typename std::list< Splabel >::iterator inner_iter + = outer_iter; + if (!b_outer_iter_at_or_beyond_last_valid_pos_for_dominance + && outer_iter + == get(vec_last_valid_positions_for_dominance, + i_cur_resident_vertex)) + b_outer_iter_at_or_beyond_last_valid_pos_for_dominance + = true; + if (!get(b_vec_vertex_already_checked_for_dominance, + i_cur_resident_vertex) + || b_outer_iter_at_or_beyond_last_valid_pos_for_dominance) + { + ++inner_iter; + } + else + { + inner_iter + = get(vec_last_valid_positions_for_dominance, + i_cur_resident_vertex); + ++inner_iter; + } + bool b_outer_iter_erased = false; + while (inner_iter != list_labels_cur_vertex.end()) + { + Splabel cur_inner_splabel = *inner_iter; + if (dominance(cur_outer_splabel + ->cumulated_resource_consumption, + cur_inner_splabel + ->cumulated_resource_consumption)) + { + typename std::list< Splabel >::iterator buf + = inner_iter; + ++inner_iter; + list_labels_cur_vertex.erase(buf); + if (cur_inner_splabel->b_is_processed) + { + cur_inner_splabel.reset(); + } + else + cur_inner_splabel->b_is_dominated = true; + continue; + } + else + ++inner_iter; + if (dominance(cur_inner_splabel + ->cumulated_resource_consumption, + cur_outer_splabel + ->cumulated_resource_consumption)) + { + typename std::list< Splabel >::iterator buf + = outer_iter; + ++outer_iter; + list_labels_cur_vertex.erase(buf); + b_outer_iter_erased = true; + if (cur_outer_splabel->b_is_processed) + { + cur_outer_splabel.reset(); + } + else + cur_outer_splabel->b_is_dominated = true; + break; + } + } + if (!b_outer_iter_erased) + ++outer_iter; + } + if (list_labels_cur_vertex.size() > 1) + put(vec_last_valid_positions_for_dominance, + i_cur_resident_vertex, + (--(list_labels_cur_vertex.end()))); + else + put(vec_last_valid_positions_for_dominance, + i_cur_resident_vertex, + list_labels_cur_vertex.begin()); + put(b_vec_vertex_already_checked_for_dominance, + i_cur_resident_vertex, true); + put(vec_last_valid_index_for_dominance, + i_cur_resident_vertex, + list_labels_cur_vertex.size() - 1); + } + } + if (!b_all_pareto_optimal_solutions + && cur_label->resident_vertex == t) + { + // the devil don't sleep + if (cur_label->b_is_dominated) + { + cur_label.reset(); + } + while (unprocessed_labels.size()) + { + Splabel l = unprocessed_labels.top(); + unprocessed_labels.pop(); + // delete only dominated labels, because nondominated labels + // are deleted at the end of the function + if (l->b_is_dominated) + { + l.reset(); + } + } + break; + } + if (!cur_label->b_is_dominated) + { + cur_label->b_is_processed = true; + vis.on_label_not_dominated(*cur_label, g); + typename graph_traits< Graph >::vertex_descriptor cur_vertex + = cur_label->resident_vertex; + typename graph_traits< Graph >::out_edge_iterator oei, oei_end; + for (boost::tie(oei, oei_end) = out_edges(cur_vertex, g); + oei != oei_end; ++oei) + { + b_feasible = true; + Splabel new_label = boost::allocate_shared< + r_c_shortest_paths_label< Graph, Resource_Container > >( + l_alloc, i_label_num++, + cur_label->cumulated_resource_consumption, cur_label, + *oei, target(*oei, g)); + b_feasible = ref(g, + new_label->cumulated_resource_consumption, + new_label->p_pred_label->cumulated_resource_consumption, + new_label->pred_edge); + + if (!b_feasible) + { + vis.on_label_not_feasible(*new_label, g); + new_label.reset(); + } + else + { + vis.on_label_feasible(*new_label, g); + vec_vertex_labels[new_label->resident_vertex].push_back( + new_label); + unprocessed_labels.push(new_label); + } + } + } + else + { + vis.on_label_dominated(*cur_label, g); + cur_label.reset(); + } + } + std::list< Splabel > dsplabels = get(vec_vertex_labels, t); + if(!b_all_pareto_optimal_solutions) + { + dsplabels.sort(); + } + typename std::list< Splabel >::const_iterator csi = dsplabels.begin(); + typename std::list< Splabel >::const_iterator csi_end = dsplabels.end(); + // if d could be reached from o + if (!dsplabels.empty()) + { + for (; csi != csi_end; ++csi) + { + std::vector< typename graph_traits< Graph >::edge_descriptor > + cur_pareto_optimal_path; + boost::shared_ptr< + r_c_shortest_paths_label< Graph, Resource_Container > > + p_cur_label = *csi; + pareto_optimal_resource_containers.push_back( + p_cur_label->cumulated_resource_consumption); + while (p_cur_label->num != 0) + { + cur_pareto_optimal_path.push_back(p_cur_label->pred_edge); + p_cur_label = p_cur_label->p_pred_label; + + // assertion b_is_valid beyond this point is not correct if + // the domination function requires resource levels to be + // strictly greater than existing values + // + // Example + // Customers + // id min_arrival max_departure + // 2 0 974 + // 3 0 972 + // 4 0 964 + // 5 678 801 + // + // Path A: 2-3-4-5 (times: 0-16-49-84-678) + // Path B: 3-2-4-5 (times: 0-18-51-62-678) + // The partial path 3-2-4 dominates the other partial path + // 2-3-4, though the path 3-2-4-5 does not strictly dominate + // the path 2-3-4-5 + } + pareto_optimal_solutions.push_back(cur_pareto_optimal_path); + if (!b_all_pareto_optimal_solutions) + break; + } + } + + BGL_FORALL_VERTICES_T(i, g, Graph) + { + std::list< Splabel >& list_labels_cur_vertex = vec_vertex_labels[i]; + typename std::list< Splabel >::iterator si + = list_labels_cur_vertex.begin(); + const typename std::list< Splabel >::iterator si_end + = list_labels_cur_vertex.end(); + for (; si != si_end; ++si) + { + (*si).reset(); + } + } + } // r_c_shortest_paths_dispatch + +} // detail + +// default_r_c_shortest_paths_visitor struct +struct default_r_c_shortest_paths_visitor +{ + template < class Label, class Graph > + void on_label_popped(const Label&, const Graph&) + { + } + template < class Label, class Graph > + void on_label_feasible(const Label&, const Graph&) + { + } + template < class Label, class Graph > + void on_label_not_feasible(const Label&, const Graph&) + { + } + template < class Label, class Graph > + void on_label_dominated(const Label&, const Graph&) + { + } + template < class Label, class Graph > + void on_label_not_dominated(const Label&, const Graph&) + { + } + template < class Queue, class Graph > + bool on_enter_loop(const Queue& queue, const Graph& graph) + { + return true; + } +}; // default_r_c_shortest_paths_visitor + +// default_r_c_shortest_paths_allocator +typedef std::allocator< int > default_r_c_shortest_paths_allocator; +// default_r_c_shortest_paths_allocator + +// r_c_shortest_paths functions (handle/interface) +// first overload: +// - return all pareto-optimal solutions +// - specify Label_Allocator and Visitor arguments +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function, class Label_Allocator, class Visitor > +void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + // each inner vector corresponds to a pareto-optimal path + std::vector< + std::vector< typename graph_traits< Graph >::edge_descriptor > >& + pareto_optimal_solutions, + std::vector< Resource_Container >& pareto_optimal_resource_containers, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator la, Visitor vis) +{ + r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + pareto_optimal_solutions, pareto_optimal_resource_containers, true, rc, + ref, dominance, la, vis); +} + +// second overload: +// - return only one pareto-optimal solution +// - specify Label_Allocator and Visitor arguments +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function, class Label_Allocator, class Visitor > +void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + std::vector< typename graph_traits< Graph >::edge_descriptor >& + pareto_optimal_solution, + Resource_Container& pareto_optimal_resource_container, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance, + // to specify the memory management strategy for the labels + Label_Allocator la, Visitor vis) +{ + // each inner vector corresponds to a pareto-optimal path + std::vector< + std::vector< typename graph_traits< Graph >::edge_descriptor > > + pareto_optimal_solutions; + std::vector< Resource_Container > pareto_optimal_resource_containers; + r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + pareto_optimal_solutions, pareto_optimal_resource_containers, false, rc, + ref, dominance, la, vis); + if (!pareto_optimal_solutions.empty()) + { + pareto_optimal_solution = pareto_optimal_solutions[0]; + pareto_optimal_resource_container + = pareto_optimal_resource_containers[0]; + } +} + +// third overload: +// - return all pareto-optimal solutions +// - use default Label_Allocator and Visitor +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function > +void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + // each inner vector corresponds to a pareto-optimal path + std::vector< + std::vector< typename graph_traits< Graph >::edge_descriptor > >& + pareto_optimal_solutions, + std::vector< Resource_Container >& pareto_optimal_resource_containers, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance) +{ + r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + pareto_optimal_solutions, pareto_optimal_resource_containers, true, rc, + ref, dominance, default_r_c_shortest_paths_allocator(), + default_r_c_shortest_paths_visitor()); +} + +// fourth overload: +// - return only one pareto-optimal solution +// - use default Label_Allocator and Visitor +template < class Graph, class VertexIndexMap, class EdgeIndexMap, + class Resource_Container, class Resource_Extension_Function, + class Dominance_Function > +void r_c_shortest_paths(const Graph& g, const VertexIndexMap& vertex_index_map, + const EdgeIndexMap& edge_index_map, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + std::vector< typename graph_traits< Graph >::edge_descriptor >& + pareto_optimal_solution, + Resource_Container& pareto_optimal_resource_container, + // to initialize the first label/resource container + // and to carry the type information + const Resource_Container& rc, const Resource_Extension_Function& ref, + const Dominance_Function& dominance) +{ + // each inner vector corresponds to a pareto-optimal path + std::vector< + std::vector< typename graph_traits< Graph >::edge_descriptor > > + pareto_optimal_solutions; + std::vector< Resource_Container > pareto_optimal_resource_containers; + r_c_shortest_paths_dispatch(g, vertex_index_map, edge_index_map, s, t, + pareto_optimal_solutions, pareto_optimal_resource_containers, false, rc, + ref, dominance, default_r_c_shortest_paths_allocator(), + default_r_c_shortest_paths_visitor()); + if (!pareto_optimal_solutions.empty()) + { + pareto_optimal_solution = pareto_optimal_solutions[0]; + pareto_optimal_resource_container + = pareto_optimal_resource_containers[0]; + } +} +// r_c_shortest_paths + +// check_r_c_path function +template < class Graph, class Resource_Container, + class Resource_Extension_Function > +void check_r_c_path(const Graph& g, + const std::vector< typename graph_traits< Graph >::edge_descriptor >& + ed_vec_path, + const Resource_Container& initial_resource_levels, + // if true, computed accumulated final resource levels must + // be equal to desired_final_resource_levels + // if false, computed accumulated final resource levels must + // be less than or equal to desired_final_resource_levels + bool b_result_must_be_equal_to_desired_final_resource_levels, + const Resource_Container& desired_final_resource_levels, + Resource_Container& actual_final_resource_levels, + const Resource_Extension_Function& ref, bool& b_is_a_path_at_all, + bool& b_feasible, bool& b_correctly_extended, + typename graph_traits< Graph >::edge_descriptor& ed_last_extended_arc) +{ + size_t i_size_ed_vec_path = ed_vec_path.size(); + std::vector< typename graph_traits< Graph >::edge_descriptor > buf_path; + if (i_size_ed_vec_path == 0) + b_feasible = true; + else + { + if (i_size_ed_vec_path == 1 + || target(ed_vec_path[0], g) == source(ed_vec_path[1], g)) + buf_path = ed_vec_path; + else + for (size_t i = i_size_ed_vec_path; i > 0; --i) + buf_path.push_back(ed_vec_path[i - 1]); + for (size_t i = 0; i < i_size_ed_vec_path - 1; ++i) + { + if (target(buf_path[i], g) != source(buf_path[i + 1], g)) + { + b_is_a_path_at_all = false; + b_feasible = false; + b_correctly_extended = false; + return; + } + } + } + b_is_a_path_at_all = true; + b_feasible = true; + b_correctly_extended = false; + Resource_Container current_resource_levels = initial_resource_levels; + actual_final_resource_levels = current_resource_levels; + for (size_t i = 0; i < i_size_ed_vec_path; ++i) + { + ed_last_extended_arc = buf_path[i]; + b_feasible = ref(g, actual_final_resource_levels, + current_resource_levels, buf_path[i]); + current_resource_levels = actual_final_resource_levels; + if (!b_feasible) + return; + } + if (b_result_must_be_equal_to_desired_final_resource_levels) + b_correctly_extended + = actual_final_resource_levels == desired_final_resource_levels + ? true + : false; + else + { + if (actual_final_resource_levels < desired_final_resource_levels + || actual_final_resource_levels == desired_final_resource_levels) + b_correctly_extended = true; + } +} // check_path + +} // namespace + +#endif // BOOST_GRAPH_R_C_SHORTEST_PATHS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/random.hpp b/contrib/restricted/boost/graph/include/boost/graph/random.hpp new file mode 100644 index 0000000000..4c1261b110 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/random.hpp @@ -0,0 +1,290 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright (C) Vladimir Prus 2003 +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_RANDOM_HPP +#define BOOST_GRAPH_RANDOM_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/random/uniform_int.hpp> +#include <boost/random/uniform_real.hpp> +#include <boost/random/variate_generator.hpp> + +#include <boost/pending/property.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/next_prior.hpp> + +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/copy.hpp> +#include <boost/mpl/if.hpp> +#include <boost/type_traits/is_convertible.hpp> + +#include <iostream> +#include <boost/assert.hpp> + +namespace boost +{ + +// grab a random vertex from the graph's vertex set +template < class Graph, class RandomNumGen > +typename graph_traits< Graph >::vertex_descriptor random_vertex( + Graph& g, RandomNumGen& gen) +{ + if (num_vertices(g) > 1) + { +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) + std::size_t n = std::random(num_vertices(g)); +#else + uniform_int<> distrib(0, num_vertices(g) - 1); + variate_generator< RandomNumGen&, uniform_int<> > rand_gen( + gen, distrib); + std::size_t n = rand_gen(); +#endif + typename graph_traits< Graph >::vertex_iterator i = vertices(g).first; + return *(boost::next(i, n)); + } + else + return *vertices(g).first; +} + +template < class Graph, class RandomNumGen > +typename graph_traits< Graph >::edge_descriptor random_edge( + Graph& g, RandomNumGen& gen) +{ + if (num_edges(g) > 1) + { +#if BOOST_WORKAROUND(BOOST_BORLANDC, BOOST_TESTED_AT(0x581)) + typename graph_traits< Graph >::edges_size_type n + = std::random(num_edges(g)); +#else + uniform_int<> distrib(0, num_edges(g) - 1); + variate_generator< RandomNumGen&, uniform_int<> > rand_gen( + gen, distrib); + typename graph_traits< Graph >::edges_size_type n = rand_gen(); +#endif + typename graph_traits< Graph >::edge_iterator i = edges(g).first; + return *(boost::next(i, n)); + } + else + return *edges(g).first; +} + +template < typename Graph, typename RandomNumGen > +typename graph_traits< Graph >::edge_descriptor random_out_edge(Graph& g, + typename graph_traits< Graph >::vertex_descriptor src, RandomNumGen& gen) +{ + typedef typename graph_traits< Graph >::degree_size_type degree_size_type; + typedef boost::uniform_int< degree_size_type > ui_type; + ui_type ui(0, out_degree(src, g) - 1); + boost::variate_generator< RandomNumGen&, ui_type > variate(gen, ui); + typename graph_traits< Graph >::out_edge_iterator it + = out_edges(src, g).first; + std::advance(it, variate()); + return *it; +} + +template < typename Graph, typename WeightMap, typename RandomNumGen > +typename graph_traits< Graph >::edge_descriptor weighted_random_out_edge( + Graph& g, typename graph_traits< Graph >::vertex_descriptor src, + WeightMap weight, RandomNumGen& gen) +{ + typedef typename property_traits< WeightMap >::value_type weight_type; + weight_type weight_sum(0); + BGL_FORALL_OUTEDGES_T(src, e, g, Graph) { weight_sum += get(weight, e); } + typedef boost::uniform_real<> ur_type; + ur_type ur(0, weight_sum); + boost::variate_generator< RandomNumGen&, ur_type > variate(gen, ur); + weight_type chosen_weight = variate(); + BGL_FORALL_OUTEDGES_T(src, e, g, Graph) + { + weight_type w = get(weight, e); + if (chosen_weight < w) + { + return e; + } + else + { + chosen_weight -= w; + } + } + BOOST_ASSERT(false); // Should not get here + return typename graph_traits< Graph >::edge_descriptor(); +} + +namespace detail +{ + class dummy_property_copier + { + public: + template < class V1, class V2 > + void operator()(const V1&, const V2&) const + { + } + }; +} + +template < typename MutableGraph, class RandNumGen > +void generate_random_graph1(MutableGraph& g, + typename graph_traits< MutableGraph >::vertices_size_type V, + typename graph_traits< MutableGraph >::vertices_size_type E, + RandNumGen& gen, bool allow_parallel = true, bool self_edges = false) +{ + typedef graph_traits< MutableGraph > Traits; + typedef typename Traits::edge_descriptor edge_t; + typedef typename Traits::vertices_size_type v_size_t; + typedef typename Traits::edges_size_type e_size_t; + typedef typename Traits::vertex_descriptor vertex_descriptor; + + // When parallel edges are not allowed, we create a new graph which + // does not allow parallel edges, construct it and copy back. + // This is not efficient if 'g' already disallow parallel edges, + // but that's task for later. + if (!allow_parallel) + { + + typedef + typename boost::graph_traits< MutableGraph >::directed_category dir; + typedef typename mpl::if_< is_convertible< dir, directed_tag >, + directedS, undirectedS >::type select; + adjacency_list< setS, vecS, select > g2; + generate_random_graph1(g2, V, E, gen, true, self_edges); + + copy_graph(g2, g, + vertex_copy(detail::dummy_property_copier()) + .edge_copy(detail::dummy_property_copier())); + } + else + { + + for (v_size_t i = 0; i < V; ++i) + add_vertex(g); + + e_size_t not_inserted_counter + = 0; /* Number of edge insertion failures */ + e_size_t num_vertices_squared = num_vertices(g) * num_vertices(g); + for (e_size_t j = 0; j < E; /* Increment in body */) + { + vertex_descriptor a = random_vertex(g, gen), b; + do + { + b = random_vertex(g, gen); + } while (self_edges == false && a == b); + edge_t e; + bool inserted; + boost::tie(e, inserted) = add_edge(a, b, g); + if (inserted) + { + ++j; + } + else + { + ++not_inserted_counter; + } + if (not_inserted_counter >= num_vertices_squared) + { + return; /* Rather than looping forever on complete graph */ + } + } + } +} + +template < typename MutableGraph, class RandNumGen > +void generate_random_graph(MutableGraph& g, + typename graph_traits< MutableGraph >::vertices_size_type V, + typename graph_traits< MutableGraph >::vertices_size_type E, + RandNumGen& gen, bool allow_parallel = true, bool self_edges = false) +{ + generate_random_graph1(g, V, E, gen, allow_parallel, self_edges); +} + +template < typename MutableGraph, typename RandNumGen, + typename VertexOutputIterator, typename EdgeOutputIterator > +void generate_random_graph(MutableGraph& g, + typename graph_traits< MutableGraph >::vertices_size_type V, + typename graph_traits< MutableGraph >::vertices_size_type E, + RandNumGen& gen, VertexOutputIterator vertex_out, + EdgeOutputIterator edge_out, bool self_edges = false) +{ + typedef graph_traits< MutableGraph > Traits; + typedef typename Traits::vertices_size_type v_size_t; + typedef typename Traits::edges_size_type e_size_t; + typedef typename Traits::vertex_descriptor vertex_t; + typedef typename Traits::edge_descriptor edge_t; + + for (v_size_t i = 0; i < V; ++i) + *vertex_out++ = add_vertex(g); + + e_size_t not_inserted_counter = 0; /* Number of edge insertion failures */ + e_size_t num_vertices_squared = num_vertices(g) * num_vertices(g); + for (e_size_t j = 0; j < E; /* Increment in body */) + { + vertex_t a = random_vertex(g, gen), b; + do + { + b = random_vertex(g, gen); + } while (self_edges == false && a == b); + edge_t e; + bool inserted; + boost::tie(e, inserted) = add_edge(a, b, g); + if (inserted) + { + *edge_out++ = std::make_pair(source(e, g), target(e, g)); + ++j; + } + else + { + ++not_inserted_counter; + } + if (not_inserted_counter >= num_vertices_squared) + { + return; /* Rather than looping forever on complete graph */ + } + } +} + +namespace detail +{ + + template < class Property, class G, class RandomGenerator > + void randomize_property( + G& g, RandomGenerator& rg, Property, vertex_property_tag) + { + typename property_map< G, Property >::type pm = get(Property(), g); + typename graph_traits< G >::vertex_iterator vi, ve; + for (boost::tie(vi, ve) = vertices(g); vi != ve; ++vi) + { + pm[*vi] = rg(); + } + } + + template < class Property, class G, class RandomGenerator > + void randomize_property( + G& g, RandomGenerator& rg, Property, edge_property_tag) + { + typename property_map< G, Property >::type pm = get(Property(), g); + typename graph_traits< G >::edge_iterator ei, ee; + for (boost::tie(ei, ee) = edges(g); ei != ee; ++ei) + { + pm[*ei] = rg(); + } + } +} + +template < class Property, class G, class RandomGenerator > +void randomize_property(G& g, RandomGenerator& rg) +{ + detail::randomize_property( + g, rg, Property(), typename property_kind< Property >::type()); +} + +} + +#include <boost/graph/iteration_macros_undef.hpp> + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/random_layout.hpp b/contrib/restricted/boost/graph/include/boost/graph/random_layout.hpp new file mode 100644 index 0000000000..757585ced7 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/random_layout.hpp @@ -0,0 +1,35 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_RANDOM_LAYOUT_HPP +#define BOOST_GRAPH_RANDOM_LAYOUT_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/random/uniform_int.hpp> +#include <boost/random/uniform_01.hpp> +#include <boost/random/uniform_real.hpp> +#include <boost/type_traits/is_integral.hpp> +#include <boost/mpl/if.hpp> +#include <boost/graph/iteration_macros.hpp> + +namespace boost +{ + +template < typename Topology, typename Graph, typename PositionMap > +void random_graph_layout( + const Graph& g, PositionMap position_map, const Topology& topology) +{ + BGL_FORALL_VERTICES_T(v, g, Graph) + { + put(position_map, v, topology.random_point()); + } +} + +} // end namespace boost + +#endif // BOOST_GRAPH_RANDOM_LAYOUT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/random_spanning_tree.hpp b/contrib/restricted/boost/graph/include/boost/graph/random_spanning_tree.hpp new file mode 100644 index 0000000000..593261da81 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/random_spanning_tree.hpp @@ -0,0 +1,144 @@ +// Copyright 2010 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Andrew Lumsdaine + +#ifndef BOOST_GRAPH_RANDOM_SPANNING_TREE_HPP +#define BOOST_GRAPH_RANDOM_SPANNING_TREE_HPP + +#include <vector> +#include <boost/assert.hpp> +#include <boost/graph/loop_erased_random_walk.hpp> +#include <boost/graph/random.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/config.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/named_function_params.hpp> + +namespace boost +{ + +namespace detail +{ + // Use Wilson's algorithm (based on loop-free random walks) to generate a + // random spanning tree. The distribution of edges used is controlled by + // the next_edge() function, so this version allows either weighted or + // unweighted selection of trees. + // Algorithm is from http://en.wikipedia.org/wiki/Uniform_spanning_tree + template < typename Graph, typename PredMap, typename ColorMap, + typename NextEdge > + void random_spanning_tree_internal(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, PredMap pred, + ColorMap color, NextEdge next_edge) + { + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + + BOOST_ASSERT(num_vertices(g) + >= 1); // g must also be undirected (or symmetric) and connected + + typedef color_traits< typename property_traits< ColorMap >::value_type > + color_gen; + BGL_FORALL_VERTICES_T(v, g, Graph) put(color, v, color_gen::white()); + + std::vector< vertex_descriptor > path; + + put(color, s, color_gen::black()); + put(pred, s, graph_traits< Graph >::null_vertex()); + + BGL_FORALL_VERTICES_T(v, g, Graph) + { + if (get(color, v) != color_gen::white()) + continue; + loop_erased_random_walk(g, v, next_edge, color, path); + for (typename std::vector< + vertex_descriptor >::const_reverse_iterator i + = path.rbegin(); + boost::next(i) + != (typename std::vector< + vertex_descriptor >::const_reverse_iterator)path.rend(); + ++i) + { + typename std::vector< + vertex_descriptor >::const_reverse_iterator j + = i; + ++j; + BOOST_ASSERT(get(color, *j) == color_gen::gray()); + put(color, *j, color_gen::black()); + put(pred, *j, *i); + } + } + } +} + +// Compute a uniformly-distributed spanning tree on a graph. Use Wilson's +// algorithm: +// @inproceedings{wilson96generating, +// author = {Wilson, David Bruce}, +// title = {Generating random spanning trees more quickly than the cover +// time}, booktitle = {STOC '96: Proceedings of the twenty-eighth annual ACM +// symposium on Theory of computing}, year = {1996}, isbn = {0-89791-785-5}, +// pages = {296--303}, +// location = {Philadelphia, Pennsylvania, United States}, +// doi = {http://doi.acm.org/10.1145/237814.237880}, +// publisher = {ACM}, +// address = {New York, NY, USA}, +// } +// +template < typename Graph, typename Gen, typename PredMap, typename ColorMap > +void random_spanning_tree(const Graph& g, Gen& gen, + typename graph_traits< Graph >::vertex_descriptor root, PredMap pred, + static_property_map< double >, ColorMap color) +{ + unweighted_random_out_edge_gen< Graph, Gen > random_oe(gen); + detail::random_spanning_tree_internal(g, root, pred, color, random_oe); +} + +// Compute a weight-distributed spanning tree on a graph. +template < typename Graph, typename Gen, typename PredMap, typename WeightMap, + typename ColorMap > +void random_spanning_tree(const Graph& g, Gen& gen, + typename graph_traits< Graph >::vertex_descriptor root, PredMap pred, + WeightMap weight, ColorMap color) +{ + weighted_random_out_edge_gen< Graph, WeightMap, Gen > random_oe( + weight, gen); + detail::random_spanning_tree_internal(g, root, pred, color, random_oe); +} + +template < typename Graph, typename Gen, typename P, typename T, typename R > +void random_spanning_tree( + const Graph& g, Gen& gen, const bgl_named_params< P, T, R >& params) +{ + using namespace boost::graph::keywords; + typedef bgl_named_params< P, T, R > params_type; + BOOST_GRAPH_DECLARE_CONVERTED_PARAMETERS(params_type, params) + typedef typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + vertex_descriptor default_vertex = *vertices(g).first; + vertex_descriptor start_vertex = arg_pack[_root_vertex | default_vertex]; + typename boost::parameter::binding< arg_pack_type, + boost::graph::keywords::tag::predecessor_map >::type pred_map + = arg_pack[_predecessor_map]; + static_property_map< double > default_weight_map(1.); + typename boost::parameter::value_type< arg_pack_type, + boost::graph::keywords::tag::weight_map, + static_property_map< double > >::type e_w_map + = arg_pack[_weight_map | default_weight_map]; + typename boost::detail::map_maker< Graph, arg_pack_type, + boost::graph::keywords::tag::color_map, + boost::default_color_type >::map_type c_map + = boost::detail::make_color_map_from_arg_pack(g, arg_pack); + random_spanning_tree(g, gen, start_vertex, pred_map, e_w_map, c_map); +} +} + +#include <boost/graph/iteration_macros_undef.hpp> + +#endif // BOOST_GRAPH_RANDOM_SPANNING_TREE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/read_dimacs.hpp b/contrib/restricted/boost/graph/include/boost/graph/read_dimacs.hpp new file mode 100644 index 0000000000..4e702793b9 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/read_dimacs.hpp @@ -0,0 +1,370 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Jeremy G. Siek, Andrew Lumsdaine, Lie-Quan Lee +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +/* + Reads maximal flow problem in extended DIMACS format. + This works, but could use some polishing. +*/ + +/* ----------------------------------------------------------------- */ + +#ifndef BOOST_GRAPH_READ_DIMACS_HPP +#define BOOST_GRAPH_READ_DIMACS_HPP + +#include <vector> +#include <iostream> +#include <string> +#include <cstdio> +#include <cstring> +#include <cstdlib> + +#include <boost/graph/graph_traits.hpp> + +namespace boost +{ + +namespace detail +{ + + template < class Graph, class CapacityMap, class ReverseEdgeMap > + int read_dimacs_max_flow_internal(Graph& g, CapacityMap capacity, + ReverseEdgeMap reverse_edge, + typename graph_traits< Graph >::vertex_descriptor& src, + typename graph_traits< Graph >::vertex_descriptor& sink, + std::istream& in, bool require_source_and_sink, + const std::string& problem_type) + { + // const int MAXLINE = 100; /* max line length in the input file + // */ + const int ARC_FIELDS = 3; /* no of fields in arc line */ + const int NODE_FIELDS = 2; /* no of fields in node line */ + const int P_FIELDS = 3; /* no of fields in problem line */ + + typedef + typename graph_traits< Graph >::vertex_descriptor vertex_descriptor; + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor; + + std::vector< vertex_descriptor > verts; + + long m, n, /* number of edges and nodes */ + i, head, tail, cap; + + long no_lines = 0, /* no of current input line */ + no_plines = 0, /* no of problem-lines */ + no_nslines = 0, /* no of node-source-lines */ + no_nklines = 0, /* no of node-source-lines */ + no_alines = 0; /* no of arc-lines */ + + std::string in_line; /* for reading input line */ + char pr_type[4]; /* for reading type of the problem */ + char nd; /* source (s) or sink (t) */ + + int k, /* temporary */ + err_no; /* no of detected error */ + + /* -------------- error numbers & error messages ---------------- */ + const int EN1 = 0; + const int EN2 = 1; + const int EN3 = 2; + const int EN4 = 3; + // const int EN6 = 4; + // const int EN10 = 5; + // const int EN7 = 6; + const int EN8 = 7; + const int EN9 = 8; + const int EN11 = 9; + const int EN12 = 10; + // const int EN13 = 11; + const int EN14 = 12; + const int EN16 = 13; + const int EN15 = 14; + const int EN17 = 15; + const int EN18 = 16; + const int EN21 = 17; + const int EN19 = 18; + const int EN20 = 19; + const int EN22 = 20; + + static const char* err_message[] = { + /* 0*/ "more than one problem line.", + /* 1*/ "wrong number of parameters in the problem line.", + /* 2*/ "it is not a Max Flow problem line.", + /* 3*/ "bad value of a parameter in the problem line.", + /* 4*/ "can't obtain enough memory to solve this problem.", + /* 5*/ "more than one line with the problem name.", + /* 6*/ "can't read problem name.", + /* 7*/ "problem description must be before node description.", + /* 8*/ "this parser doesn't support multiply sources and sinks.", + /* 9*/ "wrong number of parameters in the node line.", + /*10*/ "wrong value of parameters in the node line.", + /*11*/ " ", + /*12*/ + "source and sink descriptions must be before arc descriptions.", + /*13*/ "too many arcs in the input.", + /*14*/ "wrong number of parameters in the arc line.", + /*15*/ "wrong value of parameters in the arc line.", + /*16*/ "unknown line type in the input.", + /*17*/ "reading error.", + /*18*/ "not enough arcs in the input.", + /*19*/ "source or sink doesn't have incident arcs.", + /*20*/ "can't read anything from the input file." + }; + /* --------------------------------------------------------------- */ + + /* The main loop: + - reads the line of the input, + - analyses its type, + - checks correctness of parameters, + - puts data to the arrays, + - does service functions + */ + + while (std::getline(in, in_line)) + { + ++no_lines; + + switch (in_line[0]) + { + case 'c': /* skip lines with comments */ + case '\n': /* skip empty lines */ + case '\0': /* skip empty lines at the end of file */ + break; + + case 'p': /* problem description */ + if (no_plines > 0) + /* more than one problem line */ + { + err_no = EN1; + goto error; + } + + no_plines = 1; + + if ( + /* reading problem line: type of problem, no of nodes, no of + arcs */ + std::sscanf( + in_line.c_str(), "%*c %3s %ld %ld", pr_type, &n, &m) + != P_FIELDS) + /*wrong number of parameters in the problem line*/ + { + err_no = EN2; + goto error; + } + + if (pr_type != problem_type) + /*wrong problem type*/ + { + err_no = EN3; + goto error; + } + + if (n <= 0 || m <= 0) + /*wrong value of no of arcs or nodes*/ + { + err_no = EN4; + goto error; + } + + { + for (long vi = 0; vi < n; ++vi) + verts.push_back(add_vertex(g)); + } + break; + + case 'n': /* source(s) description */ + if (no_plines == 0) + /* there was not problem line above */ + { + err_no = EN8; + goto error; + } + + /* reading source or sink */ + k = std::sscanf(in_line.c_str(), "%*c %ld %c", &i, &nd); + --i; // index from 0 + if (k < NODE_FIELDS) + /* node line is incorrect */ + { + err_no = EN11; + goto error; + } + + if (i < 0 || i > n) + /* wrong value of node */ + { + err_no = EN12; + goto error; + } + + switch (nd) + { + case 's': /* source line */ + + if (no_nslines != 0) + /* more than one source line */ + { + err_no = EN9; + goto error; + } + + no_nslines = 1; + src = verts[i]; + break; + + case 't': /* sink line */ + + if (no_nklines != 0) + /* more than one sink line */ + { + err_no = EN9; + goto error; + } + + no_nklines = 1; + sink = verts[i]; + break; + + default: + /* wrong type of node-line */ + err_no = EN12; + goto error; + } + break; + + case 'a': /* arc description */ + if (require_source_and_sink + && (no_nslines == 0 || no_nklines == 0)) + /* there was not source and sink description above */ + { + err_no = EN14; + goto error; + } + + if (no_alines >= m) + /*too many arcs on input*/ + { + err_no = EN16; + goto error; + } + + if ( + /* reading an arc description */ + std::sscanf( + in_line.c_str(), "%*c %ld %ld %ld", &tail, &head, &cap) + != ARC_FIELDS) + /* arc description is not correct */ + { + err_no = EN15; + goto error; + } + + --tail; // index from 0, not 1 + --head; + if (tail < 0 || tail > n || head < 0 || head > n) + /* wrong value of nodes */ + { + err_no = EN17; + goto error; + } + + { + edge_descriptor e1, e2; + bool in1, in2; + boost::tie(e1, in1) = add_edge(verts[tail], verts[head], g); + boost::tie(e2, in2) = add_edge(verts[head], verts[tail], g); + if (!in1 || !in2) + { + std::cerr << "unable to add edge (" << head << "," + << tail << ")" << std::endl; + return -1; + } + capacity[e1] = cap; + capacity[e2] = 0; + reverse_edge[e1] = e2; + reverse_edge[e2] = e1; + } + ++no_alines; + break; + + default: + /* unknown type of line */ + err_no = EN18; + goto error; + + } /* end of switch */ + } /* end of input loop */ + + /* ----- all is red or error while reading ----- */ + + if (in.eof() == 0) /* reading error */ + { + err_no = EN21; + goto error; + } + + if (no_lines == 0) /* empty input */ + { + err_no = EN22; + goto error; + } + + if (no_alines < m) /* not enough arcs */ + { + err_no = EN19; + goto error; + } + + if (require_source_and_sink + && (out_degree(src, g) == 0 || out_degree(sink, g) == 0)) + /* no arc goes out of the source */ + { + err_no = EN20; + goto error; + } + + /* Thanks God! all is done */ + return (0); + + /* ---------------------------------- */ + error: /* error found reading input */ + + std::printf( + "\nline %ld of input - %s\n", no_lines, err_message[err_no]); + + return -1; + } + /* -------------------- end of parser -------------------*/ + +} // namespace detail + +template < class Graph, class CapacityMap, class ReverseEdgeMap > +int read_dimacs_max_flow(Graph& g, CapacityMap capacity, + ReverseEdgeMap reverse_edge, + typename graph_traits< Graph >::vertex_descriptor& src, + typename graph_traits< Graph >::vertex_descriptor& sink, + std::istream& in = std::cin) +{ + return detail::read_dimacs_max_flow_internal( + g, capacity, reverse_edge, src, sink, in, true, "max"); +} + +template < class Graph, class CapacityMap, class ReverseEdgeMap > +int read_dimacs_min_cut(Graph& g, CapacityMap capacity, + ReverseEdgeMap reverse_edge, std::istream& in = std::cin) +{ + typename graph_traits< Graph >::vertex_descriptor dummy_src, + dummy_sink; // Not filled in + return detail::read_dimacs_max_flow_internal( + g, capacity, reverse_edge, dummy_src, dummy_sink, in, false, "cut"); +} + +} // namespace boost + +#endif // BOOST_GRAPH_READ_DIMACS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/rmat_graph_generator.hpp b/contrib/restricted/boost/graph/include/boost/graph/rmat_graph_generator.hpp new file mode 100644 index 0000000000..35c71ec347 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/rmat_graph_generator.hpp @@ -0,0 +1,663 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Nick Edmonds +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_RMAT_GENERATOR_HPP +#define BOOST_GRAPH_RMAT_GENERATOR_HPP + +#include <math.h> +#include <iterator> +#include <utility> +#include <vector> +#include <queue> +#include <map> +#include <boost/shared_ptr.hpp> +#include <boost/assert.hpp> +#include <boost/random/uniform_int.hpp> +#include <boost/random/uniform_01.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/detail/mpi_include.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/type_traits/is_same.hpp> +// #include <boost/test/floating_point_comparison.hpp> + +using boost::shared_ptr; +using boost::uniform_01; + +// Returns floor(log_2(n)), and -1 when n is 0 +template < typename IntegerType > inline int int_log2(IntegerType n) +{ + int l = 0; + while (n > 0) + { + ++l; + n >>= 1; + } + return l - 1; +} + +struct keep_all_edges +{ + template < typename T > bool operator()(const T&, const T&) { return true; } +}; + +template < typename Distribution, typename ProcessId > struct keep_local_edges +{ + + keep_local_edges(const Distribution& distrib, const ProcessId& id) + : distrib(distrib), id(id) + { + } + + template < typename T > bool operator()(const T& x, const T& y) + { + return distrib(x) == id || distrib(y) == id; + } + +private: + const Distribution& distrib; + const ProcessId& id; +}; + +template < typename RandomGenerator, typename T > +void generate_permutation_vector( + RandomGenerator& gen, std::vector< T >& vertexPermutation, T n) +{ + using boost::uniform_int; + + vertexPermutation.resize(n); + + // Generate permutation map of vertex numbers + uniform_int< T > rand_vertex(0, n - 1); + for (T i = 0; i < n; ++i) + vertexPermutation[i] = i; + + // Can't use std::random_shuffle unless we create another (synchronized) + // PRNG + for (T i = 0; i < n; ++i) + std::swap(vertexPermutation[i], vertexPermutation[rand_vertex(gen)]); +} + +template < typename RandomGenerator, typename T > +std::pair< T, T > generate_edge( + shared_ptr< uniform_01< RandomGenerator > > prob, T n, unsigned int SCALE, + double a, double b, double c, double d) +{ + T u = 0, v = 0; + T step = n / 2; + for (unsigned int j = 0; j < SCALE; ++j) + { + double p = (*prob)(); + + if (p < a) + ; + else if (p >= a && p < a + b) + v += step; + else if (p >= a + b && p < a + b + c) + u += step; + else + { // p > a + b + c && p < a + b + c + d + u += step; + v += step; + } + + step /= 2; + + // 0.2 and 0.9 are hardcoded in the reference SSCA implementation. + // The maximum change in any given value should be less than 10% + a *= 0.9 + 0.2 * (*prob)(); + b *= 0.9 + 0.2 * (*prob)(); + c *= 0.9 + 0.2 * (*prob)(); + d *= 0.9 + 0.2 * (*prob)(); + + double S = a + b + c + d; + + a /= S; + b /= S; + c /= S; + // d /= S; + // Ensure all values add up to 1, regardless of floating point errors + d = 1. - a - b - c; + } + + return std::make_pair(u, v); +} + +namespace boost +{ + +/* + Chakrabarti's R-MAT scale free generator. + + For all flavors of the R-MAT iterator a+b+c+d must equal 1 and for the + unique_rmat_iterator 'm' << 'n^2'. If 'm' is too close to 'n^2' the + generator may be unable to generate sufficient unique edges + + To get a true scale free distribution {a, b, c, d : a > b, a > c, a > d} +*/ + +template < typename RandomGenerator, typename Graph > class rmat_iterator +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + typedef typename graph_traits< Graph >::edges_size_type edges_size_type; + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; // Not used + + // No argument constructor, set to terminating condition + rmat_iterator() : gen(), edge(0) {} + + // Initialize for edge generation + rmat_iterator(RandomGenerator& gen, vertices_size_type n, edges_size_type m, + double a, double b, double c, double d, bool permute_vertices = true) + : gen() + , n(n) + , a(a) + , b(b) + , c(c) + , d(d) + , edge(m) + , permute_vertices(permute_vertices) + , SCALE(int_log2(n)) + + { + this->gen.reset(new uniform_01< RandomGenerator >(gen)); + + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + + // d, 1., 1.e-5)); + + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + // TODO: Generate the entire adjacency matrix then "Clip and flip" if + // undirected graph + + // Generate the first edge + vertices_size_type u, v; + boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (permute_vertices) + current + = std::make_pair(vertexPermutation[u], vertexPermutation[v]); + else + current = std::make_pair(u, v); + + --edge; + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + rmat_iterator& operator++() + { + vertices_size_type u, v; + boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (permute_vertices) + current + = std::make_pair(vertexPermutation[u], vertexPermutation[v]); + else + current = std::make_pair(u, v); + + --edge; + + return *this; + } + + rmat_iterator operator++(int) + { + rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const rmat_iterator& other) const + { + return edge == other.edge; + } + + bool operator!=(const rmat_iterator& other) const + { + return !(*this == other); + } + +private: + // Parameters + shared_ptr< uniform_01< RandomGenerator > > gen; + vertices_size_type n; + double a, b, c, d; + int edge; + bool permute_vertices; + int SCALE; + + // Internal data structures + std::vector< vertices_size_type > vertexPermutation; + value_type current; +}; + +// Sorted version for CSR +template < typename T > struct sort_pair +{ + bool operator()(const std::pair< T, T >& x, const std::pair< T, T >& y) + { + if (x.first == y.first) + return x.second > y.second; + else + return x.first > y.first; + } +}; + +template < typename RandomGenerator, typename Graph, + typename EdgePredicate = keep_all_edges > +class sorted_rmat_iterator +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + typedef typename graph_traits< Graph >::edges_size_type edges_size_type; + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; // Not used + + // No argument constructor, set to terminating condition + sorted_rmat_iterator() + : gen(), values(sort_pair< vertices_size_type >()), done(true) + { + } + + // Initialize for edge generation + sorted_rmat_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, double a, double b, double c, double d, + bool permute_vertices = true, EdgePredicate ep = keep_all_edges()) + : gen() + , permute_vertices(permute_vertices) + , values(sort_pair< vertices_size_type >()) + , done(false) + + { + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + + // d, 1., 1.e-5)); + + this->gen.reset(new uniform_01< RandomGenerator >(gen)); + + std::vector< vertices_size_type > vertexPermutation; + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + // TODO: "Clip and flip" if undirected graph + int SCALE = int_log2(n); + + for (edges_size_type i = 0; i < m; ++i) + { + + vertices_size_type u, v; + boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (permute_vertices) + { + if (ep(vertexPermutation[u], vertexPermutation[v])) + values.push(std::make_pair( + vertexPermutation[u], vertexPermutation[v])); + } + else + { + if (ep(u, v)) + values.push(std::make_pair(u, v)); + } + } + + current = values.top(); + values.pop(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + sorted_rmat_iterator& operator++() + { + if (!values.empty()) + { + current = values.top(); + values.pop(); + } + else + done = true; + + return *this; + } + + sorted_rmat_iterator operator++(int) + { + sorted_rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const sorted_rmat_iterator& other) const + { + return values.empty() && other.values.empty() && done && other.done; + } + + bool operator!=(const sorted_rmat_iterator& other) const + { + return !(*this == other); + } + +private: + // Parameters + shared_ptr< uniform_01< RandomGenerator > > gen; + bool permute_vertices; + + // Internal data structures + std::priority_queue< value_type, std::vector< value_type >, + sort_pair< vertices_size_type > > + values; + value_type current; + bool done; +}; + +// This version is slow but guarantees unique edges +template < typename RandomGenerator, typename Graph, + typename EdgePredicate = keep_all_edges > +class unique_rmat_iterator +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + typedef typename graph_traits< Graph >::edges_size_type edges_size_type; + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; // Not used + + // No argument constructor, set to terminating condition + unique_rmat_iterator() : gen(), done(true) {} + + // Initialize for edge generation + unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, double a, double b, double c, double d, + bool permute_vertices = true, EdgePredicate ep = keep_all_edges()) + : gen(), done(false) + + { + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + + // d, 1., 1.e-5)); + + this->gen.reset(new uniform_01< RandomGenerator >(gen)); + + std::vector< vertices_size_type > vertexPermutation; + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + int SCALE = int_log2(n); + + std::map< value_type, bool > edge_map; + + edges_size_type edges = 0; + do + { + vertices_size_type u, v; + boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + // Lowest vertex number always comes first + // (this means we don't have to worry about i->j and j->i being in + // the edge list) + if (u > v && is_same< directed_category, undirected_tag >::value) + std::swap(u, v); + + if (edge_map.find(std::make_pair(u, v)) == edge_map.end()) + { + edge_map[std::make_pair(u, v)] = true; + + if (permute_vertices) + { + if (ep(vertexPermutation[u], vertexPermutation[v])) + values.push_back(std::make_pair( + vertexPermutation[u], vertexPermutation[v])); + } + else + { + if (ep(u, v)) + values.push_back(std::make_pair(u, v)); + } + + edges++; + } + } while (edges < m); + // NGE - Asking for more than n^2 edges will result in an infinite loop + // here + // Asking for a value too close to n^2 edges may as well + + current = values.back(); + values.pop_back(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + unique_rmat_iterator& operator++() + { + if (!values.empty()) + { + current = values.back(); + values.pop_back(); + } + else + done = true; + + return *this; + } + + unique_rmat_iterator operator++(int) + { + unique_rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const unique_rmat_iterator& other) const + { + return values.empty() && other.values.empty() && done && other.done; + } + + bool operator!=(const unique_rmat_iterator& other) const + { + return !(*this == other); + } + +private: + // Parameters + shared_ptr< uniform_01< RandomGenerator > > gen; + + // Internal data structures + std::vector< value_type > values; + value_type current; + bool done; +}; + +// This version is slow but guarantees unique edges +template < typename RandomGenerator, typename Graph, + typename EdgePredicate = keep_all_edges > +class sorted_unique_rmat_iterator +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + typedef typename graph_traits< Graph >::edges_size_type edges_size_type; + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef std::ptrdiff_t difference_type; // Not used + + // No argument constructor, set to terminating condition + sorted_unique_rmat_iterator() + : gen(), values(sort_pair< vertices_size_type >()), done(true) + { + } + + // Initialize for edge generation + sorted_unique_rmat_iterator(RandomGenerator& gen, vertices_size_type n, + edges_size_type m, double a, double b, double c, double d, + bool bidirectional = false, bool permute_vertices = true, + EdgePredicate ep = keep_all_edges()) + : gen() + , bidirectional(bidirectional) + , values(sort_pair< vertices_size_type >()) + , done(false) + + { + // BOOST_ASSERT(boost::test_tools::check_is_close(a + b + c + + // d, 1., 1.e-5)); + + this->gen.reset(new uniform_01< RandomGenerator >(gen)); + + std::vector< vertices_size_type > vertexPermutation; + if (permute_vertices) + generate_permutation_vector(gen, vertexPermutation, n); + + int SCALE = int_log2(n); + + std::map< value_type, bool > edge_map; + + edges_size_type edges = 0; + do + { + + vertices_size_type u, v; + boost::tie(u, v) = generate_edge(this->gen, n, SCALE, a, b, c, d); + + if (bidirectional) + { + if (edge_map.find(std::make_pair(u, v)) == edge_map.end()) + { + edge_map[std::make_pair(u, v)] = true; + edge_map[std::make_pair(v, u)] = true; + + if (ep(u, v)) + { + if (permute_vertices) + { + values.push(std::make_pair( + vertexPermutation[u], vertexPermutation[v])); + values.push(std::make_pair( + vertexPermutation[v], vertexPermutation[u])); + } + else + { + values.push(std::make_pair(u, v)); + values.push(std::make_pair(v, u)); + } + } + + ++edges; + } + } + else + { + // Lowest vertex number always comes first + // (this means we don't have to worry about i->j and j->i being + // in the edge list) + if (u > v + && is_same< directed_category, undirected_tag >::value) + std::swap(u, v); + + if (edge_map.find(std::make_pair(u, v)) == edge_map.end()) + { + edge_map[std::make_pair(u, v)] = true; + + if (permute_vertices) + { + if (ep(vertexPermutation[u], vertexPermutation[v])) + values.push(std::make_pair( + vertexPermutation[u], vertexPermutation[v])); + } + else + { + if (ep(u, v)) + values.push(std::make_pair(u, v)); + } + + ++edges; + } + } + + } while (edges < m); + // NGE - Asking for more than n^2 edges will result in an infinite loop + // here + // Asking for a value too close to n^2 edges may as well + + current = values.top(); + values.pop(); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + sorted_unique_rmat_iterator& operator++() + { + if (!values.empty()) + { + current = values.top(); + values.pop(); + } + else + done = true; + + return *this; + } + + sorted_unique_rmat_iterator operator++(int) + { + sorted_unique_rmat_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const sorted_unique_rmat_iterator& other) const + { + return values.empty() && other.values.empty() && done && other.done; + } + + bool operator!=(const sorted_unique_rmat_iterator& other) const + { + return !(*this == other); + } + +private: + // Parameters + shared_ptr< uniform_01< RandomGenerator > > gen; + bool bidirectional; + + // Internal data structures + std::priority_queue< value_type, std::vector< value_type >, + sort_pair< vertices_size_type > > + values; + value_type current; + bool done; +}; + +} // end namespace boost + + + +#endif // BOOST_GRAPH_RMAT_GENERATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/sequential_vertex_coloring.hpp b/contrib/restricted/boost/graph/include/boost/graph/sequential_vertex_coloring.hpp new file mode 100644 index 0000000000..fcfa24301e --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/sequential_vertex_coloring.hpp @@ -0,0 +1,126 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2004 The Trustees of Indiana University +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_SEQUENTIAL_VERTEX_COLORING_HPP +#define BOOST_GRAPH_SEQUENTIAL_VERTEX_COLORING_HPP + +#include <vector> +#include <boost/graph/graph_traits.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/limits.hpp> + +#ifdef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS +#include <iterator> +#endif + +/* This algorithm is to find coloring of a graph + + Algorithm: + Let G = (V,E) be a graph with vertices (somehow) ordered v_1, v_2, ..., + v_n. For k = 1, 2, ..., n the sequential algorithm assigns v_k to the + smallest possible color. + + Reference: + + Thomas F. Coleman and Jorge J. More, Estimation of sparse Jacobian + matrices and graph coloring problems. J. Numer. Anal. V20, P187-209, 1983 + + v_k is stored as o[k] here. + + The color of the vertex v will be stored in color[v]. + i.e., vertex v belongs to coloring color[v] */ + +namespace boost +{ +template < class VertexListGraph, class OrderPA, class ColorMap > +typename property_traits< ColorMap >::value_type sequential_vertex_coloring( + const VertexListGraph& G, OrderPA order, ColorMap color) +{ + typedef graph_traits< VertexListGraph > GraphTraits; + typedef typename GraphTraits::vertex_descriptor Vertex; + typedef typename property_traits< ColorMap >::value_type size_type; + + size_type max_color = 0; + const size_type V = num_vertices(G); + + // We need to keep track of which colors are used by + // adjacent vertices. We do this by marking the colors + // that are used. The mark array contains the mark + // for each color. The length of mark is the + // number of vertices since the maximum possible number of colors + // is the number of vertices. + std::vector< size_type > mark(V, + std::numeric_limits< size_type >::max + BOOST_PREVENT_MACRO_SUBSTITUTION()); + + // Initialize colors + typename GraphTraits::vertex_iterator v, vend; + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) + put(color, *v, V - 1); + + // Determine the color for every vertex one by one + for (size_type i = 0; i < V; i++) + { + Vertex current = get(order, i); + typename GraphTraits::adjacency_iterator v, vend; + + // Mark the colors of vertices adjacent to current. + // i can be the value for marking since i increases successively + for (boost::tie(v, vend) = adjacent_vertices(current, G); v != vend; + ++v) + mark[get(color, *v)] = i; + + // Next step is to assign the smallest un-marked color + // to the current vertex. + size_type j = 0; + + // Scan through all useable colors, find the smallest possible + // color that is not used by neighbors. Note that if mark[j] + // is equal to i, color j is used by one of the current vertex's + // neighbors. + while (j < max_color && mark[j] == i) + ++j; + + if (j == max_color) // All colors are used up. Add one more color + ++max_color; + + // At this point, j is the smallest possible color + put(color, current, j); // Save the color of vertex current + } + + return max_color; +} + +template < class VertexListGraph, class ColorMap > +typename property_traits< ColorMap >::value_type sequential_vertex_coloring( + const VertexListGraph& G, ColorMap color) +{ + typedef typename graph_traits< VertexListGraph >::vertex_descriptor + vertex_descriptor; + typedef typename graph_traits< VertexListGraph >::vertex_iterator + vertex_iterator; + + std::pair< vertex_iterator, vertex_iterator > v = vertices(G); +#ifndef BOOST_NO_TEMPLATED_ITERATOR_CONSTRUCTORS + std::vector< vertex_descriptor > order(v.first, v.second); +#else + std::vector< vertex_descriptor > order; + order.reserve(std::distance(v.first, v.second)); + while (v.first != v.second) + order.push_back(*v.first++); +#endif + return sequential_vertex_coloring(G, + make_iterator_property_map(order.begin(), identity_property_map(), + graph_traits< VertexListGraph >::null_vertex()), + color); +} +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/simple_point.hpp b/contrib/restricted/boost/graph/include/boost/graph/simple_point.hpp new file mode 100644 index 0000000000..0e3dffca63 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/simple_point.hpp @@ -0,0 +1,23 @@ +//======================================================================= +// Copyright 2005 Trustees of Indiana University +// Authors: Andrew Lumsdaine, Douglas Gregor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_SIMPLE_POINT_HPP +#define BOOST_GRAPH_SIMPLE_POINT_HPP + +namespace boost +{ + +template < typename T > struct simple_point +{ + T x; + T y; +}; + +} // end namespace boost + +#endif // BOOST_GRAPH_SIMPLE_POINT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/sloan_ordering.hpp b/contrib/restricted/boost/graph/include/boost/graph/sloan_ordering.hpp new file mode 100644 index 0000000000..88f845b81c --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/sloan_ordering.hpp @@ -0,0 +1,448 @@ +// +//======================================================================= +// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) +// ETH Zurich, Center of Structure Technologies +// (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_SLOAN_HPP +#define BOOST_GRAPH_SLOAN_HPP + +#define WEIGHT1 1 // default weight for the distance in the Sloan algorithm +#define WEIGHT2 2 // default weight for the degree in the Sloan algorithm + +#include <boost/config.hpp> +#include <vector> +#include <queue> +#include <algorithm> +#include <limits> +#include <boost/pending/queue.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/breadth_first_search.hpp> +#include <boost/graph/properties.hpp> +#include <boost/pending/indirect_cmp.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/visitors.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/cuthill_mckee_ordering.hpp> + +//////////////////////////////////////////////////////////// +// +// Sloan-Algorithm for graph reordering +//(optimzes profile and wavefront, not primiraly bandwidth +// +//////////////////////////////////////////////////////////// + +namespace boost +{ + +///////////////////////////////////////////////////////////////////////// +// Function that returns the maximum depth of +// a rooted level strucutre (RLS) +// +///////////////////////////////////////////////////////////////////////// +template < class Distance > typename Distance::value_type RLS_depth(Distance& d) +{ + typename Distance::value_type h_s = 0; + typename Distance::iterator iter; + + for (iter = d.begin(); iter != d.end(); ++iter) + { + if (*iter > h_s) + { + h_s = *iter; + } + } + + return h_s; +} + +///////////////////////////////////////////////////////////////////////// +// Function that returns the width of the largest level of +// a rooted level strucutre (RLS) +// +///////////////////////////////////////////////////////////////////////// +template < class Distance, class my_int > +typename Distance::value_type RLS_max_width(Distance& d, my_int depth) +{ + + typedef typename Distance::value_type Degree; + + // Searching for the maximum width of a level + std::vector< Degree > dummy_width(depth + 1, 0); + typename std::vector< Degree >::iterator my_it; + typename Distance::iterator iter; + Degree w_max = 0; + + for (iter = d.begin(); iter != d.end(); ++iter) + { + dummy_width[*iter]++; + } + + for (my_it = dummy_width.begin(); my_it != dummy_width.end(); ++my_it) + { + if (*my_it > w_max) + w_max = *my_it; + } + + return w_max; +} + +///////////////////////////////////////////////////////////////////////// +// Function for finding a good starting node for Sloan algorithm +// +// This is to find a good starting node. "good" is in the sense +// of the ordering generated. +///////////////////////////////////////////////////////////////////////// +template < class Graph, class ColorMap, class DegreeMap > +typename graph_traits< Graph >::vertex_descriptor sloan_start_end_vertices( + Graph& G, typename graph_traits< Graph >::vertex_descriptor& s, + ColorMap color, DegreeMap degree) +{ + typedef typename property_traits< DegreeMap >::value_type Degree; + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename std::vector< + typename graph_traits< Graph >::vertices_size_type >::iterator vec_iter; + typedef typename graph_traits< Graph >::vertices_size_type size_type; + + typedef typename property_map< Graph, vertex_index_t >::const_type VertexID; + + s = *(vertices(G).first); + Vertex e = s; + Vertex i; + Degree my_degree = get(degree, s); + Degree dummy, h_i, h_s, w_i, w_e; + bool new_start = true; + Degree maximum_degree = 0; + + // Creating a std-vector for storing the distance from the start vertex in + // dist + std::vector< typename graph_traits< Graph >::vertices_size_type > dist( + num_vertices(G), 0); + + // Wrap a property_map_iterator around the std::iterator + boost::iterator_property_map< vec_iter, VertexID, size_type, size_type& > + dist_pmap(dist.begin(), get(vertex_index, G)); + + // Creating a property_map for the indices of a vertex + typename property_map< Graph, vertex_index_t >::type index_map + = get(vertex_index, G); + + // Creating a priority queue + typedef indirect_cmp< DegreeMap, std::greater< Degree > > Compare; + Compare comp(degree); + std::priority_queue< Vertex, std::vector< Vertex >, Compare > degree_queue( + comp); + + // step 1 + // Scan for the vertex with the smallest degree and the maximum degree + typename graph_traits< Graph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + { + dummy = get(degree, *ui); + + if (dummy < my_degree) + { + my_degree = dummy; + s = *ui; + } + + if (dummy > maximum_degree) + { + maximum_degree = dummy; + } + } + // end 1 + + do + { + new_start = false; // Setting the loop repetition status to false + + // step 2 + // initialize the the disance std-vector with 0 + for (typename std::vector< typename graph_traits< + Graph >::vertices_size_type >::iterator iter + = dist.begin(); + iter != dist.end(); ++iter) + *iter = 0; + + // generating the RLS (rooted level structure) + breadth_first_search(G, s, + visitor( + make_bfs_visitor(record_distances(dist_pmap, on_tree_edge())))); + + // end 2 + + // step 3 + // calculating the depth of the RLS + h_s = RLS_depth(dist); + + // step 4 + // pushing one node of each degree in an ascending manner into + // degree_queue + std::vector< bool > shrink_trace(maximum_degree, false); + for (boost::tie(ui, ui_end) = vertices(G); ui != ui_end; ++ui) + { + dummy = get(degree, *ui); + + if ((dist[index_map[*ui]] == h_s) && (!shrink_trace[dummy])) + { + degree_queue.push(*ui); + shrink_trace[dummy] = true; + } + } + + // end 3 & 4 + + // step 5 + // Initializing w + w_e = (std::numeric_limits< Degree >::max)(); + // end 5 + + // step 6 + // Testing for termination + while (!degree_queue.empty()) + { + i = degree_queue.top(); // getting the node with the lowest degree + // from the degree queue + degree_queue.pop(); // ereasing the node with the lowest degree from + // the degree queue + + // generating a RLS + for (typename std::vector< typename graph_traits< + Graph >::vertices_size_type >::iterator iter + = dist.begin(); + iter != dist.end(); ++iter) + *iter = 0; + + breadth_first_search(G, i, + boost::visitor(make_bfs_visitor( + record_distances(dist_pmap, on_tree_edge())))); + + // Calculating depth and width of the rooted level + h_i = RLS_depth(dist); + w_i = RLS_max_width(dist, h_i); + + // Testing for termination + if ((h_i > h_s) && (w_i < w_e)) + { + h_s = h_i; + s = i; + while (!degree_queue.empty()) + degree_queue.pop(); + new_start = true; + } + else if (w_i < w_e) + { + w_e = w_i; + e = i; + } + } + // end 6 + + } while (new_start); + + return e; +} + +////////////////////////////////////////////////////////////////////////// +// Sloan algorithm with a given starting Vertex. +// +// This algorithm requires user to provide a starting vertex to +// compute Sloan ordering. +////////////////////////////////////////////////////////////////////////// +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap, + class PriorityMap, class Weight > +OutputIterator sloan_ordering(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor e, + OutputIterator permutation, ColorMap color, DegreeMap degree, + PriorityMap priority, Weight W1, Weight W2) +{ + // typedef typename property_traits<DegreeMap>::value_type Degree; + typedef typename property_traits< PriorityMap >::value_type Degree; + typedef typename property_traits< ColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename std::vector< + typename graph_traits< Graph >::vertices_size_type >::iterator vec_iter; + typedef typename graph_traits< Graph >::vertices_size_type size_type; + + typedef typename property_map< Graph, vertex_index_t >::const_type VertexID; + + // Creating a std-vector for storing the distance from the end vertex in it + typename std::vector< typename graph_traits< Graph >::vertices_size_type > + dist(num_vertices(g), 0); + + // Wrap a property_map_iterator around the std::iterator + boost::iterator_property_map< vec_iter, VertexID, size_type, size_type& > + dist_pmap(dist.begin(), get(vertex_index, g)); + + breadth_first_search(g, e, + visitor(make_bfs_visitor(record_distances(dist_pmap, on_tree_edge())))); + + // Creating a property_map for the indices of a vertex + typename property_map< Graph, vertex_index_t >::type index_map + = get(vertex_index, g); + + // Sets the color and priority to their initial status + Degree cdeg; + typename graph_traits< Graph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + put(color, *ui, Color::white()); + cdeg = get(degree, *ui) + 1; + put(priority, *ui, W1 * dist[index_map[*ui]] - W2 * cdeg); + } + + // Priority list + typedef indirect_cmp< PriorityMap, std::greater< Degree > > Compare; + Compare comp(priority); + std::list< Vertex > priority_list; + + // Some more declarations + typename graph_traits< Graph >::out_edge_iterator ei, ei_end, ei2, ei2_end; + Vertex u, v, w; + + put(color, s, + Color::green()); // Sets the color of the starting vertex to gray + priority_list.push_front(s); // Puts s into the priority_list + + while (!priority_list.empty()) + { + priority_list.sort(comp); // Orders the elements in the priority list in + // an ascending manner + + u = priority_list + .front(); // Accesses the last element in the priority list + priority_list + .pop_front(); // Removes the last element in the priority list + + if (get(color, u) == Color::green()) + { + // for-loop over all out-edges of vertex u + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) + { + v = target(*ei, g); + + put(priority, v, get(priority, v) + W2); // updates the priority + + if (get(color, v) + == Color::white()) // test if the vertex is inactive + { + put(color, v, + Color::green()); // giving the vertex a preactive status + priority_list.push_front( + v); // writing the vertex in the priority_queue + } + } + } + + // Here starts step 8 + *permutation++ + = u; // Puts u to the first position in the permutation-vector + put(color, u, Color::black()); // Gives u an inactive status + + // for loop over all the adjacent vertices of u + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) + { + + v = target(*ei, g); + + if (get(color, v) == Color::green()) + { // tests if the vertex is inactive + + put(color, v, + Color::red()); // giving the vertex an active status + put(priority, v, get(priority, v) + W2); // updates the priority + + // for loop over alll adjacent vertices of v + for (boost::tie(ei2, ei2_end) = out_edges(v, g); ei2 != ei2_end; + ++ei2) + { + w = target(*ei2, g); + + if (get(color, w) != Color::black()) + { // tests if vertex is postactive + + put(priority, w, + get(priority, w) + W2); // updates the priority + + if (get(color, w) == Color::white()) + { + + put(color, w, Color::green()); // gives the vertex a + // preactive status + priority_list.push_front( + w); // puts the vertex into the priority queue + + } // end if + + } // end if + + } // end for + + } // end if + + } // end for + + } // end while + + return permutation; +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Same algorithm as before, but without the weights given (taking default +// weights +template < class Graph, class OutputIterator, class ColorMap, class DegreeMap, + class PriorityMap > +OutputIterator sloan_ordering(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor e, + OutputIterator permutation, ColorMap color, DegreeMap degree, + PriorityMap priority) +{ + return sloan_ordering( + g, s, e, permutation, color, degree, priority, WEIGHT1, WEIGHT2); +} + +////////////////////////////////////////////////////////////////////////// +// Sloan algorithm without a given starting Vertex. +// +// This algorithm finds a good starting vertex itself to +// compute Sloan-ordering. +////////////////////////////////////////////////////////////////////////// + +template < class Graph, class OutputIterator, class Color, class Degree, + class Priority, class Weight > +inline OutputIterator sloan_ordering(Graph& G, OutputIterator permutation, + Color color, Degree degree, Priority priority, Weight W1, Weight W2) +{ + typedef typename boost::graph_traits< Graph >::vertex_descriptor Vertex; + + Vertex s, e; + e = sloan_start_end_vertices(G, s, color, degree); + + return sloan_ordering( + G, s, e, permutation, color, degree, priority, W1, W2); +} + +///////////////////////////////////////////////////////////////////////////////////////// +// Same as before, but without given weights (default weights are taken instead) +template < class Graph, class OutputIterator, class Color, class Degree, + class Priority > +inline OutputIterator sloan_ordering(Graph& G, OutputIterator permutation, + Color color, Degree degree, Priority priority) +{ + return sloan_ordering( + G, permutation, color, degree, priority, WEIGHT1, WEIGHT2); +} + +} // namespace boost + +#endif // BOOST_GRAPH_SLOAN_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/small_world_generator.hpp b/contrib/restricted/boost/graph/include/boost/graph/small_world_generator.hpp new file mode 100644 index 0000000000..f2d0d084ac --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/small_world_generator.hpp @@ -0,0 +1,132 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP +#define BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP + +#include <iterator> +#include <utility> +#include <boost/graph/graph_traits.hpp> +#include <boost/random/uniform_01.hpp> +#include <boost/random/uniform_int.hpp> + +namespace boost +{ + +// Assumes undirected +template < typename RandomGenerator, typename Graph > class small_world_iterator +{ + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + small_world_iterator() : gen(0) {} + small_world_iterator(RandomGenerator& gen, vertices_size_type n, + vertices_size_type k, double prob = 0.0, bool allow_self_loops = false) + : gen(&gen) + , n(n) + , k(k) + , prob(prob) + , source(0) + , target(allow_self_loops ? 0 : 1) + , allow_self_loops(allow_self_loops) + , current(0, allow_self_loops ? 0 : 1) + { + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + small_world_iterator& operator++() + { + target = (target + 1) % n; + if (target == (source + k / 2 + 1) % n) + { + ++source; + if (allow_self_loops) + target = source; + else + target = (source + 1) % n; + } + current.first = source; + + uniform_01< RandomGenerator, double > rand01(*gen); + uniform_int< vertices_size_type > rand_vertex_gen(0, n - 1); + double x = rand01(); + *gen = rand01.base(); // GRRRR + if (x < prob) + { + vertices_size_type lower = (source + n - k / 2) % n; + vertices_size_type upper = (source + k / 2) % n; + do + { + current.second = rand_vertex_gen(*gen); + } while ((current.second >= lower && current.second <= upper) + || (upper < lower + && (current.second >= lower || current.second <= upper))); + } + else + { + current.second = target; + } + return *this; + } + + small_world_iterator operator++(int) + { + small_world_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const small_world_iterator& other) const + { + if (!gen && other.gen) + return other == *this; + else if (gen && !other.gen) + return source == n; + else if (!gen && !other.gen) + return true; + return source == other.source && target == other.target; + } + + bool operator!=(const small_world_iterator& other) const + { + return !(*this == other); + } + +private: + void next() + { + uniform_int< vertices_size_type > rand_vertex(0, n - 1); + current.first = rand_vertex(*gen); + do + { + current.second = rand_vertex(*gen); + } while (current.first == current.second && !allow_self_loops); + } + + RandomGenerator* gen; + vertices_size_type n; + vertices_size_type k; + double prob; + vertices_size_type source; + vertices_size_type target; + bool allow_self_loops; + value_type current; +}; + +} // end namespace boost + +#endif // BOOST_GRAPH_SMALL_WORLD_GENERATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/smallest_last_ordering.hpp b/contrib/restricted/boost/graph/include/boost/graph/smallest_last_ordering.hpp new file mode 100644 index 0000000000..88af0ea931 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/smallest_last_ordering.hpp @@ -0,0 +1,152 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +// Revision History: +// 17 March 2006: Fixed a bug: when updating the degree a vertex +// could be moved to a wrong bucket. (Roman Dementiev) +// + +#ifndef BOOST_SMALLEST_LAST_VERTEX_ORDERING_HPP +#define BOOST_SMALLEST_LAST_VERTEX_ORDERING_HPP +/* + The smallest-last ordering is defined for the loopless graph G with + vertices a(j), j = 1,2,...,n where a(j) is the j-th column of A and + with edge (a(i),a(j)) if and only if columns i and j have a + non-zero in the same row position. The smallest-last ordering is + determined recursively by letting list(k), k = n,...,1 be a column + with least degree in the subgraph spanned by the un-ordered + columns. + */ +#include <vector> +#include <algorithm> +#include <boost/config.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/pending/bucket_sorter.hpp> + +namespace boost +{ + +template < class VertexListGraph, class Order, class Degree, class Marker > +void smallest_last_vertex_ordering( + const VertexListGraph& G, Order order, Degree degree, Marker marker) +{ + typedef typename boost::graph_traits< VertexListGraph > GraphTraits; + typedef typename GraphTraits::vertex_descriptor Vertex; + // typedef typename GraphTraits::size_type size_type; + typedef std::size_t size_type; + + const size_type num = num_vertices(G); + + typedef + typename boost::property_map< VertexListGraph, vertex_index_t >::type + ID; + typedef bucket_sorter< size_type, Vertex, Degree, ID > BucketSorter; + + BucketSorter degree_bucket_sorter(num, num, degree, get(vertex_index, G)); + + smallest_last_vertex_ordering( + G, order, degree, marker, degree_bucket_sorter); +} + +template < class VertexListGraph, class Order, class Degree, class Marker, + class BucketSorter > +void smallest_last_vertex_ordering(const VertexListGraph& G, Order order, + Degree degree, Marker marker, BucketSorter& degree_buckets) +{ + typedef typename boost::graph_traits< VertexListGraph > GraphTraits; + typedef typename GraphTraits::vertex_descriptor Vertex; + // typedef typename GraphTraits::size_type size_type; + typedef std::size_t size_type; + + const size_type num = num_vertices(G); + + typename GraphTraits::vertex_iterator v, vend; + for (boost::tie(v, vend) = vertices(G); v != vend; ++v) + { + put(marker, *v, num); + put(degree, *v, out_degree(*v, G)); + degree_buckets.push(*v); + } + + size_type minimum_degree = 0; + size_type current_order = num - 1; + + while (1) + { + typedef typename BucketSorter::stack MDStack; + MDStack minimum_degree_stack = degree_buckets[minimum_degree]; + while (minimum_degree_stack.empty()) + minimum_degree_stack = degree_buckets[++minimum_degree]; + + Vertex node = minimum_degree_stack.top(); + put(order, current_order, node); + + if (current_order == 0) // find all vertices + break; + + minimum_degree_stack.pop(); + put(marker, node, 0); // node has been ordered. + + typename GraphTraits::adjacency_iterator v, vend; + for (boost::tie(v, vend) = adjacent_vertices(node, G); v != vend; ++v) + + if (get(marker, *v) > current_order) + { //*v is unordered vertex + put(marker, *v, + current_order); // mark the columns adjacent to node + + // delete *v from the bucket sorter + degree_buckets.remove(*v); + + // It is possible minimum degree goes down + // Here we keep tracking it. + put(degree, *v, get(degree, *v) - 1); + BOOST_USING_STD_MIN(); + minimum_degree = min BOOST_PREVENT_MACRO_SUBSTITUTION( + minimum_degree, get(degree, *v)); + + // reinsert *v in the bucket sorter with the new degree + degree_buckets.push(*v); + } + + current_order--; + } + + // at this point, order[i] = v_i; +} + +template < class VertexListGraph, class Order > +void smallest_last_vertex_ordering(const VertexListGraph& G, Order order) +{ + typedef typename graph_traits< VertexListGraph >::vertex_descriptor + vertex_descriptor; + typedef typename graph_traits< VertexListGraph >::degree_size_type + degree_size_type; + smallest_last_vertex_ordering(G, order, + make_shared_array_property_map( + num_vertices(G), degree_size_type(0), get(vertex_index, G)), + make_shared_array_property_map( + num_vertices(G), (std::size_t)(0), get(vertex_index, G))); +} + +template < class VertexListGraph > +std::vector< typename graph_traits< VertexListGraph >::vertex_descriptor > +smallest_last_vertex_ordering(const VertexListGraph& G) +{ + std::vector< typename graph_traits< VertexListGraph >::vertex_descriptor > + o(num_vertices(G)); + smallest_last_vertex_ordering(G, + make_iterator_property_map( + o.begin(), typed_identity_property_map< std::size_t >())); + return o; +} +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/ssca_graph_generator.hpp b/contrib/restricted/boost/graph/include/boost/graph/ssca_graph_generator.hpp new file mode 100644 index 0000000000..a2281236ca --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/ssca_graph_generator.hpp @@ -0,0 +1,197 @@ +// Copyright 2004, 2005 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Nick Edmonds +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_SSCA_GENERATOR_HPP +#define BOOST_GRAPH_SSCA_GENERATOR_HPP + +#include <iterator> +#include <utility> +#include <vector> +#include <queue> +#include <boost/config.hpp> +#include <boost/random/uniform_int.hpp> +#include <boost/random/uniform_01.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/type_traits/is_base_and_derived.hpp> +#include <boost/type_traits/is_same.hpp> + +enum Direction +{ + FORWARD = 1, + BACKWARD = 2, + BOTH = FORWARD | BACKWARD +}; + +namespace boost +{ + +// This generator generates graphs according to the method specified +// in SSCA 1.1. Current versions of SSCA use R-MAT graphs + +template < typename RandomGenerator, typename Graph > class ssca_iterator +{ + typedef typename graph_traits< Graph >::directed_category directed_category; + typedef + typename graph_traits< Graph >::vertices_size_type vertices_size_type; + +public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< vertices_size_type, vertices_size_type > value_type; + typedef const value_type& reference; + typedef const value_type* pointer; + typedef void difference_type; + + // No argument constructor, set to terminating condition + ssca_iterator() : gen(), verticesRemaining(0) {} + + // Initialize for edge generation + ssca_iterator(RandomGenerator& gen, vertices_size_type totVertices, + vertices_size_type maxCliqueSize, double probUnidirectional, + int maxParallelEdges, double probIntercliqueEdges) + : gen(&gen) + , totVertices(totVertices) + , maxCliqueSize(maxCliqueSize) + , probUnidirectional(probUnidirectional) + , maxParallelEdges(maxParallelEdges) + , probIntercliqueEdges(probIntercliqueEdges) + , currentClique(0) + , verticesRemaining(totVertices) + { + cliqueNum = std::vector< int >(totVertices, -1); + current = std::make_pair(0, 0); + } + + reference operator*() const { return current; } + pointer operator->() const { return ¤t; } + + ssca_iterator& operator++() + { + BOOST_USING_STD_MIN(); + while (values.empty() && verticesRemaining > 0) + { // If there are no values left, generate a new clique + uniform_int< vertices_size_type > clique_size(1, maxCliqueSize); + uniform_int< vertices_size_type > rand_vertex(0, totVertices - 1); + uniform_int< int > num_parallel_edges(1, maxParallelEdges); + uniform_int< short > direction(0, 1); + uniform_01< RandomGenerator > prob(*gen); + std::vector< vertices_size_type > cliqueVertices; + + cliqueVertices.clear(); + vertices_size_type size = min BOOST_PREVENT_MACRO_SUBSTITUTION( + clique_size(*gen), verticesRemaining); + while (cliqueVertices.size() < size) + { + vertices_size_type v = rand_vertex(*gen); + if (cliqueNum[v] == -1) + { + cliqueNum[v] = currentClique; + cliqueVertices.push_back(v); + verticesRemaining--; + } + } // Nick: This is inefficient when only a few vertices remain... + // I should probably just select the remaining vertices + // in order when only a certain fraction remain. + + typename std::vector< vertices_size_type >::iterator first, second; + for (first = cliqueVertices.begin(); first != cliqueVertices.end(); + ++first) + for (second = first + 1; second != cliqueVertices.end(); + ++second) + { + Direction d; + int edges; + + d = prob() < probUnidirectional + ? (direction(*gen) == 0 ? FORWARD : BACKWARD) + : BOTH; + + if (d & FORWARD) + { + edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(*first, *second)); + } + + if (d & BACKWARD) + { + edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(*second, *first)); + } + } + + if (verticesRemaining == 0) + { + // Generate interclique edges + for (vertices_size_type i = 0; i < totVertices; ++i) + { + double p = probIntercliqueEdges; + for (vertices_size_type d = 2; d < totVertices / 2; + d *= 2, p /= 2) + { + vertices_size_type j = (i + d) % totVertices; + if (cliqueNum[j] != cliqueNum[i] && prob() < p) + { + int edges = num_parallel_edges(*gen); + for (int i = 0; i < edges; ++i) + values.push(std::make_pair(i, j)); + } + } + } + } + + currentClique++; + } + + if (!values.empty()) + { // If we're not done return a value + current = values.front(); + values.pop(); + } + + return *this; + } + + ssca_iterator operator++(int) + { + ssca_iterator temp(*this); + ++(*this); + return temp; + } + + bool operator==(const ssca_iterator& other) const + { + return verticesRemaining == other.verticesRemaining && values.empty() + && other.values.empty(); + } + + bool operator!=(const ssca_iterator& other) const + { + return !(*this == other); + } + +private: + // Parameters + RandomGenerator* gen; + vertices_size_type totVertices; + vertices_size_type maxCliqueSize; + double probUnidirectional; + int maxParallelEdges; + double probIntercliqueEdges; + + // Internal data structures + std::vector< int > cliqueNum; + std::queue< value_type > values; + int currentClique; + vertices_size_type verticesRemaining; + value_type current; +}; + +} // end namespace boost + +#endif // BOOST_GRAPH_SSCA_GENERATOR_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/st_connected.hpp b/contrib/restricted/boost/graph/include/boost/graph/st_connected.hpp new file mode 100644 index 0000000000..2e8f444319 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/st_connected.hpp @@ -0,0 +1,89 @@ +// Copyright (C) 2006 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_DISTRIBUTED_ST_CONNECTED_HPP +#define BOOST_GRAPH_DISTRIBUTED_ST_CONNECTED_HPP + +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/two_bit_color_map.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/pending/queue.hpp> + +namespace boost +{ +namespace graph +{ + + template < typename Graph, typename ColorMap > + bool st_connected(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, ColorMap color) + { + typedef typename property_traits< ColorMap >::value_type Color; + typedef color_traits< Color > ColorTraits; + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + // Set all vertices to white (unvisited) + BGL_FORALL_VERTICES_T(v, g, Graph) + put(color, v, ColorTraits::white()); + + // Vertices found from the source are grey + put(color, s, ColorTraits::gray()); + + // Vertices found from the target are greeen + put(color, t, ColorTraits::green()); + queue< Vertex > Q; + Q.push(s); + Q.push(t); + + while (!Q.empty()) + { + Vertex u = Q.top(); + Q.pop(); + Color u_color = get(color, u); + + BGL_FORALL_OUTEDGES_T(u, e, g, Graph) + { + Vertex v = target(e, g); + Color v_color = get(color, v); + if (v_color == ColorTraits::white()) + { + // We have not seen "v" before; mark it with the same color + // as u + Color u_color = get(color, u); + put(color, v, u_color); + + // Push it on the queue + Q.push(v); + } + else if (v_color != ColorTraits::black() && u_color != v_color) + { + // Colors have collided. We're done! + return true; + } + } + // u is done, so mark it black + put(color, u, ColorTraits::black()); + } + + return false; + } + + template < typename Graph > + inline bool st_connected(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t) + { + return st_connected(g, s, t, + make_two_bit_color_map(num_vertices(g), get(vertex_index, g))); + } + +} +} // end namespace boost::graph + +#endif // BOOST_GRAPH_DISTRIBUTED_ST_CONNECTED_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/stanford_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/stanford_graph.hpp new file mode 100644 index 0000000000..a3b949e610 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/stanford_graph.hpp @@ -0,0 +1,586 @@ +//======================================================================= +// Copyright 1997-2001 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +#ifndef BOOST_GRAPH_SGB_GRAPH_HPP +#define BOOST_GRAPH_SGB_GRAPH_HPP + +#include <boost/config.hpp> +#include <boost/operators.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> + +// Thanks to Andreas Scherer for numerous suggestions and fixes! + +// This file adapts a Stanford GraphBase (SGB) Graph pointer into a +// VertexListGraph. Note that a graph adaptor class is not needed, +// SGB's Graph* is used as is. The VertexListGraph concept is fulfilled by +// defining the appropriate non-member functions for Graph*. +// +// The PROTOTYPES change file extensions to SGB must be applied so +// that the SGB functions have real prototypes which are necessary for +// the C++ compiler. To apply the PROTOTYPES extensions, before you do +// "make tests install" for SGB do "ln -s PROTOTYPES/* ." to the SGB +// root directory (or just copy all the files from the PROTOTYPES +// directory to the SGB root directory). +// +extern "C" +{ + // We include all global definitions for the general stuff + // of The Stanford GraphBase and its various graph generator + // functions by reading all SGB headerfiles as in section 2 of + // the "test_sample" program. +#include <gb_graph.h> /* SGB data structures */ +#include <gb_io.h> /* SGB input/output routines */ +#include <gb_flip.h> /* random number generator */ +#include <gb_dijk.h> /* routines for shortest paths */ +#include <gb_basic.h> /* the basic graph operations */ +#undef empty /* avoid name clash with C++ standard library */ + inline Graph* empty(long n) /* and provide workaround */ + { + return board(n, 0L, 0L, 0L, 2L, 0L, 0L); + } +#include <gb_books.h> /* graphs based on literature */ +#include <gb_econ.h> /* graphs based on economic data */ +#include <gb_games.h> /* graphs based on football scores */ +#undef ap /* avoid name clash with BGL parameter */ + // ap ==> Vertex::u.I +#include <gb_gates.h> /* graphs based on logic circuits */ +#undef val /* avoid name clash with g++ headerfile stl_tempbuf.h */ + // val ==> Vertex::x.I +#include <gb_lisa.h> /* graphs based on Mona Lisa */ +#include <gb_miles.h> /* graphs based on mileage data */ +#include <gb_plane.h> /* planar graphs */ +#include <gb_raman.h> /* Ramanujan graphs */ +#include <gb_rand.h> /* random graphs */ +#include <gb_roget.h> /* graphs based on Roget's Thesaurus */ +#include <gb_save.h> /* we save results in ASCII format */ +#include <gb_words.h> /* five-letter-word graphs */ +#undef weight /* avoid name clash with BGL parameter */ + // weight ==> Vertex::u.I +} + +namespace boost +{ +class sgb_edge; +} + +class sgb_out_edge_iterator; +class sgb_adj_iterator; +class sgb_vertex_iterator; + +namespace boost +{ +typedef Graph* sgb_graph_ptr; +typedef const Graph* sgb_const_graph_ptr; + +struct sgb_traversal_tag : public virtual vertex_list_graph_tag, + public virtual incidence_graph_tag, + public virtual adjacency_graph_tag +{ +}; + +template <> struct graph_traits< sgb_graph_ptr > +{ + typedef Vertex* vertex_descriptor; + typedef boost::sgb_edge edge_descriptor; + typedef sgb_out_edge_iterator out_edge_iterator; + typedef void in_edge_iterator; + typedef sgb_adj_iterator adjacency_iterator; + typedef sgb_vertex_iterator vertex_iterator; + typedef void edge_iterator; + typedef long vertices_size_type; + typedef long edge_size_type; + typedef long degree_size_type; + typedef directed_tag directed_category; + typedef sgb_traversal_tag traversal_category; + typedef allow_parallel_edge_tag edge_parallel_category; + /** Return a null descriptor */ + static vertex_descriptor null_vertex() { return NULL; } +}; +template <> struct graph_traits< sgb_const_graph_ptr > +{ + typedef Vertex* vertex_descriptor; + typedef boost::sgb_edge edge_descriptor; + typedef sgb_out_edge_iterator out_edge_iterator; + typedef void in_edge_iterator; + typedef sgb_adj_iterator adjacency_iterator; + typedef sgb_vertex_iterator vertex_iterator; + typedef void edge_iterator; + typedef long vertices_size_type; + typedef long edge_size_type; + typedef long degree_size_type; + typedef directed_tag directed_category; + typedef sgb_traversal_tag traversal_category; + typedef allow_parallel_edge_tag edge_parallel_category; + /** Return a null descriptor */ + static vertex_descriptor null_vertex() { return NULL; } +}; +} + +namespace boost +{ + +struct edge_length_t +{ + typedef edge_property_tag kind; +}; + +// We could just use Arc* as the edge descriptor type, but +// we want to add the source(e,g) function which requires +// that we carry along a pointer to the source vertex. +class sgb_edge +{ + typedef sgb_edge self; + +public: + sgb_edge() : _arc(0), _src(0) {} + sgb_edge(Arc* a, Vertex* s) : _arc(a), _src(s) {} + friend Vertex* source(self e, sgb_const_graph_ptr) { return e._src; } + friend Vertex* target(self e, sgb_const_graph_ptr) { return e._arc->tip; } + friend bool operator==(const self& a, const self& b) + { + return a._arc == b._arc; + } + friend bool operator!=(const self& a, const self& b) + { + return a._arc != b._arc; + } +#if !defined(BOOST_NO_MEMBER_TEMPLATE_FRIENDS) + template < class Ref > friend class sgb_edge_length_map; + template < class Tag, class Ref > friend class sgb_edge_util_map; + friend long get(edge_length_t, const sgb_graph_ptr&, const sgb_edge& key); + friend long get( + edge_length_t, const sgb_const_graph_ptr&, const sgb_edge& key); + friend void put( + edge_length_t, sgb_graph_ptr&, const sgb_edge& key, long value); + +protected: +#endif + Arc* _arc; + Vertex* _src; +}; +} // namespace boost + +class sgb_out_edge_iterator +: public boost::forward_iterator_helper< sgb_out_edge_iterator, boost::sgb_edge, + std::ptrdiff_t, boost::sgb_edge*, boost::sgb_edge > +{ + typedef sgb_out_edge_iterator self; + +public: + sgb_out_edge_iterator() : _src(0), _arc(0) {} + sgb_out_edge_iterator(Vertex* s, Arc* d) : _src(s), _arc(d) {} + boost::sgb_edge operator*() { return boost::sgb_edge(_arc, _src); } + self& operator++() + { + _arc = _arc->next; + return *this; + } + friend bool operator==(const self& x, const self& y) + { + return x._arc == y._arc; + } + +protected: + Vertex* _src; + Arc* _arc; +}; + +class sgb_adj_iterator +: public boost::forward_iterator_helper< sgb_adj_iterator, Vertex*, + std::ptrdiff_t, Vertex**, Vertex* > +{ + typedef sgb_adj_iterator self; + +public: + sgb_adj_iterator() : _arc(0) {} + sgb_adj_iterator(Arc* d) : _arc(d) {} + Vertex* operator*() { return _arc->tip; } + self& operator++() + { + _arc = _arc->next; + return *this; + } + friend bool operator==(const self& x, const self& y) + { + return x._arc == y._arc; + } + +protected: + Arc* _arc; +}; + +// The reason we have this instead of just using Vertex* is that we +// want to use Vertex* as the vertex_descriptor instead of just +// Vertex, which avoids problems with boost passing vertex descriptors +// by value and how that interacts with the sgb_vertex_id_map. +class sgb_vertex_iterator +: public boost::forward_iterator_helper< sgb_vertex_iterator, Vertex*, + std::ptrdiff_t, Vertex**, Vertex* > +{ + typedef sgb_vertex_iterator self; + +public: + sgb_vertex_iterator() : _v(0) {} + sgb_vertex_iterator(Vertex* v) : _v(v) {} + Vertex* operator*() { return _v; } + self& operator++() + { + ++_v; + return *this; + } + friend bool operator==(const self& x, const self& y) + { + return x._v == y._v; + } + +protected: + Vertex* _v; +}; + +namespace boost +{ + +inline std::pair< sgb_vertex_iterator, sgb_vertex_iterator > vertices( + sgb_const_graph_ptr g) +{ + return std::make_pair(sgb_vertex_iterator(g->vertices), + sgb_vertex_iterator(g->vertices + g->n)); +} + +inline std::pair< sgb_out_edge_iterator, sgb_out_edge_iterator > out_edges( + Vertex* u, sgb_const_graph_ptr) +{ + return std::make_pair( + sgb_out_edge_iterator(u, u->arcs), sgb_out_edge_iterator(u, 0)); +} + +inline boost::graph_traits< sgb_graph_ptr >::degree_size_type out_degree( + Vertex* u, sgb_const_graph_ptr g) +{ + boost::graph_traits< sgb_graph_ptr >::out_edge_iterator i, i_end; + boost::tie(i, i_end) = out_edges(u, g); + return std::distance(i, i_end); +} + +// in_edges? + +inline std::pair< sgb_adj_iterator, sgb_adj_iterator > adjacent_vertices( + Vertex* u, sgb_const_graph_ptr) +{ + return std::make_pair(sgb_adj_iterator(u->arcs), sgb_adj_iterator(0)); +} + +inline long num_vertices(sgb_const_graph_ptr g) { return g->n; } +inline long num_edges(sgb_const_graph_ptr g) { return g->m; } + +inline Vertex* vertex(long v, sgb_const_graph_ptr g) { return g->vertices + v; } + +// Various Property Maps + +// Vertex ID +class sgb_vertex_id_map +: public boost::put_get_helper< long, sgb_vertex_id_map > +{ +public: + typedef boost::readable_property_map_tag category; + typedef long value_type; + typedef long reference; + typedef Vertex* key_type; + sgb_vertex_id_map() : _g(0) {} + sgb_vertex_id_map(sgb_graph_ptr g) : _g(g) {} + long operator[](Vertex* v) const { return v - _g->vertices; } + +protected: + sgb_graph_ptr _g; +}; +inline sgb_vertex_id_map get(vertex_index_t, sgb_graph_ptr g) +{ + return sgb_vertex_id_map(g); +} + +// Vertex Name +class sgb_vertex_name_map +: public boost::put_get_helper< char*, sgb_vertex_name_map > +{ +public: + typedef boost::readable_property_map_tag category; + typedef char* value_type; + typedef char* reference; + typedef Vertex* key_type; + char* operator[](Vertex* v) const { return v->name; } +}; +inline sgb_vertex_name_map get(vertex_name_t, sgb_graph_ptr) +{ + return sgb_vertex_name_map(); +} + +// Vertex Property Tags +#define SGB_PROPERTY_TAG(KIND, TAG) \ + template < class T > struct TAG##_property \ + { \ + typedef KIND##_property_tag kind; \ + typedef T type; \ + }; +SGB_PROPERTY_TAG(vertex, u) +SGB_PROPERTY_TAG(vertex, v) +SGB_PROPERTY_TAG(vertex, w) +SGB_PROPERTY_TAG(vertex, x) +SGB_PROPERTY_TAG(vertex, y) +SGB_PROPERTY_TAG(vertex, z) + +// Edge Property Tags +SGB_PROPERTY_TAG(edge, a) +SGB_PROPERTY_TAG(edge, b) + +// Various Utility Maps + +// helpers +inline Vertex*& get_util(util& u, Vertex*) { return u.V; } +inline Arc*& get_util(util& u, Arc*) { return u.A; } +inline sgb_graph_ptr& get_util(util& u, sgb_graph_ptr) { return u.G; } +inline char*& get_util(util& u, char*) { return u.S; } +inline long& get_util(util& u, long) { return u.I; } + +#define SGB_GET_UTIL_FIELD(KIND, X) \ + template < class T > inline T& get_util_field(KIND* k, X##_property< T >) \ + { \ + return get_util(k->X, T()); \ + } + +SGB_GET_UTIL_FIELD(Vertex, u) +SGB_GET_UTIL_FIELD(Vertex, v) +SGB_GET_UTIL_FIELD(Vertex, w) +SGB_GET_UTIL_FIELD(Vertex, x) +SGB_GET_UTIL_FIELD(Vertex, y) +SGB_GET_UTIL_FIELD(Vertex, z) + +SGB_GET_UTIL_FIELD(Arc, a) +SGB_GET_UTIL_FIELD(Arc, b) + +// Vertex Utility Map +template < class Tag, class Ref > +class sgb_vertex_util_map +: public boost::put_get_helper< Ref, sgb_vertex_util_map< Tag, Ref > > +{ + Tag tag; + +public: + explicit sgb_vertex_util_map(Tag tag = Tag()) : tag(tag) {} + typedef boost::lvalue_property_map_tag category; + typedef typename Tag::type value_type; + typedef Vertex* key_type; + typedef Ref reference; + reference operator[](Vertex* v) const { return get_util_field(v, tag); } +}; + +// Edge Utility Map +template < class Tag, class Ref > +class sgb_edge_util_map +: public boost::put_get_helper< Ref, sgb_edge_util_map< Tag, Ref > > +{ + Tag tag; + +public: + explicit sgb_edge_util_map(Tag tag = Tag()) : tag(tag) {} + typedef boost::lvalue_property_map_tag category; + typedef typename Tag::type value_type; + typedef Vertex* key_type; + typedef Ref reference; + reference operator[](const sgb_edge& e) const + { + return get_util_field(e._arc, tag); + } +}; + +template < class Tag > +inline sgb_vertex_util_map< Tag, const typename Tag::type& > get_property_map( + Tag, const sgb_graph_ptr& g, vertex_property_tag) +{ + return sgb_vertex_util_map< Tag, const typename Tag::type& >(); +} +template < class Tag > +inline sgb_vertex_util_map< Tag, typename Tag::type& > get_property_map( + Tag, sgb_graph_ptr& g, vertex_property_tag) +{ + return sgb_vertex_util_map< Tag, typename Tag::type& >(); +} + +template < class Tag > +inline sgb_edge_util_map< Tag, const typename Tag::type& > get_property_map( + Tag, const sgb_graph_ptr& g, edge_property_tag) +{ + return sgb_edge_util_map< Tag, const typename Tag::type& >(); +} +template < class Tag > +inline sgb_edge_util_map< Tag, typename Tag::type& > get_property_map( + Tag, sgb_graph_ptr& g, edge_property_tag) +{ + return sgb_edge_util_map< Tag, typename Tag::type& >(); +} + +// Edge Length Access +template < class Ref > +class sgb_edge_length_map +: public boost::put_get_helper< Ref, sgb_edge_length_map< Ref > > +{ +public: + typedef boost::lvalue_property_map_tag category; + typedef long value_type; + typedef sgb_edge key_type; + typedef Ref reference; + reference operator[](const sgb_edge& e) const { return e._arc->len; } +}; + +inline sgb_edge_length_map< const long& > get( + edge_length_t, const sgb_graph_ptr&) +{ + return sgb_edge_length_map< const long& >(); +} +inline sgb_edge_length_map< const long& > get( + edge_length_t, const sgb_const_graph_ptr&) +{ + return sgb_edge_length_map< const long& >(); +} +inline sgb_edge_length_map< long& > get(edge_length_t, sgb_graph_ptr&) +{ + return sgb_edge_length_map< long& >(); +} +inline long get(edge_length_t, const sgb_graph_ptr&, const sgb_edge& key) +{ + return key._arc->len; +} +inline long get(edge_length_t, const sgb_const_graph_ptr&, const sgb_edge& key) +{ + return key._arc->len; +} +inline void put(edge_length_t, sgb_graph_ptr&, const sgb_edge& key, long value) +{ + key._arc->len = value; +} + +// Property Map Traits Classes +template <> struct property_map< sgb_graph_ptr, edge_length_t > +{ + typedef sgb_edge_length_map< long& > type; + typedef sgb_edge_length_map< const long& > const_type; +}; +template <> struct property_map< sgb_graph_ptr, vertex_index_t > +{ + typedef sgb_vertex_id_map type; + typedef sgb_vertex_id_map const_type; +}; +template <> struct property_map< sgb_graph_ptr, vertex_name_t > +{ + typedef sgb_vertex_name_map type; + typedef sgb_vertex_name_map const_type; +}; + +template <> struct property_map< sgb_const_graph_ptr, edge_length_t > +{ + typedef sgb_edge_length_map< const long& > const_type; +}; +template <> struct property_map< sgb_const_graph_ptr, vertex_index_t > +{ + typedef sgb_vertex_id_map const_type; +}; +template <> struct property_map< sgb_const_graph_ptr, vertex_name_t > +{ + typedef sgb_vertex_name_map const_type; +}; + +namespace detail +{ + template < class Kind, class PropertyTag > struct sgb_choose_property_map + { + }; + template < class PropertyTag > + struct sgb_choose_property_map< vertex_property_tag, PropertyTag > + { + typedef typename PropertyTag::type value_type; + typedef sgb_vertex_util_map< PropertyTag, value_type& > type; + typedef sgb_vertex_util_map< PropertyTag, const value_type& > + const_type; + }; + template < class PropertyTag > + struct sgb_choose_property_map< edge_property_tag, PropertyTag > + { + typedef typename PropertyTag::type value_type; + typedef sgb_edge_util_map< PropertyTag, value_type& > type; + typedef sgb_edge_util_map< PropertyTag, const value_type& > const_type; + }; +} // namespace detail +template < class PropertyTag > struct property_map< sgb_graph_ptr, PropertyTag > +{ + typedef typename property_kind< PropertyTag >::type Kind; + typedef detail::sgb_choose_property_map< Kind, PropertyTag > Choice; + typedef typename Choice::type type; + typedef typename Choice::const_type const_type; +}; +template < class PropertyTag > +struct property_map< sgb_const_graph_ptr, PropertyTag > +{ + typedef typename property_kind< PropertyTag >::type Kind; + typedef detail::sgb_choose_property_map< Kind, PropertyTag > Choice; + typedef typename Choice::const_type const_type; +}; + +#define SGB_UTIL_ACCESSOR(KIND, X) \ + template < class T > \ + inline sgb_##KIND##_util_map< X##_property< T >, T& > get( \ + X##_property< T >, sgb_graph_ptr&) \ + { \ + return sgb_##KIND##_util_map< X##_property< T >, T& >(); \ + } \ + template < class T > \ + inline sgb_##KIND##_util_map< X##_property< T >, const T& > get( \ + X##_property< T >, const sgb_graph_ptr&) \ + { \ + return sgb_##KIND##_util_map< X##_property< T >, const T& >(); \ + } \ + template < class T > \ + inline sgb_##KIND##_util_map< X##_property< T >, const T& > get( \ + X##_property< T >, const sgb_const_graph_ptr&) \ + { \ + return sgb_##KIND##_util_map< X##_property< T >, const T& >(); \ + } \ + template < class T, class Key > \ + inline typename sgb_##KIND##_util_map< X##_property< T >, \ + const T& >::value_type \ + get(X##_property< T >, const sgb_graph_ptr&, const Key& key) \ + { \ + return sgb_##KIND##_util_map< X##_property< T >, const T& >()[key]; \ + } \ + template < class T, class Key > \ + inline typename sgb_##KIND##_util_map< X##_property< T >, \ + const T& >::value_type \ + get(X##_property< T >, const sgb_const_graph_ptr&, const Key& key) \ + { \ + return sgb_##KIND##_util_map< X##_property< T >, const T& >()[key]; \ + } \ + template < class T, class Key, class Value > \ + inline void put( \ + X##_property< T >, sgb_graph_ptr&, const Key& key, const Value& value) \ + { \ + sgb_##KIND##_util_map< X##_property< T >, T& >()[key] = value; \ + } + +SGB_UTIL_ACCESSOR(vertex, u) +SGB_UTIL_ACCESSOR(vertex, v) +SGB_UTIL_ACCESSOR(vertex, w) +SGB_UTIL_ACCESSOR(vertex, x) +SGB_UTIL_ACCESSOR(vertex, y) +SGB_UTIL_ACCESSOR(vertex, z) + +SGB_UTIL_ACCESSOR(edge, a) +SGB_UTIL_ACCESSOR(edge, b) + +} // namespace boost + +#endif // BOOST_GRAPH_SGB_GRAPH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/stoer_wagner_min_cut.hpp b/contrib/restricted/boost/graph/include/boost/graph/stoer_wagner_min_cut.hpp new file mode 100644 index 0000000000..33ef6e9693 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/stoer_wagner_min_cut.hpp @@ -0,0 +1,383 @@ +// Copyright Daniel Trebbien 2010. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or the copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_STOER_WAGNER_MIN_CUT_HPP +#define BOOST_GRAPH_STOER_WAGNER_MIN_CUT_HPP 1 + +#include <boost/assert.hpp> +#include <set> +#include <vector> +#include <boost/concept_check.hpp> +#include <boost/concept/assert.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/buffer_concepts.hpp> +#include <boost/graph/exception.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/maximum_adjacency_search.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/graph/one_bit_color_map.hpp> +#include <boost/graph/detail/d_ary_heap.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/utility/result_of.hpp> +#include <boost/graph/iteration_macros.hpp> + +namespace boost +{ + +namespace detail +{ + /** + * \brief Performs a phase of the Stoer-Wagner min-cut algorithm + * + * Performs a phase of the Stoer-Wagner min-cut algorithm. + * + * As described by Stoer & Wagner (1997), a phase is simply a maximum + * adjacency search (also called a maximum cardinality search), which + * results in the selection of two vertices \em s and \em t, and, as a side + * product, a minimum <em>s</em>-<em>t</em> cut of the input graph. Here, + * the input graph is basically \p g, but some vertices are virtually + * assigned to others as a way of viewing \p g as a graph with some sets of + * vertices merged together. + * + * This implementation is a translation of pseudocode by Professor Uri + * Zwick, School of Computer Science, Tel Aviv University. + * + * \pre \p g is a connected, undirected graph + * \param[in] g the input graph + * \param[in] assignments a read/write property map from each vertex to the + * vertex that it is assigned to + * \param[in] assignedVertices a list of vertices that are assigned to + * others + * \param[in] weights a readable property map from each edge to its + * weight (a non-negative value) + * \param[out] pq a keyed, updatable max-priority queue + * \returns a tuple (\em s, \em t, \em w) of the "<em>s</em>" and + * "<em>t</em>" of the minimum <em>s</em>-<em>t</em> cut and the + * cut weight \em w of the minimum <em>s</em>-<em>t</em> cut. + * \see http://www.cs.tau.ac.il/~zwick/grad-algo-08/gmc.pdf + * + * \author Daniel Trebbien + * \date 2010-09-11 + */ + template < class UndirectedGraph, class VertexAssignmentMap, + class WeightMap, class KeyedUpdatablePriorityQueue > + boost::tuple< + typename boost::graph_traits< UndirectedGraph >::vertex_descriptor, + typename boost::graph_traits< UndirectedGraph >::vertex_descriptor, + typename boost::property_traits< WeightMap >::value_type > + stoer_wagner_phase(const UndirectedGraph& g, + VertexAssignmentMap assignments, + const std::set< typename boost::graph_traits< + UndirectedGraph >::vertex_descriptor >& assignedVertices, + WeightMap weights, KeyedUpdatablePriorityQueue& pq) + { + typedef + typename boost::graph_traits< UndirectedGraph >::vertex_descriptor + vertex_descriptor; + typedef typename boost::property_traits< WeightMap >::value_type + weight_type; + + BOOST_ASSERT(pq.empty()); + typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys(); + + BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) + { + if (v == get(assignments, v)) + { // foreach u \in V do + put(keys, v, weight_type(0)); + + pq.push(v); + } + } + + BOOST_ASSERT(pq.size() >= 2); + + vertex_descriptor s + = boost::graph_traits< UndirectedGraph >::null_vertex(); + vertex_descriptor t + = boost::graph_traits< UndirectedGraph >::null_vertex(); + weight_type w; + while (!pq.empty()) + { // while PQ \neq {} do + const vertex_descriptor u = pq.top(); // u = extractmax(PQ) + w = get(keys, u); + pq.pop(); + + s = t; + t = u; + + BGL_FORALL_OUTEDGES_T(u, e, g, UndirectedGraph) + { // foreach (u, v) \in E do + const vertex_descriptor v = get(assignments, target(e, g)); + + if (pq.contains(v)) + { // if v \in PQ then + put(keys, v, + get(keys, v) + + get(weights, + e)); // increasekey(PQ, v, wA(v) + w(u, v)) + pq.update(v); + } + } + + typename std::set< vertex_descriptor >::const_iterator + assignedVertexIt, + assignedVertexEnd = assignedVertices.end(); + for (assignedVertexIt = assignedVertices.begin(); + assignedVertexIt != assignedVertexEnd; ++assignedVertexIt) + { + const vertex_descriptor uPrime = *assignedVertexIt; + + if (get(assignments, uPrime) == u) + { + BGL_FORALL_OUTEDGES_T(uPrime, e, g, UndirectedGraph) + { // foreach (u, v) \in E do + const vertex_descriptor v + = get(assignments, target(e, g)); + + if (pq.contains(v)) + { // if v \in PQ then + put(keys, v, + get(keys, v) + + get(weights, e)); // increasekey(PQ, v, + // wA(v) + w(u, v)) + pq.update(v); + } + } + } + } + } + + return boost::make_tuple(s, t, w); + } + + /** + * \brief Computes a min-cut of the input graph + * + * Computes a min-cut of the input graph using the Stoer-Wagner algorithm. + * + * \pre \p g is a connected, undirected graph + * \pre <code>pq.empty()</code> + * \param[in] g the input graph + * \param[in] weights a readable property map from each edge to its weight + * (a non-negative value) \param[out] parities a writable property map from + * each vertex to a bool type object for distinguishing the two vertex sets + * of the min-cut \param[out] assignments a read/write property map from + * each vertex to a \c vertex_descriptor object. This map serves as work + * space, and no particular meaning should be derived from property values + * after completion of the algorithm. + * \param[out] pq a keyed, updatable max-priority queue + * \returns the cut weight of the min-cut + * \see + * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.114.6687&rep=rep1&type=pdf + * \see + * http://citeseerx.ist.psu.edu/viewdoc/download?doi=10.1.1.31.614&rep=rep1&type=pdf + * + * \author Daniel Trebbien + * \date 2010-09-11 + */ + template < class UndirectedGraph, class WeightMap, class ParityMap, + class VertexAssignmentMap, class KeyedUpdatablePriorityQueue, + class IndexMap > + typename boost::property_traits< WeightMap >::value_type + stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, + ParityMap parities, VertexAssignmentMap assignments, + KeyedUpdatablePriorityQueue& pq, IndexMap index_map) + { + typedef + typename boost::graph_traits< UndirectedGraph >::vertex_descriptor + vertex_descriptor; + typedef typename boost::property_traits< WeightMap >::value_type + weight_type; + typedef + typename boost::graph_traits< UndirectedGraph >::vertices_size_type + vertices_size_type; + typedef typename boost::property_traits< ParityMap >::value_type + parity_type; + + vertices_size_type n = num_vertices(g); + + std::set< vertex_descriptor > assignedVertices; + + // initialize `assignments` (all vertices are initially assigned to + // themselves) + BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { put(assignments, v, v); } + + vertex_descriptor s, t; + weight_type bestW; + + boost::tie(s, t, bestW) = boost::detail::stoer_wagner_phase( + g, assignments, assignedVertices, weights, pq); + BOOST_ASSERT(s != t); + BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) + { + put(parities, v, parity_type(v == t ? 1 : 0)); + } + put(assignments, t, s); + assignedVertices.insert(t); + --n; + + for (; n >= 2; --n) + { + weight_type w; + boost::tie(s, t, w) = boost::detail::stoer_wagner_phase( + g, assignments, assignedVertices, weights, pq); + BOOST_ASSERT(s != t); + + if (w < bestW) + { + BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) + { + put(parities, v, + parity_type(get(assignments, v) == t ? 1 : 0)); + + if (get(assignments, v) + == t) // all vertices that were assigned to t are now + // assigned to s + put(assignments, v, s); + } + + bestW = w; + } + else + { + BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) + { + if (get(assignments, v) + == t) // all vertices that were assigned to t are now + // assigned to s + put(assignments, v, s); + } + } + put(assignments, t, s); + assignedVertices.insert(t); + } + + BOOST_ASSERT(pq.empty()); + + return bestW; + } +} // end `namespace detail` within `namespace boost` + +template < class UndirectedGraph, class WeightMap, class ParityMap, + class VertexAssignmentMap, class KeyedUpdatablePriorityQueue, + class IndexMap > +typename boost::property_traits< WeightMap >::value_type stoer_wagner_min_cut( + const UndirectedGraph& g, WeightMap weights, ParityMap parities, + VertexAssignmentMap assignments, KeyedUpdatablePriorityQueue& pq, + IndexMap index_map) +{ + BOOST_CONCEPT_ASSERT((boost::IncidenceGraphConcept< UndirectedGraph >)); + BOOST_CONCEPT_ASSERT((boost::VertexListGraphConcept< UndirectedGraph >)); + typedef typename boost::graph_traits< UndirectedGraph >::vertex_descriptor + vertex_descriptor; + typedef typename boost::graph_traits< UndirectedGraph >::vertices_size_type + vertices_size_type; + typedef typename boost::graph_traits< UndirectedGraph >::edge_descriptor + edge_descriptor; + BOOST_CONCEPT_ASSERT((boost::Convertible< + typename boost::graph_traits< UndirectedGraph >::directed_category, + boost::undirected_tag >)); + BOOST_CONCEPT_ASSERT( + (boost::ReadablePropertyMapConcept< WeightMap, edge_descriptor >)); + // typedef typename boost::property_traits<WeightMap>::value_type + // weight_type; + BOOST_CONCEPT_ASSERT( + (boost::WritablePropertyMapConcept< ParityMap, vertex_descriptor >)); + // typedef typename boost::property_traits<ParityMap>::value_type + // parity_type; + BOOST_CONCEPT_ASSERT( + (boost::ReadWritePropertyMapConcept< VertexAssignmentMap, + vertex_descriptor >)); + BOOST_CONCEPT_ASSERT((boost::Convertible< vertex_descriptor, + typename boost::property_traits< VertexAssignmentMap >::value_type >)); + BOOST_CONCEPT_ASSERT( + (boost::KeyedUpdatableQueueConcept< KeyedUpdatablePriorityQueue >)); + + vertices_size_type n = num_vertices(g); + if (n < 2) + throw boost::bad_graph( + "the input graph must have at least two vertices."); + else if (!pq.empty()) + throw std::invalid_argument( + "the max-priority queue must be empty initially."); + + return detail::stoer_wagner_min_cut( + g, weights, parities, assignments, pq, index_map); +} + +namespace graph +{ + namespace detail + { + template < class UndirectedGraph, class WeightMap > + struct stoer_wagner_min_cut_impl + { + typedef typename boost::property_traits< WeightMap >::value_type + result_type; + template < typename ArgPack > + result_type operator()(const UndirectedGraph& g, WeightMap weights, + const ArgPack& arg_pack) const + { + using namespace boost::graph::keywords; + typedef typename boost::graph_traits< + UndirectedGraph >::vertex_descriptor vertex_descriptor; + typedef typename boost::property_traits< WeightMap >::value_type + weight_type; + + typedef boost::detail::make_priority_queue_from_arg_pack_gen< + boost::graph::keywords::tag::max_priority_queue, + weight_type, vertex_descriptor, + std::greater< weight_type > > + gen_type; + + gen_type gen( + choose_param(get_param(arg_pack, boost::distance_zero_t()), + weight_type(0))); + + typename boost::result_of< gen_type( + const UndirectedGraph&, const ArgPack&) >::type pq + = gen(g, arg_pack); + + boost::dummy_property_map dummy_prop; + return boost::stoer_wagner_min_cut(g, weights, + arg_pack[_parity_map | dummy_prop], + boost::detail::make_property_map_from_arg_pack_gen< + tag::vertex_assignment_map, vertex_descriptor >( + vertex_descriptor())(g, arg_pack), + pq, + boost::detail::override_const_property( + arg_pack, _vertex_index_map, g, vertex_index)); + } + }; + } + BOOST_GRAPH_MAKE_FORWARDING_FUNCTION(stoer_wagner_min_cut, 2, 4) +} + +// Named parameter interface +BOOST_GRAPH_MAKE_OLD_STYLE_PARAMETER_FUNCTION(stoer_wagner_min_cut, 2) +namespace graph +{ + // version without IndexMap kept for backwards compatibility + // (but requires vertex_index_t to be defined in the graph) + // Place after the macro to avoid compilation errors + template < class UndirectedGraph, class WeightMap, class ParityMap, + class VertexAssignmentMap, class KeyedUpdatablePriorityQueue > + typename boost::property_traits< WeightMap >::value_type + stoer_wagner_min_cut(const UndirectedGraph& g, WeightMap weights, + ParityMap parities, VertexAssignmentMap assignments, + KeyedUpdatablePriorityQueue& pq) + { + + return stoer_wagner_min_cut( + g, weights, parities, assignments, pq, get(vertex_index, g)); + } +} // end `namespace graph` +} // end `namespace boost` + +#include <boost/graph/iteration_macros_undef.hpp> + +#endif // !BOOST_GRAPH_STOER_WAGNER_MIN_CUT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp b/contrib/restricted/boost/graph/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp new file mode 100644 index 0000000000..8e1f5ad94a --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/successive_shortest_path_nonnegative_weights.hpp @@ -0,0 +1,255 @@ +//======================================================================= +// Copyright 2013 University of Warsaw. +// Authors: Piotr Wygocki +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +// This algorithm is described in "Network Flows: Theory, Algorithms, and +// Applications" +// by Ahuja, Magnanti, Orlin. + +#ifndef BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP +#define BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP + +#include <numeric> + +#include <boost/property_map/property_map.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/pending/indirect_cmp.hpp> +#include <boost/graph/dijkstra_shortest_paths.hpp> +#include <boost/graph/properties.hpp> +#include <boost/graph/iteration_macros.hpp> +#include <boost/graph/detail/augment.hpp> + +namespace boost +{ + +namespace detail +{ + + template < class Graph, class Weight, class Distance, class Reversed > + class MapReducedWeight + : public put_get_helper< typename property_traits< Weight >::value_type, + MapReducedWeight< Graph, Weight, Distance, Reversed > > + { + typedef graph_traits< Graph > gtraits; + + public: + typedef boost::readable_property_map_tag category; + typedef typename property_traits< Weight >::value_type value_type; + typedef value_type reference; + typedef typename gtraits::edge_descriptor key_type; + MapReducedWeight(const Graph& g, Weight w, Distance d, Reversed r) + : g_(g), weight_(w), distance_(d), rev_(r) + { + } + + reference operator[](key_type v) const + { + return get(distance_, source(v, g_)) - get(distance_, target(v, g_)) + + get(weight_, v); + } + + private: + const Graph& g_; + Weight weight_; + Distance distance_; + Reversed rev_; + }; + + template < class Graph, class Weight, class Distance, class Reversed > + MapReducedWeight< Graph, Weight, Distance, Reversed > make_mapReducedWeight( + const Graph& g, Weight w, Distance d, Reversed r) + { + return MapReducedWeight< Graph, Weight, Distance, Reversed >( + g, w, d, r); + } + +} // detail + +template < class Graph, class Capacity, class ResidualCapacity, class Reversed, + class Pred, class Weight, class Distance, class Distance2, + class VertexIndex > +void successive_shortest_path_nonnegative_weights(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity, + ResidualCapacity residual_capacity, Weight weight, Reversed rev, + VertexIndex index, Pred pred, Distance distance, Distance2 distance_prev) +{ + filtered_graph< const Graph, is_residual_edge< ResidualCapacity > > gres + = detail::residual_graph(g, residual_capacity); + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor; + + BGL_FORALL_EDGES_T(e, g, Graph) + { + put(residual_capacity, e, get(capacity, e)); + } + + BGL_FORALL_VERTICES_T(v, g, Graph) { put(distance_prev, v, 0); } + + while (true) + { + BGL_FORALL_VERTICES_T(v, g, Graph) { put(pred, v, edge_descriptor()); } + dijkstra_shortest_paths(gres, s, + weight_map( + detail::make_mapReducedWeight(gres, weight, distance_prev, rev)) + .distance_map(distance) + .vertex_index_map(index) + .visitor(make_dijkstra_visitor( + record_edge_predecessors(pred, on_edge_relaxed())))); + + if (get(pred, t) == edge_descriptor()) + { + break; + } + + BGL_FORALL_VERTICES_T(v, g, Graph) + { + put(distance_prev, v, get(distance_prev, v) + get(distance, v)); + } + + detail::augment(g, s, t, pred, residual_capacity, rev); + } +} + +// in this namespace argument dispatching tak place +namespace detail +{ + + template < class Graph, class Capacity, class ResidualCapacity, + class Weight, class Reversed, class Pred, class Distance, + class Distance2, class VertexIndex > + void successive_shortest_path_nonnegative_weights_dispatch3(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity, + ResidualCapacity residual_capacity, Weight weight, Reversed rev, + VertexIndex index, Pred pred, Distance dist, Distance2 dist_pred) + { + successive_shortest_path_nonnegative_weights(g, s, t, capacity, + residual_capacity, weight, rev, index, pred, dist, dist_pred); + } + + // setting default distance map + template < class Graph, class Capacity, class ResidualCapacity, + class Weight, class Reversed, class Pred, class Distance, + class VertexIndex > + void successive_shortest_path_nonnegative_weights_dispatch3(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity, + ResidualCapacity residual_capacity, Weight weight, Reversed rev, + VertexIndex index, Pred pred, Distance dist, param_not_found) + { + typedef typename property_traits< Weight >::value_type D; + + std::vector< D > d_map(num_vertices(g)); + + successive_shortest_path_nonnegative_weights(g, s, t, capacity, + residual_capacity, weight, rev, index, pred, dist, + make_iterator_property_map(d_map.begin(), index)); + } + + template < class Graph, class P, class T, class R, class Capacity, + class ResidualCapacity, class Weight, class Reversed, class Pred, + class Distance, class VertexIndex > + void successive_shortest_path_nonnegative_weights_dispatch2(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity, + ResidualCapacity residual_capacity, Weight weight, Reversed rev, + VertexIndex index, Pred pred, Distance dist, + const bgl_named_params< P, T, R >& params) + { + successive_shortest_path_nonnegative_weights_dispatch3(g, s, t, + capacity, residual_capacity, weight, rev, index, pred, dist, + get_param(params, vertex_distance2)); + } + + // setting default distance map + template < class Graph, class P, class T, class R, class Capacity, + class ResidualCapacity, class Weight, class Reversed, class Pred, + class VertexIndex > + void successive_shortest_path_nonnegative_weights_dispatch2(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity, + ResidualCapacity residual_capacity, Weight weight, Reversed rev, + VertexIndex index, Pred pred, param_not_found, + const bgl_named_params< P, T, R >& params) + { + typedef typename property_traits< Weight >::value_type D; + + std::vector< D > d_map(num_vertices(g)); + + successive_shortest_path_nonnegative_weights_dispatch3(g, s, t, + capacity, residual_capacity, weight, rev, index, pred, + make_iterator_property_map(d_map.begin(), index), + get_param(params, vertex_distance2)); + } + + template < class Graph, class P, class T, class R, class Capacity, + class ResidualCapacity, class Weight, class Reversed, class Pred, + class VertexIndex > + void successive_shortest_path_nonnegative_weights_dispatch1(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity, + ResidualCapacity residual_capacity, Weight weight, Reversed rev, + VertexIndex index, Pred pred, const bgl_named_params< P, T, R >& params) + { + successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, + capacity, residual_capacity, weight, rev, index, pred, + get_param(params, vertex_distance), params); + } + + // setting default predecessors map + template < class Graph, class P, class T, class R, class Capacity, + class ResidualCapacity, class Weight, class Reversed, + class VertexIndex > + void successive_shortest_path_nonnegative_weights_dispatch1(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, Capacity capacity, + ResidualCapacity residual_capacity, Weight weight, Reversed rev, + VertexIndex index, param_not_found, + const bgl_named_params< P, T, R >& params) + { + typedef typename graph_traits< Graph >::edge_descriptor edge_descriptor; + std::vector< edge_descriptor > pred_vec(num_vertices(g)); + + successive_shortest_path_nonnegative_weights_dispatch2(g, s, t, + capacity, residual_capacity, weight, rev, index, + make_iterator_property_map(pred_vec.begin(), index), + get_param(params, vertex_distance), params); + } + +} // detail + +template < class Graph, class P, class T, class R > +void successive_shortest_path_nonnegative_weights(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + const bgl_named_params< P, T, R >& params) +{ + + return detail::successive_shortest_path_nonnegative_weights_dispatch1(g, s, + t, + choose_const_pmap(get_param(params, edge_capacity), g, edge_capacity), + choose_pmap(get_param(params, edge_residual_capacity), g, + edge_residual_capacity), + choose_const_pmap(get_param(params, edge_weight), g, edge_weight), + choose_const_pmap(get_param(params, edge_reverse), g, edge_reverse), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index), + get_param(params, vertex_predecessor), params); +} + +template < class Graph > +void successive_shortest_path_nonnegative_weights(Graph& g, + typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t) +{ + bgl_named_params< int, buffer_param_t > params(0); + successive_shortest_path_nonnegative_weights(g, s, t, params); +} + +} // boost +#endif /* BOOST_GRAPH_SUCCESSIVE_SHORTEST_PATH_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/graph/tiernan_all_cycles.hpp b/contrib/restricted/boost/graph/include/boost/graph/tiernan_all_cycles.hpp new file mode 100644 index 0000000000..c24c87553f --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/tiernan_all_cycles.hpp @@ -0,0 +1,372 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_CYCLE_HPP +#define BOOST_GRAPH_CYCLE_HPP + +#include <vector> + +#include <boost/config.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/properties.hpp> +#include <boost/concept/assert.hpp> + +#include <boost/concept/detail/concept_def.hpp> +namespace boost +{ +namespace concepts +{ + BOOST_concept(CycleVisitor, (Visitor)(Path)(Graph)) + { + BOOST_CONCEPT_USAGE(CycleVisitor) { vis.cycle(p, g); } + + private: + Visitor vis; + Graph g; + Path p; + }; +} /* namespace concepts */ +using concepts::CycleVisitorConcept; +} /* namespace boost */ +#include <boost/concept/detail/concept_undef.hpp> + +namespace boost +{ + +// The implementation of this algorithm is a reproduction of the Teirnan +// approach for directed graphs: bibtex follows +// +// @article{362819, +// author = {James C. Tiernan}, +// title = {An efficient search algorithm to find the elementary +// circuits of a graph}, journal = {Commun. ACM}, volume = {13}, number +// = {12}, year = {1970}, issn = {0001-0782}, pages = {722--726}, doi = +// {http://doi.acm.org/10.1145/362814.362819}, +// publisher = {ACM Press}, +// address = {New York, NY, USA}, +// } +// +// It should be pointed out that the author does not provide a complete analysis +// for either time or space. This is in part, due to the fact that it's a fairly +// input sensitive problem related to the density and construction of the graph, +// not just its size. +// +// I've also taken some liberties with the interpretation of the algorithm - +// I've basically modernized it to use real data structures (no more arrays and +// matrices). Oh... and there's explicit control structures - not just gotos. +// +// The problem is definitely NP-complete, an unbounded implementation of this +// will probably run for quite a while on a large graph. The conclusions +// of this paper also reference a Paton algorithm for undirected graphs as being +// much more efficient (apparently based on spanning trees). Although not +// implemented, it can be found here: +// +// @article{363232, +// author = {Keith Paton}, +// title = {An algorithm for finding a fundamental set of cycles of a +// graph}, journal = {Commun. ACM}, volume = {12}, number = {9}, year = +// {1969}, issn = {0001-0782}, pages = {514--518}, doi = +// {http://doi.acm.org/10.1145/363219.363232}, +// publisher = {ACM Press}, +// address = {New York, NY, USA}, +// } + +/** + * The default cycle visitor provides an empty visit function for cycle + * visitors. + */ +struct cycle_visitor +{ + template < typename Path, typename Graph > + inline void cycle(const Path& p, const Graph& g) + { + } +}; + +/** + * The min_max_cycle_visitor simultaneously records the minimum and maximum + * cycles in a graph. + */ +struct min_max_cycle_visitor +{ + min_max_cycle_visitor(std::size_t& min_, std::size_t& max_) + : minimum(min_), maximum(max_) + { + } + + template < typename Path, typename Graph > + inline void cycle(const Path& p, const Graph& g) + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + std::size_t len = p.size(); + minimum = min BOOST_PREVENT_MACRO_SUBSTITUTION(minimum, len); + maximum = max BOOST_PREVENT_MACRO_SUBSTITUTION(maximum, len); + } + std::size_t& minimum; + std::size_t& maximum; +}; + +inline min_max_cycle_visitor find_min_max_cycle( + std::size_t& min_, std::size_t& max_) +{ + return min_max_cycle_visitor(min_, max_); +} + +namespace detail +{ + template < typename Graph, typename Path > + inline bool is_vertex_in_path(const Graph&, + typename graph_traits< Graph >::vertex_descriptor v, const Path& p) + { + return (std::find(p.begin(), p.end(), v) != p.end()); + } + + template < typename Graph, typename ClosedMatrix > + inline bool is_path_closed(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor u, + typename graph_traits< Graph >::vertex_descriptor v, + const ClosedMatrix& closed) + { + // the path from u to v is closed if v can be found in the list + // of closed vertices associated with u. + typedef typename ClosedMatrix::const_reference Row; + Row r = closed[get(vertex_index, g, u)]; + if (find(r.begin(), r.end(), v) != r.end()) + { + return true; + } + return false; + } + + template < typename Graph, typename Path, typename ClosedMatrix > + inline bool can_extend_path(const Graph& g, + typename graph_traits< Graph >::edge_descriptor e, const Path& p, + const ClosedMatrix& m) + { + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((VertexIndexGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + // get the vertices in question + Vertex u = source(e, g), v = target(e, g); + + // conditions for allowing a traversal along this edge are: + // 1. the index of v must be greater than that at which the + // path is rooted (p.front()). + // 2. the vertex v cannot already be in the path + // 3. the vertex v cannot be closed to the vertex u + + bool indices + = get(vertex_index, g, p.front()) < get(vertex_index, g, v); + bool path = !is_vertex_in_path(g, v, p); + bool closed = !is_path_closed(g, u, v, m); + return indices && path && closed; + } + + template < typename Graph, typename Path > + inline bool can_wrap_path(const Graph& g, const Path& p) + { + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::out_edge_iterator OutIterator; + + // iterate over the out-edges of the back, looking for the + // front of the path. also, we can't travel along the same + // edge that we did on the way here, but we don't quite have the + // stringent requirements that we do in can_extend_path(). + Vertex u = p.back(), v = p.front(); + OutIterator i, end; + for (boost::tie(i, end) = out_edges(u, g); i != end; ++i) + { + if ((target(*i, g) == v)) + { + return true; + } + } + return false; + } + + template < typename Graph, typename Path, typename ClosedMatrix > + inline typename graph_traits< Graph >::vertex_descriptor extend_path( + const Graph& g, Path& p, ClosedMatrix& closed) + { + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::out_edge_iterator OutIterator; + + // get the current vertex + Vertex u = p.back(); + Vertex ret = graph_traits< Graph >::null_vertex(); + + // AdjacencyIterator i, end; + OutIterator i, end; + for (boost::tie(i, end) = out_edges(u, g); i != end; ++i) + { + Vertex v = target(*i, g); + + // if we can actually extend along this edge, + // then that's what we want to do + if (can_extend_path(g, *i, p, closed)) + { + p.push_back(v); // add the vertex to the path + ret = v; + break; + } + } + return ret; + } + + template < typename Graph, typename Path, typename ClosedMatrix > + inline bool exhaust_paths(const Graph& g, Path& p, ClosedMatrix& closed) + { + BOOST_CONCEPT_ASSERT((GraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + + // if there's more than one vertex in the path, this closes + // of some possible routes and returns true. otherwise, if there's + // only one vertex left, the vertex has been used up + if (p.size() > 1) + { + // get the last and second to last vertices, popping the last + // vertex off the path + Vertex last, prev; + last = p.back(); + p.pop_back(); + prev = p.back(); + + // reset the closure for the last vertex of the path and + // indicate that the last vertex in p is now closed to + // the next-to-last vertex in p + closed[get(vertex_index, g, last)].clear(); + closed[get(vertex_index, g, prev)].push_back(last); + return true; + } + else + { + return false; + } + } + + template < typename Graph, typename Visitor > + inline void all_cycles_from_vertex(const Graph& g, + typename graph_traits< Graph >::vertex_descriptor v, Visitor vis, + std::size_t minlen, std::size_t maxlen) + { + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef std::vector< Vertex > Path; + BOOST_CONCEPT_ASSERT((CycleVisitorConcept< Visitor, Path, Graph >)); + typedef std::vector< Vertex > VertexList; + typedef std::vector< VertexList > ClosedMatrix; + + Path p; + ClosedMatrix closed(num_vertices(g), VertexList()); + Vertex null = graph_traits< Graph >::null_vertex(); + + // each path investigation starts at the ith vertex + p.push_back(v); + + while (1) + { + // extend the path until we've reached the end or the + // maxlen-sized cycle + Vertex j = null; + while (((j = detail::extend_path(g, p, closed)) != null) + && (p.size() < maxlen)) + ; // empty loop + + // if we're done extending the path and there's an edge + // connecting the back to the front, then we should have + // a cycle. + if (detail::can_wrap_path(g, p) && p.size() >= minlen) + { + vis.cycle(p, g); + } + + if (!detail::exhaust_paths(g, p, closed)) + { + break; + } + } + } + + // Select the minimum allowable length of a cycle based on the directedness + // of the graph - 2 for directed, 3 for undirected. + template < typename D > struct min_cycles + { + enum + { + value = 2 + }; + }; + template <> struct min_cycles< undirected_tag > + { + enum + { + value = 3 + }; + }; +} /* namespace detail */ + +template < typename Graph, typename Visitor > +inline void tiernan_all_cycles( + const Graph& g, Visitor vis, std::size_t minlen, std::size_t maxlen) +{ + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + + VertexIterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + { + detail::all_cycles_from_vertex(g, *i, vis, minlen, maxlen); + } +} + +template < typename Graph, typename Visitor > +inline void tiernan_all_cycles(const Graph& g, Visitor vis, std::size_t maxlen) +{ + typedef typename graph_traits< Graph >::directed_category Dir; + tiernan_all_cycles(g, vis, detail::min_cycles< Dir >::value, maxlen); +} + +template < typename Graph, typename Visitor > +inline void tiernan_all_cycles(const Graph& g, Visitor vis) +{ + typedef typename graph_traits< Graph >::directed_category Dir; + tiernan_all_cycles(g, vis, detail::min_cycles< Dir >::value, + (std::numeric_limits< std::size_t >::max)()); +} + +template < typename Graph > +inline std::pair< std::size_t, std::size_t > tiernan_girth_and_circumference( + const Graph& g) +{ + std::size_t min_ = (std::numeric_limits< std::size_t >::max)(), max_ = 0; + tiernan_all_cycles(g, find_min_max_cycle(min_, max_)); + + // if this is the case, the graph is acyclic... + if (max_ == 0) + max_ = min_; + + return std::make_pair(min_, max_); +} + +template < typename Graph > inline std::size_t tiernan_girth(const Graph& g) +{ + return tiernan_girth_and_circumference(g).first; +} + +template < typename Graph > +inline std::size_t tiernan_circumference(const Graph& g) +{ + return tiernan_girth_and_circumference(g).second; +} + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/topology.hpp b/contrib/restricted/boost/graph/include/boost/graph/topology.hpp new file mode 100644 index 0000000000..73dc3d944e --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/topology.hpp @@ -0,0 +1,702 @@ +// Copyright 2009 The Trustees of Indiana University. + +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Jeremiah Willcock +// Douglas Gregor +// Andrew Lumsdaine +#ifndef BOOST_GRAPH_TOPOLOGY_HPP +#define BOOST_GRAPH_TOPOLOGY_HPP + +#include <boost/algorithm/minmax.hpp> +#include <boost/config.hpp> // For BOOST_STATIC_CONSTANT +#include <boost/config/no_tr1/cmath.hpp> +#include <boost/math/constants/constants.hpp> // For root_two +#include <boost/math/special_functions/hypot.hpp> +#include <boost/random/uniform_01.hpp> +#include <boost/random/linear_congruential.hpp> +#include <boost/shared_ptr.hpp> + +#include <cmath> + +// Classes and concepts to represent points in a space, with distance and move +// operations (used for Gurson-Atun layout), plus other things like bounding +// boxes used for other layout algorithms. + +namespace boost +{ + +/*********************************************************** + * Topologies * + ***********************************************************/ +template < std::size_t Dims > class convex_topology +{ +public: // For VisualAge C++ + struct point + { + BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims); + point() {} + double& operator[](std::size_t i) { return values[i]; } + const double& operator[](std::size_t i) const { return values[i]; } + + private: + double values[Dims]; + }; + +public: // For VisualAge C++ + struct point_difference + { + BOOST_STATIC_CONSTANT(std::size_t, dimensions = Dims); + point_difference() + { + for (std::size_t i = 0; i < Dims; ++i) + values[i] = 0.; + } + double& operator[](std::size_t i) { return values[i]; } + const double& operator[](std::size_t i) const { return values[i]; } + + friend point_difference operator+( + const point_difference& a, const point_difference& b) + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] + b[i]; + return result; + } + + friend point_difference& operator+=( + point_difference& a, const point_difference& b) + { + for (std::size_t i = 0; i < Dims; ++i) + a[i] += b[i]; + return a; + } + + friend point_difference operator-(const point_difference& a) + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = -a[i]; + return result; + } + + friend point_difference operator-( + const point_difference& a, const point_difference& b) + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] - b[i]; + return result; + } + + friend point_difference& operator-=( + point_difference& a, const point_difference& b) + { + for (std::size_t i = 0; i < Dims; ++i) + a[i] -= b[i]; + return a; + } + + friend point_difference operator*( + const point_difference& a, const point_difference& b) + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] * b[i]; + return result; + } + + friend point_difference operator*(const point_difference& a, double b) + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] * b; + return result; + } + + friend point_difference operator*(double a, const point_difference& b) + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a * b[i]; + return result; + } + + friend point_difference operator/( + const point_difference& a, const point_difference& b) + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = (b[i] == 0.) ? 0. : a[i] / b[i]; + return result; + } + + friend double dot(const point_difference& a, const point_difference& b) + { + double result = 0; + for (std::size_t i = 0; i < Dims; ++i) + result += a[i] * b[i]; + return result; + } + + private: + double values[Dims]; + }; + +public: + typedef point point_type; + typedef point_difference point_difference_type; + + double distance(point a, point b) const + { + double dist = 0.; + for (std::size_t i = 0; i < Dims; ++i) + { + double diff = b[i] - a[i]; + dist = boost::math::hypot(dist, diff); + } + // Exact properties of the distance are not important, as long as + // < on what this returns matches real distances; l_2 is used because + // Fruchterman-Reingold also uses this code and it relies on l_2. + return dist; + } + + point move_position_toward(point a, double fraction, point b) const + { + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] + (b[i] - a[i]) * fraction; + return result; + } + + point_difference difference(point a, point b) const + { + point_difference result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] - b[i]; + return result; + } + + point adjust(point a, point_difference delta) const + { + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = a[i] + delta[i]; + return result; + } + + point pointwise_min(point a, point b) const + { + BOOST_USING_STD_MIN(); + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = min BOOST_PREVENT_MACRO_SUBSTITUTION(a[i], b[i]); + return result; + } + + point pointwise_max(point a, point b) const + { + BOOST_USING_STD_MAX(); + point result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = max BOOST_PREVENT_MACRO_SUBSTITUTION(a[i], b[i]); + return result; + } + + double norm(point_difference delta) const + { + double n = 0.; + for (std::size_t i = 0; i < Dims; ++i) + n = boost::math::hypot(n, delta[i]); + return n; + } + + double volume(point_difference delta) const + { + double n = 1.; + for (std::size_t i = 0; i < Dims; ++i) + n *= delta[i]; + return n; + } +}; + +template < std::size_t Dims, typename RandomNumberGenerator = minstd_rand > +class hypercube_topology : public convex_topology< Dims > +{ + typedef uniform_01< RandomNumberGenerator, double > rand_t; + +public: + typedef typename convex_topology< Dims >::point_type point_type; + typedef typename convex_topology< Dims >::point_difference_type + point_difference_type; + + explicit hypercube_topology(double scaling = 1.0) + : gen_ptr(new RandomNumberGenerator) + , rand(new rand_t(*gen_ptr)) + , scaling(scaling) + { + } + + hypercube_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : gen_ptr(), rand(new rand_t(gen)), scaling(scaling) + { + } + + point_type random_point() const + { + point_type p; + for (std::size_t i = 0; i < Dims; ++i) + p[i] = (*rand)() * scaling; + return p; + } + + point_type bound(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + point_type p; + for (std::size_t i = 0; i < Dims; ++i) + p[i] = min BOOST_PREVENT_MACRO_SUBSTITUTION( + scaling, max BOOST_PREVENT_MACRO_SUBSTITUTION(-scaling, a[i])); + return p; + } + + double distance_from_boundary(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); +#ifndef BOOST_NO_STDC_NAMESPACE + using std::abs; +#endif + BOOST_STATIC_ASSERT(Dims >= 1); + double dist = abs(scaling - a[0]); + for (std::size_t i = 1; i < Dims; ++i) + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION( + dist, abs(scaling - a[i])); + return dist; + } + + point_type center() const + { + point_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = scaling * .5; + return result; + } + + point_type origin() const + { + point_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = 0; + return result; + } + + point_difference_type extent() const + { + point_difference_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = scaling; + return result; + } + +private: + shared_ptr< RandomNumberGenerator > gen_ptr; + shared_ptr< rand_t > rand; + double scaling; +}; + +template < typename RandomNumberGenerator = minstd_rand > +class square_topology : public hypercube_topology< 2, RandomNumberGenerator > +{ + typedef hypercube_topology< 2, RandomNumberGenerator > inherited; + +public: + explicit square_topology(double scaling = 1.0) : inherited(scaling) {} + + square_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : inherited(gen, scaling) + { + } +}; + +template < typename RandomNumberGenerator = minstd_rand > +class rectangle_topology : public convex_topology< 2 > +{ + typedef uniform_01< RandomNumberGenerator, double > rand_t; + +public: + rectangle_topology(double left, double top, double right, double bottom) + : gen_ptr(new RandomNumberGenerator) + , rand(new rand_t(*gen_ptr)) + , left(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(left, right)) + , top(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom)) + , right(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(left, right)) + , bottom(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom)) + { + } + + rectangle_topology(RandomNumberGenerator& gen, double left, double top, + double right, double bottom) + : gen_ptr() + , rand(new rand_t(gen)) + , left(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(left, right)) + , top(std::min BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom)) + , right(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(left, right)) + , bottom(std::max BOOST_PREVENT_MACRO_SUBSTITUTION(top, bottom)) + { + } + + typedef typename convex_topology< 2 >::point_type point_type; + typedef typename convex_topology< 2 >::point_difference_type + point_difference_type; + + point_type random_point() const + { + point_type p; + p[0] = (*rand)() * (right - left) + left; + p[1] = (*rand)() * (bottom - top) + top; + return p; + } + + point_type bound(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + point_type p; + p[0] = min BOOST_PREVENT_MACRO_SUBSTITUTION( + right, max BOOST_PREVENT_MACRO_SUBSTITUTION(left, a[0])); + p[1] = min BOOST_PREVENT_MACRO_SUBSTITUTION( + bottom, max BOOST_PREVENT_MACRO_SUBSTITUTION(top, a[1])); + return p; + } + + double distance_from_boundary(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); +#ifndef BOOST_NO_STDC_NAMESPACE + using std::abs; +#endif + double dist = abs(left - a[0]); + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION(dist, abs(right - a[0])); + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION(dist, abs(top - a[1])); + dist = min BOOST_PREVENT_MACRO_SUBSTITUTION(dist, abs(bottom - a[1])); + return dist; + } + + point_type center() const + { + point_type result; + result[0] = (left + right) / 2.; + result[1] = (top + bottom) / 2.; + return result; + } + + point_type origin() const + { + point_type result; + result[0] = left; + result[1] = top; + return result; + } + + point_difference_type extent() const + { + point_difference_type result; + result[0] = right - left; + result[1] = bottom - top; + return result; + } + +private: + shared_ptr< RandomNumberGenerator > gen_ptr; + shared_ptr< rand_t > rand; + double left, top, right, bottom; +}; + +template < typename RandomNumberGenerator = minstd_rand > +class cube_topology : public hypercube_topology< 3, RandomNumberGenerator > +{ + typedef hypercube_topology< 3, RandomNumberGenerator > inherited; + +public: + explicit cube_topology(double scaling = 1.0) : inherited(scaling) {} + + cube_topology(RandomNumberGenerator& gen, double scaling = 1.0) + : inherited(gen, scaling) + { + } +}; + +template < std::size_t Dims, typename RandomNumberGenerator = minstd_rand > +class ball_topology : public convex_topology< Dims > +{ + typedef uniform_01< RandomNumberGenerator, double > rand_t; + +public: + typedef typename convex_topology< Dims >::point_type point_type; + typedef typename convex_topology< Dims >::point_difference_type + point_difference_type; + + explicit ball_topology(double radius = 1.0) + : gen_ptr(new RandomNumberGenerator) + , rand(new rand_t(*gen_ptr)) + , radius(radius) + { + } + + ball_topology(RandomNumberGenerator& gen, double radius = 1.0) + : gen_ptr(), rand(new rand_t(gen)), radius(radius) + { + } + + point_type random_point() const + { + point_type p; + double dist_sum; + do + { + dist_sum = 0.0; + for (std::size_t i = 0; i < Dims; ++i) + { + double x = (*rand)() * 2 * radius - radius; + p[i] = x; + dist_sum += x * x; + } + } while (dist_sum > radius * radius); + return p; + } + + point_type bound(point_type a) const + { + BOOST_USING_STD_MIN(); + BOOST_USING_STD_MAX(); + double r = 0.; + for (std::size_t i = 0; i < Dims; ++i) + r = boost::math::hypot(r, a[i]); + if (r <= radius) + return a; + double scaling_factor = radius / r; + point_type p; + for (std::size_t i = 0; i < Dims; ++i) + p[i] = a[i] * scaling_factor; + return p; + } + + double distance_from_boundary(point_type a) const + { + double r = 0.; + for (std::size_t i = 0; i < Dims; ++i) + r = boost::math::hypot(r, a[i]); + return radius - r; + } + + point_type center() const + { + point_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = 0; + return result; + } + + point_type origin() const + { + point_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = -radius; + return result; + } + + point_difference_type extent() const + { + point_difference_type result; + for (std::size_t i = 0; i < Dims; ++i) + result[i] = 2. * radius; + return result; + } + +private: + shared_ptr< RandomNumberGenerator > gen_ptr; + shared_ptr< rand_t > rand; + double radius; +}; + +template < typename RandomNumberGenerator = minstd_rand > +class circle_topology : public ball_topology< 2, RandomNumberGenerator > +{ + typedef ball_topology< 2, RandomNumberGenerator > inherited; + +public: + explicit circle_topology(double radius = 1.0) : inherited(radius) {} + + circle_topology(RandomNumberGenerator& gen, double radius = 1.0) + : inherited(gen, radius) + { + } +}; + +template < typename RandomNumberGenerator = minstd_rand > +class sphere_topology : public ball_topology< 3, RandomNumberGenerator > +{ + typedef ball_topology< 3, RandomNumberGenerator > inherited; + +public: + explicit sphere_topology(double radius = 1.0) : inherited(radius) {} + + sphere_topology(RandomNumberGenerator& gen, double radius = 1.0) + : inherited(gen, radius) + { + } +}; + +template < typename RandomNumberGenerator = minstd_rand > class heart_topology +{ + // Heart is defined as the union of three shapes: + // Square w/ corners (+-1000, -1000), (0, 0), (0, -2000) + // Circle centered at (-500, -500) radius 500*sqrt(2) + // Circle centered at (500, -500) radius 500*sqrt(2) + // Bounding box (-1000, -2000) - (1000, 500*(sqrt(2) - 1)) + + struct point + { + point() + { + values[0] = 0.0; + values[1] = 0.0; + } + point(double x, double y) + { + values[0] = x; + values[1] = y; + } + + double& operator[](std::size_t i) { return values[i]; } + double operator[](std::size_t i) const { return values[i]; } + + private: + double values[2]; + }; + + bool in_heart(point p) const + { +#ifndef BOOST_NO_STDC_NAMESPACE + using std::abs; +#endif + + if (p[1] < abs(p[0]) - 2000) + return false; // Bottom + if (p[1] <= -1000) + return true; // Diagonal of square + if (boost::math::hypot(p[0] - -500, p[1] - -500) + <= 500. * boost::math::constants::root_two< double >()) + return true; // Left circle + if (boost::math::hypot(p[0] - 500, p[1] - -500) + <= 500. * boost::math::constants::root_two< double >()) + return true; // Right circle + return false; + } + + bool segment_within_heart(point p1, point p2) const + { + // Assumes that p1 and p2 are within the heart + if ((p1[0] < 0) == (p2[0] < 0)) + return true; // Same side of symmetry line + if (p1[0] == p2[0]) + return true; // Vertical + double slope = (p2[1] - p1[1]) / (p2[0] - p1[0]); + double intercept = p1[1] - p1[0] * slope; + if (intercept > 0) + return false; // Crosses between circles + return true; + } + + typedef uniform_01< RandomNumberGenerator, double > rand_t; + +public: + typedef point point_type; + + heart_topology() + : gen_ptr(new RandomNumberGenerator), rand(new rand_t(*gen_ptr)) + { + } + + heart_topology(RandomNumberGenerator& gen) + : gen_ptr(), rand(new rand_t(gen)) + { + } + + point random_point() const + { + point result; + do + { + result[0] = (*rand)() + * (1000 + + 1000 * boost::math::constants::root_two< double >()) + - (500 + 500 * boost::math::constants::root_two< double >()); + result[1] = (*rand)() + * (2000 + + 500 + * (boost::math::constants::root_two< double >() + - 1)) + - 2000; + } while (!in_heart(result)); + return result; + } + + // Not going to provide clipping to bounding region or distance from + // boundary + + double distance(point a, point b) const + { + if (segment_within_heart(a, b)) + { + // Straight line + return boost::math::hypot(b[0] - a[0], b[1] - a[1]); + } + else + { + // Straight line bending around (0, 0) + return boost::math::hypot(a[0], a[1]) + + boost::math::hypot(b[0], b[1]); + } + } + + point move_position_toward(point a, double fraction, point b) const + { + if (segment_within_heart(a, b)) + { + // Straight line + return point(a[0] + (b[0] - a[0]) * fraction, + a[1] + (b[1] - a[1]) * fraction); + } + else + { + double distance_to_point_a = boost::math::hypot(a[0], a[1]); + double distance_to_point_b = boost::math::hypot(b[0], b[1]); + double location_of_point = distance_to_point_a + / (distance_to_point_a + distance_to_point_b); + if (fraction < location_of_point) + return point(a[0] * (1 - fraction / location_of_point), + a[1] * (1 - fraction / location_of_point)); + else + return point(b[0] + * ((fraction - location_of_point) + / (1 - location_of_point)), + b[1] + * ((fraction - location_of_point) + / (1 - location_of_point))); + } + } + +private: + shared_ptr< RandomNumberGenerator > gen_ptr; + shared_ptr< rand_t > rand; +}; + +} // namespace boost + +#endif // BOOST_GRAPH_TOPOLOGY_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/transitive_closure.hpp b/contrib/restricted/boost/graph/include/boost/graph/transitive_closure.hpp new file mode 100644 index 0000000000..fa8a7cd9e7 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/transitive_closure.hpp @@ -0,0 +1,392 @@ +// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su> +// Copyright (C) 2001 Jeremy Siek <jsiek@cs.indiana.edu> +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// NOTE: this final is generated by libs/graph/doc/transitive_closure.w + +#ifndef BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP +#define BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP + +#include <vector> +#include <algorithm> // for std::min and std::max +#include <functional> +#include <boost/config.hpp> +#include <boost/bind/bind.hpp> +#include <boost/graph/strong_components.hpp> +#include <boost/graph/topological_sort.hpp> +#include <boost/graph/graph_concepts.hpp> +#include <boost/graph/named_function_params.hpp> +#include <boost/graph/adjacency_list.hpp> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +namespace detail +{ + inline void union_successor_sets(const std::vector< std::size_t >& s1, + const std::vector< std::size_t >& s2, std::vector< std::size_t >& s3) + { + BOOST_USING_STD_MIN(); + for (std::size_t k = 0; k < s1.size(); ++k) + s3[k] = min BOOST_PREVENT_MACRO_SUBSTITUTION(s1[k], s2[k]); + } +} // namespace detail + +namespace detail +{ + template < typename TheContainer, typename ST = std::size_t, + typename VT = typename TheContainer::value_type > + struct subscript_t + { + typedef ST argument_type; + typedef VT& result_type; + + subscript_t(TheContainer& c) : container(&c) {} + VT& operator()(const ST& i) const { return (*container)[i]; } + + protected: + TheContainer* container; + }; + template < typename TheContainer > + subscript_t< TheContainer > subscript(TheContainer& c) + { + return subscript_t< TheContainer >(c); + } +} // namespace detail + +template < typename Graph, typename GraphTC, typename G_to_TC_VertexMap, + typename VertexIndexMap > +void transitive_closure(const Graph& g, GraphTC& tc, + G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map) +{ + if (num_vertices(g) == 0) + return; + typedef typename graph_traits< Graph >::vertex_descriptor vertex; + typedef typename graph_traits< Graph >::vertex_iterator vertex_iterator; + typedef typename property_traits< VertexIndexMap >::value_type size_type; + typedef + typename graph_traits< Graph >::adjacency_iterator adjacency_iterator; + + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >)); + BOOST_CONCEPT_ASSERT((VertexMutableGraphConcept< GraphTC >)); + BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< GraphTC >)); + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< VertexIndexMap, vertex >)); + + typedef size_type cg_vertex; + std::vector< cg_vertex > component_number_vec(num_vertices(g)); + iterator_property_map< cg_vertex*, VertexIndexMap, cg_vertex, cg_vertex& > + component_number(&component_number_vec[0], index_map); + + const cg_vertex num_scc + = strong_components(g, component_number, vertex_index_map(index_map)); + + std::vector< std::vector< vertex > > components; + build_component_lists(g, num_scc, component_number, components); + + typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS > + CG_t; + CG_t CG(num_scc); + for (cg_vertex s = 0; s < components.size(); ++s) + { + std::vector< cg_vertex > adj; + for (size_type i = 0; i < components[s].size(); ++i) + { + vertex u = components[s][i]; + adjacency_iterator v, v_end; + for (boost::tie(v, v_end) = adjacent_vertices(u, g); v != v_end; + ++v) + { + cg_vertex t = component_number[*v]; + if (s != t) // Avoid loops in the condensation graph + adj.push_back(t); + } + } + std::sort(adj.begin(), adj.end()); + const typename std::vector< cg_vertex >::iterator di + = std::unique(adj.begin(), adj.end()); + + for (typename std::vector< cg_vertex >::const_iterator i = adj.begin(); + i != di; ++i) + { + add_edge(s, *i, CG); + } + } + + std::vector< cg_vertex > topo_order; + std::vector< cg_vertex > topo_number(num_vertices(CG)); + topological_sort(CG, std::back_inserter(topo_order), + vertex_index_map(identity_property_map())); + std::reverse(topo_order.begin(), topo_order.end()); + size_type n = 0; + for (typename std::vector< cg_vertex >::iterator iter = topo_order.begin(); + iter != topo_order.end(); ++iter) + topo_number[*iter] = n++; + + std::vector< std::vector< cg_vertex > > CG_vec(num_vertices(CG)); + for (size_type i = 0; i < num_vertices(CG); ++i) + { + using namespace boost::placeholders; + + typedef typename boost::graph_traits< CG_t >::adjacency_iterator + cg_adj_iter; + std::pair< cg_adj_iter, cg_adj_iter > pr = adjacent_vertices(i, CG); + CG_vec[i].assign(pr.first, pr.second); + std::sort(CG_vec[i].begin(), CG_vec[i].end(), + boost::bind(std::less< cg_vertex >(), + boost::bind(detail::subscript(topo_number), _1), + boost::bind(detail::subscript(topo_number), _2))); + } + + std::vector< std::vector< cg_vertex > > chains; + { + std::vector< cg_vertex > in_a_chain(CG_vec.size()); + for (typename std::vector< cg_vertex >::iterator i = topo_order.begin(); + i != topo_order.end(); ++i) + { + cg_vertex v = *i; + if (!in_a_chain[v]) + { + chains.resize(chains.size() + 1); + std::vector< cg_vertex >& chain = chains.back(); + for (;;) + { + chain.push_back(v); + in_a_chain[v] = true; + + typename std::vector< cg_vertex >::const_iterator next + #ifdef __cpp_lib_not_fn + = std::find_if(CG_vec[v].begin(), CG_vec[v].end(), + std::not_fn(detail::subscript(in_a_chain))); + #else + = std::find_if(CG_vec[v].begin(), CG_vec[v].end(), + std::not1(detail::subscript(in_a_chain))); + #endif + + if (next != CG_vec[v].end()) + v = *next; + else + break; // end of chain, dead-end + } + } + } + } + std::vector< size_type > chain_number(CG_vec.size()); + std::vector< size_type > pos_in_chain(CG_vec.size()); + for (size_type i = 0; i < chains.size(); ++i) + for (size_type j = 0; j < chains[i].size(); ++j) + { + cg_vertex v = chains[i][j]; + chain_number[v] = i; + pos_in_chain[v] = j; + } + + cg_vertex inf = (std::numeric_limits< cg_vertex >::max)(); + std::vector< std::vector< cg_vertex > > successors( + CG_vec.size(), std::vector< cg_vertex >(chains.size(), inf)); + for (typename std::vector< cg_vertex >::reverse_iterator i + = topo_order.rbegin(); + i != topo_order.rend(); ++i) + { + cg_vertex u = *i; + typename std::vector< cg_vertex >::const_iterator adj, adj_last; + for (adj = CG_vec[u].begin(), adj_last = CG_vec[u].end(); + adj != adj_last; ++adj) + { + cg_vertex v = *adj; + if (topo_number[v] < successors[u][chain_number[v]]) + { + // Succ(u) = Succ(u) U Succ(v) + detail::union_successor_sets( + successors[u], successors[v], successors[u]); + // Succ(u) = Succ(u) U {v} + successors[u][chain_number[v]] = topo_number[v]; + } + } + } + + for (size_type i = 0; i < CG_vec.size(); ++i) + CG_vec[i].clear(); + for (size_type i = 0; i < CG_vec.size(); ++i) + for (size_type j = 0; j < chains.size(); ++j) + { + size_type topo_num = successors[i][j]; + if (topo_num < inf) + { + cg_vertex v = topo_order[topo_num]; + for (size_type k = pos_in_chain[v]; k < chains[j].size(); ++k) + CG_vec[i].push_back(chains[j][k]); + } + } + + // Add vertices to the transitive closure graph + { + vertex_iterator i, i_end; + for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i) + g_to_tc_map[*i] = add_vertex(tc); + } + // Add edges between all the vertices in two adjacent SCCs + typename std::vector< std::vector< cg_vertex > >::const_iterator si, si_end; + for (si = CG_vec.begin(), si_end = CG_vec.end(); si != si_end; ++si) + { + cg_vertex s = si - CG_vec.begin(); + typename std::vector< cg_vertex >::const_iterator i, i_end; + for (i = CG_vec[s].begin(), i_end = CG_vec[s].end(); i != i_end; ++i) + { + cg_vertex t = *i; + for (size_type k = 0; k < components[s].size(); ++k) + for (size_type l = 0; l < components[t].size(); ++l) + add_edge(g_to_tc_map[components[s][k]], + g_to_tc_map[components[t][l]], tc); + } + } + // Add edges connecting all vertices in a SCC + for (size_type i = 0; i < components.size(); ++i) + if (components[i].size() > 1) + for (size_type k = 0; k < components[i].size(); ++k) + for (size_type l = 0; l < components[i].size(); ++l) + { + vertex u = components[i][k], v = components[i][l]; + add_edge(g_to_tc_map[u], g_to_tc_map[v], tc); + } + + // Find loopbacks in the original graph. + // Need to add it to transitive closure. + { + vertex_iterator i, i_end; + for (boost::tie(i, i_end) = vertices(g); i != i_end; ++i) + { + adjacency_iterator ab, ae; + for (boost::tie(ab, ae) = adjacent_vertices(*i, g); ab != ae; ++ab) + { + if (*ab == *i) + if (components[component_number[*i]].size() == 1) + add_edge(g_to_tc_map[*i], g_to_tc_map[*i], tc); + } + } + } +} + +template < typename Graph, typename GraphTC > +void transitive_closure(const Graph& g, GraphTC& tc) +{ + if (num_vertices(g) == 0) + return; + typedef typename property_map< Graph, vertex_index_t >::const_type + VertexIndexMap; + VertexIndexMap index_map = get(vertex_index, g); + + typedef typename graph_traits< GraphTC >::vertex_descriptor tc_vertex; + std::vector< tc_vertex > to_tc_vec(num_vertices(g)); + iterator_property_map< tc_vertex*, VertexIndexMap, tc_vertex, tc_vertex& > + g_to_tc_map(&to_tc_vec[0], index_map); + + transitive_closure(g, tc, g_to_tc_map, index_map); +} + +namespace detail +{ + template < typename Graph, typename GraphTC, typename G_to_TC_VertexMap, + typename VertexIndexMap > + void transitive_closure_dispatch(const Graph& g, GraphTC& tc, + G_to_TC_VertexMap g_to_tc_map, VertexIndexMap index_map) + { + typedef typename graph_traits< GraphTC >::vertex_descriptor tc_vertex; + typename std::vector< tc_vertex >::size_type n + = is_default_param(g_to_tc_map) ? num_vertices(g) : 1; + std::vector< tc_vertex > to_tc_vec(n); + + transitive_closure(g, tc, + choose_param(g_to_tc_map, + make_iterator_property_map( + to_tc_vec.begin(), index_map, to_tc_vec[0])), + index_map); + } +} // namespace detail + +template < typename Graph, typename GraphTC, typename P, typename T, + typename R > +void transitive_closure( + const Graph& g, GraphTC& tc, const bgl_named_params< P, T, R >& params) +{ + if (num_vertices(g) == 0) + return; + detail::transitive_closure_dispatch(g, tc, + get_param(params, orig_to_copy_t()), + choose_const_pmap(get_param(params, vertex_index), g, vertex_index)); +} + +template < typename G > void warshall_transitive_closure(G& g) +{ + typedef typename graph_traits< G >::vertex_iterator vertex_iterator; + + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< G >)); + BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< G >)); + + // Matrix form: + // for k + // for i + // if A[i,k] + // for j + // A[i,j] = A[i,j] | A[k,j] + vertex_iterator ki, ke, ii, ie, ji, je; + for (boost::tie(ki, ke) = vertices(g); ki != ke; ++ki) + for (boost::tie(ii, ie) = vertices(g); ii != ie; ++ii) + if (edge(*ii, *ki, g).second) + for (boost::tie(ji, je) = vertices(g); ji != je; ++ji) + if (!edge(*ii, *ji, g).second && edge(*ki, *ji, g).second) + { + add_edge(*ii, *ji, g); + } +} + +template < typename G > void warren_transitive_closure(G& g) +{ + using namespace boost; + typedef typename graph_traits< G >::vertex_iterator vertex_iterator; + + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< G >)); + BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< G >)); + + // Make sure second loop will work + if (num_vertices(g) == 0) + return; + + // for i = 2 to n + // for k = 1 to i - 1 + // if A[i,k] + // for j = 1 to n + // A[i,j] = A[i,j] | A[k,j] + + vertex_iterator ic, ie, jc, je, kc, ke; + for (boost::tie(ic, ie) = vertices(g), ++ic; ic != ie; ++ic) + for (boost::tie(kc, ke) = vertices(g); *kc != *ic; ++kc) + if (edge(*ic, *kc, g).second) + for (boost::tie(jc, je) = vertices(g); jc != je; ++jc) + if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) + { + add_edge(*ic, *jc, g); + } + // for i = 1 to n - 1 + // for k = i + 1 to n + // if A[i,k] + // for j = 1 to n + // A[i,j] = A[i,j] | A[k,j] + + for (boost::tie(ic, ie) = vertices(g), --ie; ic != ie; ++ic) + for (kc = ic, ke = ie, ++kc; kc != ke; ++kc) + if (edge(*ic, *kc, g).second) + for (boost::tie(jc, je) = vertices(g); jc != je; ++jc) + if (!edge(*ic, *jc, g).second && edge(*kc, *jc, g).second) + { + add_edge(*ic, *jc, g); + } +} + +} // namespace boost + +#endif // BOOST_GRAPH_TRANSITIVE_CLOSURE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/transitive_reduction.hpp b/contrib/restricted/boost/graph/include/boost/graph/transitive_reduction.hpp new file mode 100644 index 0000000000..32cb384aaa --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/transitive_reduction.hpp @@ -0,0 +1,137 @@ +// (C) Copyright 2009 Eric Bose-Wolf +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_TRANSITIVE_REDUCTION_HPP +#define BOOST_GRAPH_TRANSITIVE_REDUCTION_HPP + +#include <vector> +#include <algorithm> //std::find +#include <boost/concept/requires.hpp> +#include <boost/concept_check.hpp> + +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/topological_sort.hpp> + +// also I didn't got all of the concepts thin. Am I suppose to check +// for all concepts, which are needed for functions I call? (As if I +// wouldn't do that, the users would see the functions called by +// complaining about missings concepts, which would be clearly an error +// message revealing internal implementation and should therefore be avoided?) + +// the pseudocode which I followed implementing this algorithmn was taken +// from the german book Algorithmische Graphentheorie by Volker Turau +// it is proposed to be of O(n + nm_red ) where n is the number +// of vertices and m_red is the number of edges in the transitive +// reduction, but I think my implementation spoiled this up at some point +// indicated below. + +namespace boost +{ + +template < typename Graph, typename GraphTR, typename G_to_TR_VertexMap, + typename VertexIndexMap > +BOOST_CONCEPT_REQUIRES( + ((VertexListGraphConcept< Graph >))((IncidenceGraphConcept< Graph >))( + (MutableGraphConcept< GraphTR >))( + (ReadablePropertyMapConcept< VertexIndexMap, + typename graph_traits< Graph >::vertex_descriptor >))( + (Integer< typename property_traits< VertexIndexMap >::value_type >))( + (LvaluePropertyMapConcept< G_to_TR_VertexMap, + typename graph_traits< Graph >::vertex_descriptor >)), + (void)) +transitive_reduction(const Graph& g, GraphTR& tr, G_to_TR_VertexMap g_to_tr_map, + VertexIndexMap g_index_map) +{ + typedef typename graph_traits< Graph >::vertex_descriptor Vertex; + typedef typename graph_traits< Graph >::vertex_iterator VertexIterator; + typedef typename std::vector< Vertex >::size_type size_type; + + std::vector< Vertex > topo_order; + topological_sort(g, std::back_inserter(topo_order)); + + std::vector< size_type > topo_number_storage(num_vertices(g)); + + iterator_property_map< size_type*, VertexIndexMap, size_type, size_type& > + topo_number(&topo_number_storage[0], g_index_map); + + { + typename std::vector< Vertex >::reverse_iterator it + = topo_order.rbegin(); + size_type n = 0; + for (; it != topo_order.rend(); ++it, ++n) + { + topo_number[*it] = n; + } + } + + std::vector< std::vector< bool > > edge_in_closure( + num_vertices(g), std::vector< bool >(num_vertices(g), false)); + { + typename std::vector< Vertex >::reverse_iterator it + = topo_order.rbegin(); + for (; it != topo_order.rend(); ++it) + { + g_to_tr_map[*it] = add_vertex(tr); + } + } + + typename std::vector< Vertex >::iterator it = topo_order.begin(), + end = topo_order.end(); + for (; it != end; ++it) + { + size_type i = topo_number[*it]; + edge_in_closure[i][i] = true; + std::vector< Vertex > neighbors; + + // I have to collect the successors of *it and traverse them in + // ascending topological order. I didn't know a better way, how to + // do that. So what I'm doint is, collection the successors of *it here + { + typename Graph::out_edge_iterator oi, oi_end; + for (boost::tie(oi, oi_end) = out_edges(*it, g); oi != oi_end; ++oi) + { + neighbors.push_back(target(*oi, g)); + } + } + + { + // and run through all vertices in topological order + typename std::vector< Vertex >::reverse_iterator rit + = topo_order.rbegin(), + rend = topo_order.rend(); + for (; rit != rend; ++rit) + { + // looking if they are successors of *it + if (std::find(neighbors.begin(), neighbors.end(), *rit) + != neighbors.end()) + { + size_type j = topo_number[*rit]; + if (not edge_in_closure[i][j]) + { + for (size_type k = j; k < num_vertices(g); ++k) + { + if (not edge_in_closure[i][k]) + { + // here we need edge_in_closure to be in + // topological order, + edge_in_closure[i][k] = edge_in_closure[j][k]; + } + } + // therefore we only access edge_in_closure only through + // topo_number property_map + add_edge(g_to_tr_map[*it], g_to_tr_map[*rit], tr); + } // if ( not edge_in_ + } // if (find ( + } // for( typename vector<Vertex>::reverse_iterator + } // { + + } // for( typename vector<Vertex>::iterator + +} // void transitive_reduction + +} // namespace boost + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/tree_traits.hpp b/contrib/restricted/boost/graph/include/boost/graph/tree_traits.hpp new file mode 100644 index 0000000000..e27396ebfd --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/tree_traits.hpp @@ -0,0 +1,48 @@ +// (C) Copyright Jeremy Siek 1999. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_TREE_STRUCTURE_HPP +#define BOOST_TREE_STRUCTURE_HPP + +#include <boost/tuple/tuple.hpp> //For boost::tie() + +namespace boost +{ + +template < class T > struct tree_traits +{ + typedef typename T::node_descriptor node_descriptor; + typedef typename T::children_iterator children_iterator; +}; + +template < class Tree, class TreeVisitor > +void traverse_tree(typename tree_traits< Tree >::node_descriptor v, Tree& t, + TreeVisitor visitor) +{ + visitor.preorder(v, t); + typename tree_traits< Tree >::children_iterator i, end; + boost::tie(i, end) = children(v, t); + if (i != end) + { + traverse_tree(*i++, t, visitor); + visitor.inorder(v, t); + while (i != end) + traverse_tree(*i++, t, visitor); + } + else + visitor.inorder(v, t); + visitor.postorder(v, t); +} + +struct null_tree_visitor +{ + template < typename Node, typename Tree > void preorder(Node, Tree&) {} + template < typename Node, typename Tree > void inorder(Node, Tree&) {} + template < typename Node, typename Tree > void postorder(Node, Tree&) {} +}; + +} /* namespace boost */ + +#endif /* BOOST_TREE_STRUCTURE_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/graph/two_graphs_common_spanning_trees.hpp b/contrib/restricted/boost/graph/include/boost/graph/two_graphs_common_spanning_trees.hpp new file mode 100644 index 0000000000..a41dc84b21 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/two_graphs_common_spanning_trees.hpp @@ -0,0 +1,852 @@ +// Copyright (C) 2012, Michele Caini. +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Two Graphs Common Spanning Trees Algorithm +// Based on academic article of Mint, Read and Tarjan +// Efficient Algorithm for Common Spanning Tree Problem +// Electron. Lett., 28 April 1983, Volume 19, Issue 9, p.346-347 + +#ifndef BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP +#define BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP + +#include <boost/config.hpp> + +#include <boost/bimap.hpp> +#include <boost/type_traits.hpp> +#include <boost/concept/requires.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/undirected_dfs.hpp> +#include <boost/graph/connected_components.hpp> +#include <boost/graph/filtered_graph.hpp> +#include <vector> +#include <stack> +#include <map> + +namespace boost +{ + +namespace detail +{ + + template < typename TreeMap, typename PredMap, typename DistMap, + typename LowMap, typename Buffer > + struct bridges_visitor : public default_dfs_visitor + { + bridges_visitor(TreeMap tree, PredMap pred, DistMap dist, LowMap low, + Buffer& buffer) + : mTree(tree), mPred(pred), mDist(dist), mLow(low), mBuffer(buffer) + { + mNum = -1; + } + + template < typename Vertex, typename Graph > + void initialize_vertex(const Vertex& u, const Graph& g) + { + put(mPred, u, u); + put(mDist, u, -1); + } + + template < typename Vertex, typename Graph > + void discover_vertex(const Vertex& u, const Graph& g) + { + put(mDist, u, ++mNum); + put(mLow, u, get(mDist, u)); + } + + template < typename Edge, typename Graph > + void tree_edge(const Edge& e, const Graph& g) + { + put(mPred, target(e, g), source(e, g)); + put(mTree, target(e, g), e); + } + + template < typename Edge, typename Graph > + void back_edge(const Edge& e, const Graph& g) + { + put(mLow, source(e, g), + (std::min)(get(mLow, source(e, g)), get(mDist, target(e, g)))); + } + + template < typename Vertex, typename Graph > + void finish_vertex(const Vertex& u, const Graph& g) + { + Vertex parent = get(mPred, u); + if (get(mLow, u) > get(mDist, parent)) + mBuffer.push(get(mTree, u)); + put(mLow, parent, (std::min)(get(mLow, parent), get(mLow, u))); + } + + TreeMap mTree; + PredMap mPred; + DistMap mDist; + LowMap mLow; + Buffer& mBuffer; + int mNum; + }; + + template < typename Buffer > + struct cycle_finder : public base_visitor< cycle_finder< Buffer > > + { + typedef on_back_edge event_filter; + cycle_finder() : mBuffer(0) {} + cycle_finder(Buffer* buffer) : mBuffer(buffer) {} + template < typename Edge, typename Graph > + void operator()(const Edge& e, const Graph& g) + { + if (mBuffer) + mBuffer->push(e); + } + Buffer* mBuffer; + }; + + template < typename DeletedMap > struct deleted_edge_status + { + deleted_edge_status() {} + deleted_edge_status(DeletedMap map) : mMap(map) {} + template < typename Edge > bool operator()(const Edge& e) const + { + return (!get(mMap, e)); + } + DeletedMap mMap; + }; + + template < typename InLMap > struct inL_edge_status + { + inL_edge_status() {} + inL_edge_status(InLMap map) : mMap(map) {} + template < typename Edge > bool operator()(const Edge& e) const + { + return get(mMap, e); + } + InLMap mMap; + }; + + template < typename Graph, typename Func, typename Seq, typename Map > + void rec_two_graphs_common_spanning_trees(const Graph& iG, + bimap< bimaps::set_of< int >, + bimaps::set_of< typename graph_traits< Graph >::edge_descriptor > > + iG_bimap, + Map aiG_inL, Map diG, const Graph& vG, + bimap< bimaps::set_of< int >, + bimaps::set_of< typename graph_traits< Graph >::edge_descriptor > > + vG_bimap, + Map avG_inL, Map dvG, Func func, Seq inL) + { + typedef graph_traits< Graph > GraphTraits; + + typedef typename GraphTraits::vertex_descriptor vertex_descriptor; + typedef typename GraphTraits::edge_descriptor edge_descriptor; + + typedef typename Seq::size_type seq_size_type; + + int edges = num_vertices(iG) - 1; + // + // [ Michele Caini ] + // + // Using the condition (edges != 0) leads to the accidental submission + // of + // sub-graphs ((V-1+1)-fake-tree, named here fat-tree). + // Remove this condition is a workaround for the problem of fat-trees. + // Please do not add that condition, even if it improves performance. + // + // Here is proposed the previous guard (that was wrong): + // for(seq_size_type i = 0; (i < inL.size()) && (edges != 0); ++i) + // + { + for (seq_size_type i = 0; i < inL.size(); ++i) + if (inL[i]) + --edges; + + if (edges < 0) + return; + } + + bool is_tree = (edges == 0); + if (is_tree) + { + func(inL); + } + else + { + std::map< vertex_descriptor, default_color_type > vertex_color; + std::map< edge_descriptor, default_color_type > edge_color; + + std::stack< edge_descriptor > iG_buf, vG_buf; + bool found = false; + + seq_size_type m; + for (seq_size_type j = 0; j < inL.size() && !found; ++j) + { + if (!inL[j] && !get(diG, iG_bimap.left.at(j)) + && !get(dvG, vG_bimap.left.at(j))) + { + put(aiG_inL, iG_bimap.left.at(j), true); + put(avG_inL, vG_bimap.left.at(j), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(aiG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&iG_buf)), + associative_property_map< + std::map< vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >( + edge_color)); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(avG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&vG_buf)), + associative_property_map< + std::map< vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >( + edge_color)); + + if (iG_buf.empty() && vG_buf.empty()) + { + inL[j] = true; + found = true; + m = j; + } + else + { + while (!iG_buf.empty()) + iG_buf.pop(); + while (!vG_buf.empty()) + vG_buf.pop(); + put(aiG_inL, iG_bimap.left.at(j), false); + put(avG_inL, vG_bimap.left.at(j), false); + } + } + } + + if (found) + { + + std::stack< edge_descriptor > iG_buf_copy, vG_buf_copy; + for (seq_size_type j = 0; j < inL.size(); ++j) + { + if (!inL[j] && !get(diG, iG_bimap.left.at(j)) + && !get(dvG, vG_bimap.left.at(j))) + { + + put(aiG_inL, iG_bimap.left.at(j), true); + put(avG_inL, vG_bimap.left.at(j), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< + associative_property_map< + std::map< edge_descriptor, bool > > >( + aiG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&iG_buf)), + associative_property_map< std::map< + vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< std::map< edge_descriptor, + default_color_type > >(edge_color)); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< + associative_property_map< + std::map< edge_descriptor, bool > > >( + avG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&vG_buf)), + associative_property_map< std::map< + vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< std::map< edge_descriptor, + default_color_type > >(edge_color)); + + if (!iG_buf.empty() || !vG_buf.empty()) + { + while (!iG_buf.empty()) + iG_buf.pop(); + while (!vG_buf.empty()) + vG_buf.pop(); + put(diG, iG_bimap.left.at(j), true); + put(dvG, vG_bimap.left.at(j), true); + iG_buf_copy.push(iG_bimap.left.at(j)); + vG_buf_copy.push(vG_bimap.left.at(j)); + } + + put(aiG_inL, iG_bimap.left.at(j), false); + put(avG_inL, vG_bimap.left.at(j), false); + } + } + + // REC + detail::rec_two_graphs_common_spanning_trees< Graph, Func, Seq, + Map >(iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, + dvG, func, inL); + + while (!iG_buf_copy.empty()) + { + put(diG, iG_buf_copy.top(), false); + put(dvG, + vG_bimap.left.at(iG_bimap.right.at(iG_buf_copy.top())), + false); + iG_buf_copy.pop(); + } + while (!vG_buf_copy.empty()) + { + put(dvG, vG_buf_copy.top(), false); + put(diG, + iG_bimap.left.at(vG_bimap.right.at(vG_buf_copy.top())), + false); + vG_buf_copy.pop(); + } + + inL[m] = false; + put(aiG_inL, iG_bimap.left.at(m), false); + put(avG_inL, vG_bimap.left.at(m), false); + + put(diG, iG_bimap.left.at(m), true); + put(dvG, vG_bimap.left.at(m), true); + + std::map< vertex_descriptor, edge_descriptor > tree_map; + std::map< vertex_descriptor, vertex_descriptor > pred_map; + std::map< vertex_descriptor, int > dist_map, low_map; + + detail::bridges_visitor< + associative_property_map< + std::map< vertex_descriptor, edge_descriptor > >, + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor > >, + associative_property_map< + std::map< vertex_descriptor, int > >, + associative_property_map< + std::map< vertex_descriptor, int > >, + std::stack< edge_descriptor > > + iG_vis(associative_property_map< + std::map< vertex_descriptor, edge_descriptor > >( + tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor > >( + pred_map), + associative_property_map< + std::map< vertex_descriptor, int > >(dist_map), + associative_property_map< + std::map< vertex_descriptor, int > >(low_map), + iG_buf), + vG_vis(associative_property_map< + std::map< vertex_descriptor, edge_descriptor > >( + tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor > >( + pred_map), + associative_property_map< + std::map< vertex_descriptor, int > >(dist_map), + associative_property_map< + std::map< vertex_descriptor, int > >(low_map), + vG_buf); + + undirected_dfs( + make_filtered_graph(iG, + detail::deleted_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(diG)), + iG_vis, + associative_property_map< + std::map< vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >( + edge_color)); + undirected_dfs( + make_filtered_graph(vG, + detail::deleted_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(dvG)), + vG_vis, + associative_property_map< + std::map< vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >( + edge_color)); + + found = false; + std::stack< edge_descriptor > iG_buf_tmp, vG_buf_tmp; + while (!iG_buf.empty() && !found) + { + if (!inL[iG_bimap.right.at(iG_buf.top())]) + { + put(aiG_inL, iG_buf.top(), true); + put(avG_inL, + vG_bimap.left.at(iG_bimap.right.at(iG_buf.top())), + true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< + associative_property_map< + std::map< edge_descriptor, bool > > >( + aiG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&iG_buf_tmp)), + associative_property_map< std::map< + vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< std::map< edge_descriptor, + default_color_type > >(edge_color)); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< + associative_property_map< + std::map< edge_descriptor, bool > > >( + avG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&vG_buf_tmp)), + associative_property_map< std::map< + vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< std::map< edge_descriptor, + default_color_type > >(edge_color)); + + if (!iG_buf_tmp.empty() || !vG_buf_tmp.empty()) + { + found = true; + } + else + { + while (!iG_buf_tmp.empty()) + iG_buf_tmp.pop(); + while (!vG_buf_tmp.empty()) + vG_buf_tmp.pop(); + iG_buf_copy.push(iG_buf.top()); + } + + put(aiG_inL, iG_buf.top(), false); + put(avG_inL, + vG_bimap.left.at(iG_bimap.right.at(iG_buf.top())), + false); + } + iG_buf.pop(); + } + while (!vG_buf.empty() && !found) + { + if (!inL[vG_bimap.right.at(vG_buf.top())]) + { + put(avG_inL, vG_buf.top(), true); + put(aiG_inL, + iG_bimap.left.at(vG_bimap.right.at(vG_buf.top())), + true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< + associative_property_map< + std::map< edge_descriptor, bool > > >( + aiG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&iG_buf_tmp)), + associative_property_map< std::map< + vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< std::map< edge_descriptor, + default_color_type > >(edge_color)); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< + associative_property_map< + std::map< edge_descriptor, bool > > >( + avG_inL)), + make_dfs_visitor(detail::cycle_finder< + std::stack< edge_descriptor > >(&vG_buf_tmp)), + associative_property_map< std::map< + vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< std::map< edge_descriptor, + default_color_type > >(edge_color)); + + if (!iG_buf_tmp.empty() || !vG_buf_tmp.empty()) + { + found = true; + } + else + { + while (!iG_buf_tmp.empty()) + iG_buf_tmp.pop(); + while (!vG_buf_tmp.empty()) + vG_buf_tmp.pop(); + vG_buf_copy.push(vG_buf.top()); + } + + put(avG_inL, vG_buf.top(), false); + put(aiG_inL, + iG_bimap.left.at(vG_bimap.right.at(vG_buf.top())), + false); + } + vG_buf.pop(); + } + + if (!found) + { + + while (!iG_buf_copy.empty()) + { + inL[iG_bimap.right.at(iG_buf_copy.top())] = true; + put(aiG_inL, iG_buf_copy.top(), true); + put(avG_inL, + vG_bimap.left.at( + iG_bimap.right.at(iG_buf_copy.top())), + true); + iG_buf.push(iG_buf_copy.top()); + iG_buf_copy.pop(); + } + while (!vG_buf_copy.empty()) + { + inL[vG_bimap.right.at(vG_buf_copy.top())] = true; + put(avG_inL, vG_buf_copy.top(), true); + put(aiG_inL, + iG_bimap.left.at( + vG_bimap.right.at(vG_buf_copy.top())), + true); + vG_buf.push(vG_buf_copy.top()); + vG_buf_copy.pop(); + } + + // REC + detail::rec_two_graphs_common_spanning_trees< Graph, Func, + Seq, Map >(iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, + aiG_inL, dvG, func, inL); + + while (!iG_buf.empty()) + { + inL[iG_bimap.right.at(iG_buf.top())] = false; + put(aiG_inL, iG_buf.top(), false); + put(avG_inL, + vG_bimap.left.at(iG_bimap.right.at(iG_buf.top())), + false); + iG_buf.pop(); + } + while (!vG_buf.empty()) + { + inL[vG_bimap.right.at(vG_buf.top())] = false; + put(avG_inL, vG_buf.top(), false); + put(aiG_inL, + iG_bimap.left.at(vG_bimap.right.at(vG_buf.top())), + false); + vG_buf.pop(); + } + } + + put(diG, iG_bimap.left.at(m), false); + put(dvG, vG_bimap.left.at(m), false); + } + } + } + +} // namespace detail + +template < typename Coll, typename Seq > struct tree_collector +{ + +public: + BOOST_CONCEPT_ASSERT((BackInsertionSequence< Coll >)); + BOOST_CONCEPT_ASSERT((RandomAccessContainer< Seq >)); + BOOST_CONCEPT_ASSERT((CopyConstructible< Seq >)); + + typedef typename Coll::value_type coll_value_type; + typedef typename Seq::value_type seq_value_type; + + BOOST_STATIC_ASSERT((is_same< coll_value_type, Seq >::value)); + BOOST_STATIC_ASSERT((is_same< seq_value_type, bool >::value)); + + tree_collector(Coll& seqs) : mSeqs(seqs) {} + + inline void operator()(Seq seq) { mSeqs.push_back(seq); } + +private: + Coll& mSeqs; +}; + +template < typename Graph, typename Order, typename Func, typename Seq > +BOOST_CONCEPT_REQUIRES( + ((RandomAccessContainer< Order >))((IncidenceGraphConcept< Graph >))( + (UnaryFunction< Func, void, Seq >))( + (Mutable_RandomAccessContainer< Seq >))( + (VertexAndEdgeListGraphConcept< Graph >)), + (void)) +two_graphs_common_spanning_trees(const Graph& iG, Order iG_map, const Graph& vG, + Order vG_map, Func func, Seq inL) +{ + typedef graph_traits< Graph > GraphTraits; + + typedef typename GraphTraits::directed_category directed_category; + typedef typename GraphTraits::vertex_descriptor vertex_descriptor; + typedef typename GraphTraits::edge_descriptor edge_descriptor; + + typedef typename GraphTraits::edges_size_type edges_size_type; + typedef typename GraphTraits::edge_iterator edge_iterator; + + typedef typename Seq::value_type seq_value_type; + typedef typename Seq::size_type seq_size_type; + + typedef typename Order::value_type order_value_type; + typedef typename Order::size_type order_size_type; + + BOOST_STATIC_ASSERT((is_same< order_value_type, edge_descriptor >::value)); + BOOST_CONCEPT_ASSERT((Convertible< order_size_type, edges_size_type >)); + + BOOST_CONCEPT_ASSERT((Convertible< seq_size_type, edges_size_type >)); + BOOST_STATIC_ASSERT((is_same< seq_value_type, bool >::value)); + + BOOST_STATIC_ASSERT((is_same< directed_category, undirected_tag >::value)); + + if (num_vertices(iG) != num_vertices(vG)) + return; + + if (inL.size() != num_edges(iG) || inL.size() != num_edges(vG)) + return; + + if (iG_map.size() != num_edges(iG) || vG_map.size() != num_edges(vG)) + return; + + typedef bimaps::bimap< bimaps::set_of< int >, + bimaps::set_of< order_value_type > > + bimap_type; + typedef typename bimap_type::value_type bimap_value; + + bimap_type iG_bimap, vG_bimap; + for (order_size_type i = 0; i < iG_map.size(); ++i) + iG_bimap.insert(bimap_value(i, iG_map[i])); + for (order_size_type i = 0; i < vG_map.size(); ++i) + vG_bimap.insert(bimap_value(i, vG_map[i])); + + edge_iterator current, last; + boost::tuples::tie(current, last) = edges(iG); + for (; current != last; ++current) + if (iG_bimap.right.find(*current) == iG_bimap.right.end()) + return; + boost::tuples::tie(current, last) = edges(vG); + for (; current != last; ++current) + if (vG_bimap.right.find(*current) == vG_bimap.right.end()) + return; + + std::stack< edge_descriptor > iG_buf, vG_buf; + + std::map< vertex_descriptor, edge_descriptor > tree_map; + std::map< vertex_descriptor, vertex_descriptor > pred_map; + std::map< vertex_descriptor, int > dist_map, low_map; + + detail::bridges_visitor< associative_property_map< std::map< + vertex_descriptor, edge_descriptor > >, + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor > >, + associative_property_map< std::map< vertex_descriptor, int > >, + associative_property_map< std::map< vertex_descriptor, int > >, + std::stack< edge_descriptor > > + iG_vis(associative_property_map< + std::map< vertex_descriptor, edge_descriptor > >(tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor > >(pred_map), + associative_property_map< std::map< vertex_descriptor, int > >( + dist_map), + associative_property_map< std::map< vertex_descriptor, int > >(low_map), + iG_buf), + vG_vis(associative_property_map< + std::map< vertex_descriptor, edge_descriptor > >(tree_map), + associative_property_map< + std::map< vertex_descriptor, vertex_descriptor > >(pred_map), + associative_property_map< std::map< vertex_descriptor, int > >( + dist_map), + associative_property_map< std::map< vertex_descriptor, int > >( + low_map), + vG_buf); + + std::map< vertex_descriptor, default_color_type > vertex_color; + std::map< edge_descriptor, default_color_type > edge_color; + + undirected_dfs(iG, iG_vis, + associative_property_map< + std::map< vertex_descriptor, default_color_type > >(vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >(edge_color)); + undirected_dfs(vG, vG_vis, + associative_property_map< + std::map< vertex_descriptor, default_color_type > >(vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >(edge_color)); + + while (!iG_buf.empty()) + { + inL[iG_bimap.right.at(iG_buf.top())] = true; + iG_buf.pop(); + } + while (!vG_buf.empty()) + { + inL[vG_bimap.right.at(vG_buf.top())] = true; + vG_buf.pop(); + } + + std::map< edge_descriptor, bool > iG_inL, vG_inL; + associative_property_map< std::map< edge_descriptor, bool > > aiG_inL( + iG_inL), + avG_inL(vG_inL); + + for (seq_size_type i = 0; i < inL.size(); ++i) + { + if (inL[i]) + { + put(aiG_inL, iG_bimap.left.at(i), true); + put(avG_inL, vG_bimap.left.at(i), true); + } + else + { + put(aiG_inL, iG_bimap.left.at(i), false); + put(avG_inL, vG_bimap.left.at(i), false); + } + } + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< + associative_property_map< std::map< edge_descriptor, bool > > >( + aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack< edge_descriptor > >(&iG_buf)), + associative_property_map< + std::map< vertex_descriptor, default_color_type > >(vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >(edge_color)); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< + associative_property_map< std::map< edge_descriptor, bool > > >( + avG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack< edge_descriptor > >(&vG_buf)), + associative_property_map< + std::map< vertex_descriptor, default_color_type > >(vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >(edge_color)); + + if (iG_buf.empty() && vG_buf.empty()) + { + + std::map< edge_descriptor, bool > iG_deleted, vG_deleted; + associative_property_map< std::map< edge_descriptor, bool > > diG( + iG_deleted); + associative_property_map< std::map< edge_descriptor, bool > > dvG( + vG_deleted); + + boost::tuples::tie(current, last) = edges(iG); + for (; current != last; ++current) + put(diG, *current, false); + boost::tuples::tie(current, last) = edges(vG); + for (; current != last; ++current) + put(dvG, *current, false); + + for (seq_size_type j = 0; j < inL.size(); ++j) + { + if (!inL[j]) + { + put(aiG_inL, iG_bimap.left.at(j), true); + put(avG_inL, vG_bimap.left.at(j), true); + + undirected_dfs( + make_filtered_graph(iG, + detail::inL_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(aiG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack< edge_descriptor > >( + &iG_buf)), + associative_property_map< + std::map< vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >( + edge_color)); + undirected_dfs( + make_filtered_graph(vG, + detail::inL_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(avG_inL)), + make_dfs_visitor( + detail::cycle_finder< std::stack< edge_descriptor > >( + &vG_buf)), + associative_property_map< + std::map< vertex_descriptor, default_color_type > >( + vertex_color), + associative_property_map< + std::map< edge_descriptor, default_color_type > >( + edge_color)); + + if (!iG_buf.empty() || !vG_buf.empty()) + { + while (!iG_buf.empty()) + iG_buf.pop(); + while (!vG_buf.empty()) + vG_buf.pop(); + put(diG, iG_bimap.left.at(j), true); + put(dvG, vG_bimap.left.at(j), true); + } + + put(aiG_inL, iG_bimap.left.at(j), false); + put(avG_inL, vG_bimap.left.at(j), false); + } + } + + int cc = 0; + + std::map< vertex_descriptor, int > com_map; + cc += connected_components( + make_filtered_graph(iG, + detail::deleted_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(diG)), + associative_property_map< std::map< vertex_descriptor, int > >( + com_map)); + cc += connected_components( + make_filtered_graph(vG, + detail::deleted_edge_status< associative_property_map< + std::map< edge_descriptor, bool > > >(dvG)), + associative_property_map< std::map< vertex_descriptor, int > >( + com_map)); + + if (cc != 2) + return; + + // REC + detail::rec_two_graphs_common_spanning_trees< Graph, Func, Seq, + associative_property_map< std::map< edge_descriptor, bool > > >( + iG, iG_bimap, aiG_inL, diG, vG, vG_bimap, aiG_inL, dvG, func, inL); + } +} + +template < typename Graph, typename Func, typename Seq > +BOOST_CONCEPT_REQUIRES( + ((IncidenceGraphConcept< Graph >))((EdgeListGraphConcept< Graph >)), (void)) +two_graphs_common_spanning_trees( + const Graph& iG, const Graph& vG, Func func, Seq inL) +{ + typedef graph_traits< Graph > GraphTraits; + + typedef typename GraphTraits::edge_descriptor edge_descriptor; + typedef typename GraphTraits::edge_iterator edge_iterator; + + std::vector< edge_descriptor > iGO, vGO; + edge_iterator curr, last; + + boost::tuples::tie(curr, last) = edges(iG); + for (; curr != last; ++curr) + iGO.push_back(*curr); + + boost::tuples::tie(curr, last) = edges(vG); + for (; curr != last; ++curr) + vGO.push_back(*curr); + + two_graphs_common_spanning_trees(iG, iGO, vG, vGO, func, inL); +} + +} // namespace boost + +#endif // BOOST_GRAPH_TWO_GRAPHS_COMMON_SPANNING_TREES_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/undirected_dfs.hpp b/contrib/restricted/boost/graph/include/boost/graph/undirected_dfs.hpp new file mode 100644 index 0000000000..62088c87fb --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/undirected_dfs.hpp @@ -0,0 +1,269 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_GRAPH_UNDIRECTED_DFS_HPP +#define BOOST_GRAPH_UNDIRECTED_DFS_HPP + +#include <boost/graph/depth_first_search.hpp> +#include <vector> +#include <boost/concept/assert.hpp> + +namespace boost +{ + +namespace detail +{ + +// Define BOOST_RECURSIVE_DFS to use older, recursive version. +// It is retained for a while in order to perform performance +// comparison. +#ifndef BOOST_RECURSIVE_DFS + + template < typename IncidenceGraph, typename DFSVisitor, + typename VertexColorMap, typename EdgeColorMap > + void undir_dfv_impl(const IncidenceGraph& g, + typename graph_traits< IncidenceGraph >::vertex_descriptor u, + DFSVisitor& vis, VertexColorMap vertex_color, EdgeColorMap edge_color) + { + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< IncidenceGraph >)); + BOOST_CONCEPT_ASSERT((DFSVisitorConcept< DFSVisitor, IncidenceGraph >)); + typedef + typename graph_traits< IncidenceGraph >::vertex_descriptor Vertex; + typedef typename graph_traits< IncidenceGraph >::edge_descriptor Edge; + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< VertexColorMap, Vertex >)); + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< EdgeColorMap, Edge >)); + typedef + typename property_traits< VertexColorMap >::value_type ColorValue; + typedef + typename property_traits< EdgeColorMap >::value_type EColorValue; + BOOST_CONCEPT_ASSERT((ColorValueConcept< ColorValue >)); + BOOST_CONCEPT_ASSERT((ColorValueConcept< EColorValue >)); + typedef color_traits< ColorValue > Color; + typedef color_traits< EColorValue > EColor; + typedef typename graph_traits< IncidenceGraph >::out_edge_iterator Iter; + typedef std::pair< Vertex, + std::pair< boost::optional< Edge >, std::pair< Iter, Iter > > > + VertexInfo; + + std::vector< VertexInfo > stack; + + put(vertex_color, u, Color::gray()); + vis.discover_vertex(u, g); + stack.push_back(std::make_pair( + u, std::make_pair(boost::optional< Edge >(), out_edges(u, g)))); + while (!stack.empty()) + { + VertexInfo& back = stack.back(); + u = back.first; + boost::optional< Edge > src_e = back.second.first; + Iter ei = back.second.second.first, + ei_end = back.second.second.second; + stack.pop_back(); + while (ei != ei_end) + { + Vertex v = target(*ei, g); + vis.examine_edge(*ei, g); + ColorValue v_color = get(vertex_color, v); + EColorValue uv_color = get(edge_color, *ei); + put(edge_color, *ei, EColor::black()); + if (v_color == Color::white()) + { + vis.tree_edge(*ei, g); + src_e = *ei; + stack.push_back(std::make_pair(u, + std::make_pair(src_e, std::make_pair(++ei, ei_end)))); + u = v; + put(vertex_color, u, Color::gray()); + vis.discover_vertex(u, g); + boost::tie(ei, ei_end) = out_edges(u, g); + } + else if (v_color == Color::gray()) + { + if (uv_color == EColor::white()) + vis.back_edge(*ei, g); + call_finish_edge(vis, *ei, g); + ++ei; + } + else + { // if (v_color == Color::black()) + call_finish_edge(vis, *ei, g); + ++ei; + } + } + put(vertex_color, u, Color::black()); + vis.finish_vertex(u, g); + if (src_e) + call_finish_edge(vis, src_e.get(), g); + } + } + +#else // BOOST_RECURSIVE_DFS + + template < typename IncidenceGraph, typename DFSVisitor, + typename VertexColorMap, typename EdgeColorMap > + void undir_dfv_impl(const IncidenceGraph& g, + typename graph_traits< IncidenceGraph >::vertex_descriptor u, + DFSVisitor& vis, // pass-by-reference here, important! + VertexColorMap vertex_color, EdgeColorMap edge_color) + { + BOOST_CONCEPT_ASSERT((IncidenceGraphConcept< IncidenceGraph >)); + BOOST_CONCEPT_ASSERT((DFSVisitorConcept< DFSVisitor, IncidenceGraph >)); + typedef + typename graph_traits< IncidenceGraph >::vertex_descriptor Vertex; + typedef typename graph_traits< IncidenceGraph >::edge_descriptor Edge; + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< VertexColorMap, Vertex >)); + BOOST_CONCEPT_ASSERT( + (ReadWritePropertyMapConcept< EdgeColorMap, Edge >)); + typedef + typename property_traits< VertexColorMap >::value_type ColorValue; + typedef + typename property_traits< EdgeColorMap >::value_type EColorValue; + BOOST_CONCEPT_ASSERT((ColorValueConcept< ColorValue >)); + BOOST_CONCEPT_ASSERT((ColorValueConcept< EColorValue >)); + typedef color_traits< ColorValue > Color; + typedef color_traits< EColorValue > EColor; + typename graph_traits< IncidenceGraph >::out_edge_iterator ei, ei_end; + + put(vertex_color, u, Color::gray()); + vis.discover_vertex(u, g); + for (boost::tie(ei, ei_end) = out_edges(u, g); ei != ei_end; ++ei) + { + Vertex v = target(*ei, g); + vis.examine_edge(*ei, g); + ColorValue v_color = get(vertex_color, v); + EColorValue uv_color = get(edge_color, *ei); + put(edge_color, *ei, EColor::black()); + if (v_color == Color::white()) + { + vis.tree_edge(*ei, g); + undir_dfv_impl(g, v, vis, vertex_color, edge_color); + } + else if (v_color == Color::gray() && uv_color == EColor::white()) + vis.back_edge(*ei, g); + call_finish_edge(vis, *ei, g); + } + put(vertex_color, u, Color::black()); + vis.finish_vertex(u, g); + } + +#endif // ! BOOST_RECURSIVE_DFS + +} // namespace detail + +template < typename Graph, typename DFSVisitor, typename VertexColorMap, + typename EdgeColorMap, typename Vertex > +void undirected_dfs(const Graph& g, DFSVisitor vis, VertexColorMap vertex_color, + EdgeColorMap edge_color, Vertex start_vertex) +{ + BOOST_CONCEPT_ASSERT((DFSVisitorConcept< DFSVisitor, Graph >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph >)); + + typedef typename property_traits< VertexColorMap >::value_type ColorValue; + typedef color_traits< ColorValue > Color; + + typename graph_traits< Graph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + put(vertex_color, *ui, Color::white()); + vis.initialize_vertex(*ui, g); + } + typename graph_traits< Graph >::edge_iterator ei, ei_end; + for (boost::tie(ei, ei_end) = edges(g); ei != ei_end; ++ei) + put(edge_color, *ei, Color::white()); + + if (start_vertex != *vertices(g).first) + { + vis.start_vertex(start_vertex, g); + detail::undir_dfv_impl(g, start_vertex, vis, vertex_color, edge_color); + } + + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + ColorValue u_color = get(vertex_color, *ui); + if (u_color == Color::white()) + { + vis.start_vertex(*ui, g); + detail::undir_dfv_impl(g, *ui, vis, vertex_color, edge_color); + } + } +} + +template < typename Graph, typename DFSVisitor, typename VertexColorMap, + typename EdgeColorMap > +void undirected_dfs(const Graph& g, DFSVisitor vis, VertexColorMap vertex_color, + EdgeColorMap edge_color) +{ + undirected_dfs(g, vis, vertex_color, edge_color, *vertices(g).first); +} + +namespace detail +{ + template < typename VertexColorMap > struct udfs_dispatch + { + + template < typename Graph, typename Vertex, typename DFSVisitor, + typename EdgeColorMap, typename P, typename T, typename R > + static void apply(const Graph& g, DFSVisitor vis, Vertex start_vertex, + const bgl_named_params< P, T, R >&, EdgeColorMap edge_color, + VertexColorMap vertex_color) + { + undirected_dfs(g, vis, vertex_color, edge_color, start_vertex); + } + }; + + template <> struct udfs_dispatch< param_not_found > + { + template < typename Graph, typename Vertex, typename DFSVisitor, + typename EdgeColorMap, typename P, typename T, typename R > + static void apply(const Graph& g, DFSVisitor vis, Vertex start_vertex, + const bgl_named_params< P, T, R >& params, EdgeColorMap edge_color, + param_not_found) + { + std::vector< default_color_type > color_vec(num_vertices(g)); + default_color_type c = white_color; // avoid warning about un-init + undirected_dfs(g, vis, + make_iterator_property_map(color_vec.begin(), + choose_const_pmap( + get_param(params, vertex_index), g, vertex_index), + c), + edge_color, start_vertex); + } + }; + +} // namespace detail + +// Named Parameter Variant +template < typename Graph, typename P, typename T, typename R > +void undirected_dfs(const Graph& g, const bgl_named_params< P, T, R >& params) +{ + typedef typename get_param_type< vertex_color_t, + bgl_named_params< P, T, R > >::type C; + detail::udfs_dispatch< C >::apply(g, + choose_param( + get_param(params, graph_visitor), make_dfs_visitor(null_visitor())), + choose_param(get_param(params, root_vertex_t()), *vertices(g).first), + params, get_param(params, edge_color), get_param(params, vertex_color)); +} + +template < typename IncidenceGraph, typename DFSVisitor, + typename VertexColorMap, typename EdgeColorMap > +void undirected_depth_first_visit(const IncidenceGraph& g, + typename graph_traits< IncidenceGraph >::vertex_descriptor u, + DFSVisitor vis, VertexColorMap vertex_color, EdgeColorMap edge_color) +{ + detail::undir_dfv_impl(g, u, vis, vertex_color, edge_color); +} + +} // namespace boost + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/undirected_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/undirected_graph.hpp new file mode 100644 index 0000000000..ec1bbbba61 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/undirected_graph.hpp @@ -0,0 +1,822 @@ +// (C) Copyright 2007-2009 Andrew Sutton +// +// Use, modification and distribution are subject to the +// Boost Software License, Version 1.0 (See accompanying file +// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_GRAPH_UNDIRECTED_GRAPH_HPP +#define BOOST_GRAPH_UNDIRECTED_GRAPH_HPP + +#include <boost/graph/adjacency_list.hpp> +#include <boost/graph/properties.hpp> +#include <boost/pending/property.hpp> +#include <boost/property_map/transform_value_property_map.hpp> +#include <boost/type_traits.hpp> +#include <boost/mpl/if.hpp> + +namespace boost +{ +struct undirected_graph_tag +{ +}; + +/** + * The undirected_graph class template is a simplified version of the BGL + * adjacency list. This class is provided for ease of use, but may not + * perform as well as custom-defined adjacency list classes. Instances of + * this template model the VertexIndexGraph, and EdgeIndexGraph concepts. The + * graph is also fully mutable, supporting both insertions and removals of + * vertices and edges. + * + * @note Special care must be taken when removing vertices or edges since + * those operations can invalidate the numbering of vertices. + */ +template < typename VertexProp = no_property, typename EdgeProp = no_property, + typename GraphProp = no_property > +class undirected_graph +{ +public: + typedef GraphProp graph_property_type; + typedef VertexProp vertex_property_type; + typedef EdgeProp edge_property_type; + typedef typename lookup_one_property< GraphProp, graph_bundle_t >::type + graph_bundled; + typedef typename lookup_one_property< VertexProp, vertex_bundle_t >::type + vertex_bundled; + typedef typename lookup_one_property< EdgeProp, edge_bundle_t >::type + edge_bundled; + +public: + // Embed indices into the vertex type. + typedef property< vertex_index_t, unsigned, vertex_property_type > + internal_vertex_property; + typedef property< edge_index_t, unsigned, edge_property_type > + internal_edge_property; + +public: + typedef adjacency_list< listS, listS, undirectedS, internal_vertex_property, + internal_edge_property, GraphProp, listS > + graph_type; + +private: + // storage selectors + typedef typename graph_type::vertex_list_selector vertex_list_selector; + typedef typename graph_type::edge_list_selector edge_list_selector; + typedef typename graph_type::out_edge_list_selector out_edge_list_selector; + typedef typename graph_type::directed_selector directed_selector; + +public: + // more commonly used graph types + typedef typename graph_type::stored_vertex stored_vertex; + typedef typename graph_type::vertices_size_type vertices_size_type; + typedef typename graph_type::edges_size_type edges_size_type; + typedef typename graph_type::degree_size_type degree_size_type; + typedef typename graph_type::vertex_descriptor vertex_descriptor; + typedef typename graph_type::edge_descriptor edge_descriptor; + + // iterator types + typedef typename graph_type::vertex_iterator vertex_iterator; + typedef typename graph_type::edge_iterator edge_iterator; + typedef typename graph_type::out_edge_iterator out_edge_iterator; + typedef typename graph_type::in_edge_iterator in_edge_iterator; + typedef typename graph_type::adjacency_iterator adjacency_iterator; + + // miscellaneous types + typedef undirected_graph_tag graph_tag; + typedef typename graph_type::directed_category directed_category; + typedef typename graph_type::edge_parallel_category edge_parallel_category; + typedef typename graph_type::traversal_category traversal_category; + + typedef std::size_t vertex_index_type; + typedef std::size_t edge_index_type; + + inline undirected_graph(GraphProp const& p = GraphProp()) + : m_graph(p) + , m_num_vertices(0) + , m_num_edges(0) + , m_max_vertex_index(0) + , m_max_edge_index(0) + { + } + + inline undirected_graph(undirected_graph const& x) + : m_graph(x.m_graph) + , m_num_vertices(x.m_num_vertices) + , m_num_edges(x.m_num_edges) + , m_max_vertex_index(x.m_max_vertex_index) + , m_max_edge_index(x.m_max_edge_index) + { + } + + inline undirected_graph( + vertices_size_type n, GraphProp const& p = GraphProp()) + : m_graph(n, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { + renumber_vertex_indices(); + } + + template < typename EdgeIterator > + inline undirected_graph(EdgeIterator f, EdgeIterator l, + vertices_size_type n, edges_size_type m = 0, + GraphProp const& p = GraphProp()) + : m_graph(f, l, n, m, p) + , m_num_vertices(n) + , m_num_edges(0) + , m_max_vertex_index(n) + , m_max_edge_index(0) + { + // Unfortunately, we have to renumber to ensure correct indexing. + renumber_indices(); + + // Can't always guarantee that the number of edges is actually + // m if distance(f, l) != m (or is undefined). + m_num_edges = m_max_edge_index = boost::num_edges(m_graph); + } + + undirected_graph& operator=(undirected_graph const& g) + { + if (&g != this) + { + m_graph = g.m_graph; + m_num_vertices = g.m_num_vertices; + m_num_edges = g.m_num_edges; + m_max_vertex_index = g.m_max_vertex_index; + } + return *this; + } + + // The impl_() methods are not part of the public interface. + graph_type& impl() { return m_graph; } + + graph_type const& impl() const { return m_graph; } + + // The following methods are not part of the public interface + vertices_size_type num_vertices() const { return m_num_vertices; } + +private: + // This helper function manages the attribution of vertex indices. + vertex_descriptor make_index(vertex_descriptor v) + { + boost::put(vertex_index, m_graph, v, m_max_vertex_index); + m_num_vertices++; + m_max_vertex_index++; + return v; + } + +public: + vertex_descriptor add_vertex() + { + return make_index(boost::add_vertex(m_graph)); + } + + vertex_descriptor add_vertex(vertex_property_type const& p) + { + return make_index( + boost::add_vertex(internal_vertex_property(0u, p), m_graph)); + } + + void clear_vertex(vertex_descriptor v) + { + std::pair< out_edge_iterator, out_edge_iterator > p + = boost::out_edges(v, m_graph); + m_num_edges -= std::distance(p.first, p.second); + boost::clear_vertex(v, m_graph); + } + + void remove_vertex(vertex_descriptor v) + { + boost::remove_vertex(v, m_graph); + --m_num_vertices; + } + + edges_size_type num_edges() const { return m_num_edges; } + +private: + // A helper fucntion for managing edge index attributes. + std::pair< edge_descriptor, bool > const& make_index( + std::pair< edge_descriptor, bool > const& x) + { + if (x.second) + { + boost::put(edge_index, m_graph, x.first, m_max_edge_index); + ++m_num_edges; + ++m_max_edge_index; + } + return x; + } + +public: + std::pair< edge_descriptor, bool > add_edge( + vertex_descriptor u, vertex_descriptor v) + { + return make_index(boost::add_edge(u, v, m_graph)); + } + + std::pair< edge_descriptor, bool > add_edge( + vertex_descriptor u, vertex_descriptor v, edge_property_type const& p) + { + return make_index( + boost::add_edge(u, v, internal_edge_property(0u, p), m_graph)); + } + + void remove_edge(vertex_descriptor u, vertex_descriptor v) + { + // find all edges, (u, v) + std::vector< edge_descriptor > edges; + out_edge_iterator i, i_end; + for (boost::tie(i, i_end) = boost::out_edges(u, m_graph); i != i_end; + ++i) + { + if (boost::target(*i, m_graph) == v) + { + edges.push_back(*i); + } + } + // remove all edges, (u, v) + typename std::vector< edge_descriptor >::iterator j = edges.begin(), + j_end = edges.end(); + for (; j != j_end; ++j) + { + remove_edge(*j); + } + } + + void remove_edge(edge_iterator i) { remove_edge(*i); } + + void remove_edge(edge_descriptor e) + { + boost::remove_edge(e, m_graph); + --m_num_edges; + } + + vertex_index_type max_vertex_index() const { return m_max_vertex_index; } + + void renumber_vertex_indices() + { + vertex_iterator i, i_end; + boost::tie(i, i_end) = vertices(m_graph); + m_max_vertex_index = renumber_vertex_indices(i, i_end, 0); + } + + void remove_vertex_and_renumber_indices(vertex_iterator i) + { + vertex_iterator j = next(i), end = vertices(m_graph).second; + vertex_index_type n = get(vertex_index, m_graph, *i); + + // remove the offending vertex and renumber everything after + remove_vertex(*i); + m_max_vertex_index = renumber_vertex_indices(j, end, n); + } + + edge_index_type max_edge_index() const { return m_max_edge_index; } + + void renumber_edge_indices() + { + edge_iterator i, end; + boost::tie(i, end) = edges(m_graph); + m_max_edge_index = renumber_edge_indices(i, end, 0); + } + + void remove_edge_and_renumber_indices(edge_iterator i) + { + edge_iterator j = next(i), end = edges(m_graph.second); + edge_index_type n = get(edge_index, m_graph, *i); + + // remove the edge and renumber everything after it + remove_edge(*i); + m_max_edge_index = renumber_edge_indices(j, end, n); + } + + void renumber_indices() + { + renumber_vertex_indices(); + renumber_edge_indices(); + } + + // bundled property support +#ifndef BOOST_GRAPH_NO_BUNDLED_PROPERTIES + vertex_bundled& operator[](vertex_descriptor v) { return m_graph[v]; } + + vertex_bundled const& operator[](vertex_descriptor v) const + { + return m_graph[v]; + } + + edge_bundled& operator[](edge_descriptor e) { return m_graph[e]; } + + edge_bundled const& operator[](edge_descriptor e) const + { + return m_graph[e]; + } + + graph_bundled& operator[](graph_bundle_t) { return get_property(*this); } + + graph_bundled const& operator[](graph_bundle_t) const + { + return get_property(*this); + } +#endif + + // Graph concepts + static vertex_descriptor null_vertex() { return graph_type::null_vertex(); } + + void clear() + { + m_graph.clear(); + m_num_vertices = m_max_vertex_index = 0; + m_num_edges = m_max_edge_index = 0; + } + + void swap(undirected_graph& g) + { + m_graph.swap(g.m_graph); + std::swap(m_num_vertices, g.m_num_vertices); + std::swap(m_max_vertex_index, g.m_max_vertex_index); + std::swap(m_num_edges, g.m_num_edges); + std::swap(m_max_edge_index, g.m_max_edge_index); + } + +private: + vertices_size_type renumber_vertex_indices( + vertex_iterator i, vertex_iterator end, vertices_size_type n) + { + typedef + typename property_map< graph_type, vertex_index_t >::type IndexMap; + IndexMap indices = get(vertex_index, m_graph); + for (; i != end; ++i) + { + indices[*i] = n++; + } + return n; + } + + edges_size_type renumber_edge_indices( + edge_iterator i, edge_iterator end, edges_size_type n) + { + typedef + typename property_map< graph_type, edge_index_t >::type IndexMap; + IndexMap indices = get(edge_index, m_graph); + for (; i != end; ++i) + { + indices[*i] = n++; + } + return n; + } + + graph_type m_graph; + vertices_size_type m_num_vertices; + edges_size_type m_num_edges; + vertex_index_type m_max_vertex_index; + edge_index_type m_max_edge_index; +}; + +#define UNDIRECTED_GRAPH_PARAMS typename VP, typename EP, typename GP +#define UNDIRECTED_GRAPH undirected_graph< VP, EP, GP > + +// IncidenceGraph concepts +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::vertex_descriptor source( + typename UNDIRECTED_GRAPH::edge_descriptor e, UNDIRECTED_GRAPH const& g) +{ + return source(e, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::vertex_descriptor target( + typename UNDIRECTED_GRAPH::edge_descriptor e, UNDIRECTED_GRAPH const& g) +{ + return target(e, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::degree_size_type out_degree( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return out_degree(v, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::out_edge_iterator, + typename UNDIRECTED_GRAPH::out_edge_iterator > +out_edges( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return out_edges(v, g.impl()); +} + +// BidirectionalGraph concepts +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::degree_size_type in_degree( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return in_degree(v, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::in_edge_iterator, + typename UNDIRECTED_GRAPH::in_edge_iterator > +in_edges( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return in_edges(v, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::out_edge_iterator, + typename UNDIRECTED_GRAPH::out_edge_iterator > +incident_edges( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return out_edges(v, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::degree_size_type degree( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return degree(v, g.impl()); +} + +// AdjacencyGraph concepts +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::adjacency_iterator, + typename UNDIRECTED_GRAPH::adjacency_iterator > +adjacent_vertices( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return adjacent_vertices(v, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +typename UNDIRECTED_GRAPH::vertex_descriptor vertex( + typename UNDIRECTED_GRAPH::vertices_size_type n, UNDIRECTED_GRAPH const& g) +{ + return vertex(n, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +std::pair< typename UNDIRECTED_GRAPH::edge_descriptor, bool > edge( + typename UNDIRECTED_GRAPH::vertex_descriptor u, + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return edge(u, v, g.impl()); +} + +// VertexListGraph concepts +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::vertices_size_type num_vertices( + UNDIRECTED_GRAPH const& g) +{ + return g.num_vertices(); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::vertex_iterator, + typename UNDIRECTED_GRAPH::vertex_iterator > +vertices(UNDIRECTED_GRAPH const& g) +{ + return vertices(g.impl()); +} + +// EdgeListGraph concepts +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::edges_size_type num_edges( + UNDIRECTED_GRAPH const& g) +{ + return g.num_edges(); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::edge_iterator, + typename UNDIRECTED_GRAPH::edge_iterator > +edges(UNDIRECTED_GRAPH const& g) +{ + return edges(g.impl()); +} + +// MutableGraph concepts +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::vertex_descriptor add_vertex( + UNDIRECTED_GRAPH& g) +{ + return g.add_vertex(); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::vertex_descriptor add_vertex( + typename UNDIRECTED_GRAPH::vertex_property_type const& p, + UNDIRECTED_GRAPH& g) +{ + return g.add_vertex(p); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void clear_vertex( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH& g) +{ + return g.clear_vertex(v); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void remove_vertex( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH& g) +{ + return g.remove_vertex(v); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::edge_descriptor, bool > add_edge( + typename UNDIRECTED_GRAPH::vertex_descriptor u, + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH& g) +{ + return g.add_edge(u, v); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline std::pair< typename UNDIRECTED_GRAPH::edge_descriptor, bool > add_edge( + typename UNDIRECTED_GRAPH::vertex_descriptor u, + typename UNDIRECTED_GRAPH::vertex_descriptor v, + typename UNDIRECTED_GRAPH::edge_property_type const& p, UNDIRECTED_GRAPH& g) +{ + return g.add_edge(u, v, p); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void remove_edge(typename UNDIRECTED_GRAPH::vertex_descriptor u, + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH& g) +{ + return g.remove_edge(u, v); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void remove_edge( + typename UNDIRECTED_GRAPH::edge_descriptor e, UNDIRECTED_GRAPH& g) +{ + return g.remove_edge(e); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void remove_edge( + typename UNDIRECTED_GRAPH::edge_iterator i, UNDIRECTED_GRAPH& g) +{ + return g.remove_edge(i); +} + +template < UNDIRECTED_GRAPH_PARAMS, class Predicate > +inline void remove_edge_if(Predicate pred, UNDIRECTED_GRAPH& g) +{ + return remove_edge_if(pred, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS, class Predicate > +inline void remove_incident_edge_if( + typename UNDIRECTED_GRAPH::vertex_descriptor v, Predicate pred, + UNDIRECTED_GRAPH& g) +{ + return remove_out_edge_if(v, pred, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS, class Predicate > +inline void remove_out_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v, + Predicate pred, UNDIRECTED_GRAPH& g) +{ + return remove_out_edge_if(v, pred, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS, class Predicate > +inline void remove_in_edge_if(typename UNDIRECTED_GRAPH::vertex_descriptor v, + Predicate pred, UNDIRECTED_GRAPH& g) +{ + return remove_in_edge_if(v, pred, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Property > +struct property_map< UNDIRECTED_GRAPH, Property > +: property_map< typename UNDIRECTED_GRAPH::graph_type, Property > +{ +}; + +template < UNDIRECTED_GRAPH_PARAMS > +struct property_map< UNDIRECTED_GRAPH, vertex_all_t > +{ + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename UNDIRECTED_GRAPH::graph_type, + vertex_all_t >::const_type > + const_type; + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename UNDIRECTED_GRAPH::graph_type, + vertex_all_t >::type > + type; +}; + +template < UNDIRECTED_GRAPH_PARAMS > +struct property_map< UNDIRECTED_GRAPH, edge_all_t > +{ + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename UNDIRECTED_GRAPH::graph_type, + edge_all_t >::const_type > + const_type; + typedef transform_value_property_map< detail::remove_first_property, + typename property_map< typename UNDIRECTED_GRAPH::graph_type, + edge_all_t >::type > + type; +}; + +// PropertyGraph concepts +template < UNDIRECTED_GRAPH_PARAMS, typename Property > +inline typename property_map< UNDIRECTED_GRAPH, Property >::type get( + Property p, UNDIRECTED_GRAPH& g) +{ + return get(p, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Property > +inline typename property_map< UNDIRECTED_GRAPH, Property >::const_type get( + Property p, UNDIRECTED_GRAPH const& g) +{ + return get(p, g.impl()); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename property_map< UNDIRECTED_GRAPH, vertex_all_t >::type get( + vertex_all_t, UNDIRECTED_GRAPH& g) +{ + return typename property_map< UNDIRECTED_GRAPH, vertex_all_t >::type( + detail::remove_first_property(), get(vertex_all, g.impl())); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename property_map< UNDIRECTED_GRAPH, vertex_all_t >::const_type get( + vertex_all_t, UNDIRECTED_GRAPH const& g) +{ + return typename property_map< UNDIRECTED_GRAPH, vertex_all_t >::const_type( + detail::remove_first_property(), get(vertex_all, g.impl())); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename property_map< UNDIRECTED_GRAPH, edge_all_t >::type get( + edge_all_t, UNDIRECTED_GRAPH& g) +{ + return typename property_map< UNDIRECTED_GRAPH, edge_all_t >::type( + detail::remove_first_property(), get(edge_all, g.impl())); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename property_map< UNDIRECTED_GRAPH, edge_all_t >::const_type get( + edge_all_t, UNDIRECTED_GRAPH const& g) +{ + return typename property_map< UNDIRECTED_GRAPH, edge_all_t >::const_type( + detail::remove_first_property(), get(edge_all, g.impl())); +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Property, typename Key > +inline typename property_traits< typename property_map< + typename UNDIRECTED_GRAPH::graph_type, Property >::const_type >::value_type +get(Property p, UNDIRECTED_GRAPH const& g, Key const& k) +{ + return get(p, g.impl(), k); +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Key > +inline typename property_traits< + typename property_map< typename UNDIRECTED_GRAPH::graph_type, + vertex_all_t >::const_type >::value_type +get(vertex_all_t, UNDIRECTED_GRAPH const& g, Key const& k) +{ + return get(vertex_all, g.impl(), k).m_base; +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Key > +inline typename property_traits< + typename property_map< typename UNDIRECTED_GRAPH::graph_type, + edge_all_t >::const_type >::value_type +get(edge_all_t, UNDIRECTED_GRAPH const& g, Key const& k) +{ + return get(edge_all, g.impl(), k).m_base; +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Property, typename Key, + typename Value > +inline void put(Property p, UNDIRECTED_GRAPH& g, Key const& k, Value const& v) +{ + put(p, g.impl(), k, v); +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Key, typename Value > +inline void put(vertex_all_t, UNDIRECTED_GRAPH& g, Key const& k, Value const& v) +{ + put(vertex_all, g.impl(), k, + typename UNDIRECTED_GRAPH::internal_vertex_property( + get(vertex_index, g.impl(), k), v)); +} + +template < UNDIRECTED_GRAPH_PARAMS, typename Key, typename Value > +inline void put(edge_all_t, UNDIRECTED_GRAPH& g, Key const& k, Value const& v) +{ + put(edge_all, g.impl(), k, + typename UNDIRECTED_GRAPH::internal_vertex_property( + get(edge_index, g.impl(), k), v)); +} + +template < UNDIRECTED_GRAPH_PARAMS, class Property > +inline typename graph_property< UNDIRECTED_GRAPH, Property >::type& +get_property(UNDIRECTED_GRAPH& g, Property p) +{ + return get_property(g.impl(), p); +} + +template < UNDIRECTED_GRAPH_PARAMS, class Property > +inline typename graph_property< UNDIRECTED_GRAPH, Property >::type const& +get_property(UNDIRECTED_GRAPH const& g, Property p) +{ + return get_property(g.impl(), p); +} + +template < UNDIRECTED_GRAPH_PARAMS, class Property, class Value > +inline void set_property(UNDIRECTED_GRAPH& g, Property p, Value v) +{ + return set_property(g.impl(), p, v); +} + +// Indexed Vertex graph + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::vertex_index_type get_vertex_index( + typename UNDIRECTED_GRAPH::vertex_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return get(vertex_index, g, v); +} + +template < UNDIRECTED_GRAPH_PARAMS > +typename UNDIRECTED_GRAPH::vertex_index_type max_vertex_index( + UNDIRECTED_GRAPH const& g) +{ + return g.max_vertex_index(); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void renumber_vertex_indices(UNDIRECTED_GRAPH& g) +{ + g.renumber_vertex_indices(); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void remove_vertex_and_renumber_indices( + typename UNDIRECTED_GRAPH::vertex_iterator i, UNDIRECTED_GRAPH& g) +{ + g.remove_vertex_and_renumber_indices(i); +} + +// Edge index management + +template < UNDIRECTED_GRAPH_PARAMS > +inline typename UNDIRECTED_GRAPH::edge_index_type get_edge_index( + typename UNDIRECTED_GRAPH::edge_descriptor v, UNDIRECTED_GRAPH const& g) +{ + return get(edge_index, g, v); +} + +template < UNDIRECTED_GRAPH_PARAMS > +typename UNDIRECTED_GRAPH::edge_index_type max_edge_index( + UNDIRECTED_GRAPH const& g) +{ + return g.max_edge_index(); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void renumber_edge_indices(UNDIRECTED_GRAPH& g) +{ + g.renumber_edge_indices(); +} + +template < UNDIRECTED_GRAPH_PARAMS > +inline void remove_edge_and_renumber_indices( + typename UNDIRECTED_GRAPH::edge_iterator i, UNDIRECTED_GRAPH& g) +{ + g.remove_edge_and_renumber_indices(i); +} + +// Index management +template < UNDIRECTED_GRAPH_PARAMS > +inline void renumber_indices(UNDIRECTED_GRAPH& g) +{ + g.renumber_indices(); +} + +// Mutability Traits +template < UNDIRECTED_GRAPH_PARAMS > +struct graph_mutability_traits< UNDIRECTED_GRAPH > +{ + typedef mutable_property_graph_tag category; +}; + +#undef UNDIRECTED_GRAPH_PARAMS +#undef UNDIRECTED_GRAPH + +} /* namespace boost */ + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/graph/vector_as_graph.hpp b/contrib/restricted/boost/graph/include/boost/graph/vector_as_graph.hpp new file mode 100644 index 0000000000..444df87674 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/vector_as_graph.hpp @@ -0,0 +1,334 @@ +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Copyright 2006 The Trustees of Indiana University. +// Copyright (C) 2001 Vladimir Prus <ghost@cs.msu.su> +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek, Douglas Gregor +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +// The mutating functions (add_edge, etc.) were added by Vladimir Prus. + +#ifndef BOOST_VECTOR_AS_GRAPH_HPP +#define BOOST_VECTOR_AS_GRAPH_HPP + +#include <cassert> +#include <utility> +#include <vector> +#include <cstddef> +#include <iterator> +#include <boost/iterator/counting_iterator.hpp> +#include <boost/range/irange.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/property_map/property_map.hpp> +#include <boost/graph/properties.hpp> +#include <algorithm> + +/* + This module implements the VertexListGraph concept using a + std::vector as the "back-bone" of the graph (the vector *is* the + graph object). The edge-lists type of the graph is templated, so the + user can choose any STL container, so long as the value_type of the + container is convertible to the size_type of the vector. For now any + graph properties must be stored seperately. + + This module requires the C++ compiler to support partial + specialization for the graph_traits class, so this is not portable + to VC++. + +*/ + +namespace boost +{ +namespace detail +{ + template < class EdgeList > struct val_out_edge_ret; + template < class EdgeList > struct val_out_edge_iter; + template < class EdgeList > struct val_edge; +} +} + +namespace boost +{ + +struct vector_as_graph_traversal_tag : public vertex_list_graph_tag, + public adjacency_graph_tag, + public incidence_graph_tag +{ +}; + +template < class EdgeList > struct graph_traits< std::vector< EdgeList > > +{ + typedef typename EdgeList::value_type V; + typedef V vertex_descriptor; + typedef typename detail::val_edge< EdgeList >::type edge_descriptor; + typedef typename EdgeList::const_iterator adjacency_iterator; + typedef + typename detail::val_out_edge_iter< EdgeList >::type out_edge_iterator; + typedef void in_edge_iterator; + typedef void edge_iterator; + typedef counting_iterator< V > vertex_iterator; + typedef directed_tag directed_category; + typedef allow_parallel_edge_tag edge_parallel_category; + typedef vector_as_graph_traversal_tag traversal_category; + typedef typename std::vector< EdgeList >::size_type vertices_size_type; + typedef void edges_size_type; + typedef typename EdgeList::size_type degree_size_type; + static V null_vertex() { return V(-1); } +}; +template < class EdgeList > struct edge_property_type< std::vector< EdgeList > > +{ + typedef void type; +}; +template < class EdgeList > +struct vertex_property_type< std::vector< EdgeList > > +{ + typedef void type; +}; +template < class EdgeList > +struct graph_property_type< std::vector< EdgeList > > +{ + typedef void type; +}; +} + +namespace boost +{ + +namespace detail +{ + + // "val" is short for Vector Adjacency List + + template < class EdgeList > struct val_edge + { + typedef typename EdgeList::value_type V; + typedef std::pair< V, V > type; + }; + + // need rewrite this using boost::iterator_adaptor + template < class V, class Iter > class val_out_edge_iterator + { + typedef val_out_edge_iterator self; + typedef std::pair< V, V > Edge; + + public: + typedef std::input_iterator_tag iterator_category; + typedef std::pair< V, V > value_type; + typedef std::ptrdiff_t difference_type; + typedef std::pair< V, V >* pointer; + typedef const std::pair< V, V > reference; + val_out_edge_iterator() {} + val_out_edge_iterator(V s, Iter i) : _source(s), _iter(i) {} + Edge operator*() const { return Edge(_source, *_iter); } + self& operator++() + { + ++_iter; + return *this; + } + self operator++(int) + { + self t = *this; + ++_iter; + return t; + } + bool operator==(const self& x) const { return _iter == x._iter; } + bool operator!=(const self& x) const { return _iter != x._iter; } + + protected: + V _source; + Iter _iter; + }; + + template < class EdgeList > struct val_out_edge_iter + { + typedef typename EdgeList::value_type V; + typedef typename EdgeList::const_iterator Iter; + typedef val_out_edge_iterator< V, Iter > type; + }; + + template < class EdgeList > struct val_out_edge_ret + { + typedef typename val_out_edge_iter< EdgeList >::type IncIter; + typedef std::pair< IncIter, IncIter > type; + }; + +} // namesapce detail + +template < class EdgeList, class Alloc > +typename detail::val_out_edge_ret< EdgeList >::type out_edges( + typename EdgeList::value_type v, const std::vector< EdgeList, Alloc >& g) +{ + typedef typename detail::val_out_edge_iter< EdgeList >::type Iter; + typedef typename detail::val_out_edge_ret< EdgeList >::type return_type; + return return_type(Iter(v, g[v].begin()), Iter(v, g[v].end())); +} + +template < class EdgeList, class Alloc > +typename EdgeList::size_type out_degree( + typename EdgeList::value_type v, const std::vector< EdgeList, Alloc >& g) +{ + return g[v].size(); +} + +template < class EdgeList, class Alloc > +std::pair< typename EdgeList::const_iterator, + typename EdgeList::const_iterator > +adjacent_vertices( + typename EdgeList::value_type v, const std::vector< EdgeList, Alloc >& g) +{ + return std::make_pair(g[v].begin(), g[v].end()); +} + +// source() and target() already provided for pairs in graph_traits.hpp + +template < class EdgeList, class Alloc > +std::pair< boost::counting_iterator< typename EdgeList::value_type >, + boost::counting_iterator< typename EdgeList::value_type > > +vertices(const std::vector< EdgeList, Alloc >& v) +{ + typedef boost::counting_iterator< typename EdgeList::value_type > Iter; + return std::make_pair(Iter(0), Iter(v.size())); +} + +template < class EdgeList, class Alloc > +typename std::vector< EdgeList, Alloc >::size_type num_vertices( + const std::vector< EdgeList, Alloc >& v) +{ + return v.size(); +} + +template < class EdgeList, class Allocator > +typename std::pair< typename detail::val_edge< EdgeList >::type, bool > +add_edge(typename EdgeList::value_type u, typename EdgeList::value_type v, + std::vector< EdgeList, Allocator >& g) +{ + typedef typename detail::val_edge< EdgeList >::type edge_type; + g[u].insert(g[u].end(), v); + return std::make_pair(edge_type(u, v), true); +} + +template < class EdgeList, class Allocator > +typename std::pair< typename detail::val_edge< EdgeList >::type, bool > edge( + typename EdgeList::value_type u, typename EdgeList::value_type v, + std::vector< EdgeList, Allocator >& g) +{ + typedef typename detail::val_edge< EdgeList >::type edge_type; + typename EdgeList::iterator i = g[u].begin(), end = g[u].end(); + for (; i != end; ++i) + if (*i == v) + return std::make_pair(edge_type(u, v), true); + return std::make_pair(edge_type(), false); +} + +template < class EdgeList, class Allocator > +void remove_edge(typename EdgeList::value_type u, + typename EdgeList::value_type v, std::vector< EdgeList, Allocator >& g) +{ + typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v); + if (i != g[u].end()) + g[u].erase(i, g[u].end()); +} + +template < class EdgeList, class Allocator > +void remove_edge(typename detail::val_edge< EdgeList >::type e, + std::vector< EdgeList, Allocator >& g) +{ + typename EdgeList::value_type u, v; + u = e.first; + v = e.second; + // FIXME: edge type does not fully specify the edge to be deleted + typename EdgeList::iterator i = std::remove(g[u].begin(), g[u].end(), v); + if (i != g[u].end()) + g[u].erase(i, g[u].end()); +} + +template < class EdgeList, class Allocator, class Predicate > +void remove_edge_if(Predicate p, std::vector< EdgeList, Allocator >& g) +{ + for (std::size_t u = 0; u < g.size(); ++u) + { + // Oops! gcc gets internal compiler error on compose_....... + + typedef typename EdgeList::iterator iterator; + iterator b = g[u].begin(), e = g[u].end(); + + if (!g[u].empty()) + { + + for (; b != e;) + { + if (p(std::make_pair(u, *b))) + { + --e; + if (b == e) + break; + else + iter_swap(b, e); + } + else + { + ++b; + } + } + } + + if (e != g[u].end()) + g[u].erase(e, g[u].end()); + } +} + +template < class EdgeList, class Allocator > +typename EdgeList::value_type add_vertex(std::vector< EdgeList, Allocator >& g) +{ + g.resize(g.size() + 1); + return g.size() - 1; +} + +template < class EdgeList, class Allocator > +void clear_vertex( + typename EdgeList::value_type u, std::vector< EdgeList, Allocator >& g) +{ + g[u].clear(); + for (std::size_t i = 0; i < g.size(); ++i) + remove_edge(i, u, g); +} + +template < class EdgeList, class Allocator > +void remove_vertex( + typename EdgeList::value_type u, std::vector< EdgeList, Allocator >& g) +{ + typedef typename EdgeList::iterator iterator; + clear_vertex(u, g); + g.erase(g.begin() + u); + for (std::size_t i = 0; i < g.size(); ++i) + for (iterator it = g[i].begin(); it != g[i].end(); ++it) + // after clear_vertex *it is never equal to u + if (*it > u) + --*it; +} + +template < typename EdgeList, typename Allocator > +struct property_map< std::vector< EdgeList, Allocator >, vertex_index_t > +{ + typedef identity_property_map type; + typedef type const_type; +}; + +template < typename EdgeList, typename Allocator > +identity_property_map get( + vertex_index_t, const std::vector< EdgeList, Allocator >&) +{ + return identity_property_map(); +} + +template < typename EdgeList, typename Allocator > +identity_property_map get(vertex_index_t, std::vector< EdgeList, Allocator >&) +{ + return identity_property_map(); +} +} // namespace boost + +#endif // BOOST_VECTOR_AS_GRAPH_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/vertex_and_edge_range.hpp b/contrib/restricted/boost/graph/include/boost/graph/vertex_and_edge_range.hpp new file mode 100644 index 0000000000..c9e217bd72 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/vertex_and_edge_range.hpp @@ -0,0 +1,158 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +#ifndef BOOST_GRAPH_VERTEX_AND_EDGE_RANGE_HPP +#define BOOST_GRAPH_VERTEX_AND_EDGE_RANGE_HPP + +#include <boost/graph/graph_traits.hpp> +#include <iterator> + +namespace boost +{ + +namespace graph +{ + template < typename Graph, typename VertexIterator, typename EdgeIterator > + class vertex_and_edge_range + { + typedef graph_traits< Graph > traits_type; + + public: + typedef typename traits_type::directed_category directed_category; + typedef + typename traits_type::edge_parallel_category edge_parallel_category; + struct traversal_category : public virtual vertex_list_graph_tag, + public virtual edge_list_graph_tag + { + }; + + typedef std::size_t vertices_size_type; + typedef VertexIterator vertex_iterator; + typedef typename std::iterator_traits< VertexIterator >::value_type + vertex_descriptor; + + typedef EdgeIterator edge_iterator; + typedef typename std::iterator_traits< EdgeIterator >::value_type + edge_descriptor; + + typedef std::size_t edges_size_type; + + typedef void adjacency_iterator; + typedef void out_edge_iterator; + typedef void in_edge_iterator; + typedef void degree_size_type; + + static vertex_descriptor null_vertex() + { + return traits_type::null_vertex(); + } + + vertex_and_edge_range(const Graph& g, VertexIterator first_v, + VertexIterator last_v, vertices_size_type n, EdgeIterator first_e, + EdgeIterator last_e, edges_size_type m) + : g(&g) + , first_vertex(first_v) + , last_vertex(last_v) + , m_num_vertices(n) + , first_edge(first_e) + , last_edge(last_e) + , m_num_edges(m) + { + } + + vertex_and_edge_range(const Graph& g, VertexIterator first_v, + VertexIterator last_v, EdgeIterator first_e, EdgeIterator last_e) + : g(&g) + , first_vertex(first_v) + , last_vertex(last_v) + , first_edge(first_e) + , last_edge(last_e) + { + m_num_vertices = std::distance(first_v, last_v); + m_num_edges = std::distance(first_e, last_e); + } + + const Graph* g; + vertex_iterator first_vertex; + vertex_iterator last_vertex; + vertices_size_type m_num_vertices; + edge_iterator first_edge; + edge_iterator last_edge; + edges_size_type m_num_edges; + }; + + template < typename Graph, typename VertexIterator, typename EdgeIterator > + inline std::pair< VertexIterator, VertexIterator > vertices( + const vertex_and_edge_range< Graph, VertexIterator, EdgeIterator >& g) + { + return std::make_pair(g.first_vertex, g.last_vertex); + } + + template < typename Graph, typename VertexIterator, typename EdgeIterator > + inline typename vertex_and_edge_range< Graph, VertexIterator, + EdgeIterator >::vertices_size_type + num_vertices( + const vertex_and_edge_range< Graph, VertexIterator, EdgeIterator >& g) + { + return g.m_num_vertices; + } + + template < typename Graph, typename VertexIterator, typename EdgeIterator > + inline std::pair< EdgeIterator, EdgeIterator > edges( + const vertex_and_edge_range< Graph, VertexIterator, EdgeIterator >& g) + { + return std::make_pair(g.first_edge, g.last_edge); + } + + template < typename Graph, typename VertexIterator, typename EdgeIterator > + inline typename vertex_and_edge_range< Graph, VertexIterator, + EdgeIterator >::edges_size_type + num_edges( + const vertex_and_edge_range< Graph, VertexIterator, EdgeIterator >& g) + { + return g.m_num_edges; + } + + template < typename Graph, typename VertexIterator, typename EdgeIterator > + inline typename vertex_and_edge_range< Graph, VertexIterator, + EdgeIterator >::vertex_descriptor + source(typename vertex_and_edge_range< Graph, VertexIterator, + EdgeIterator >::edge_descriptor e, + const vertex_and_edge_range< Graph, VertexIterator, EdgeIterator >& g) + { + return source(e, *g.g); + } + + template < typename Graph, typename VertexIterator, typename EdgeIterator > + inline typename vertex_and_edge_range< Graph, VertexIterator, + EdgeIterator >::vertex_descriptor + target(typename vertex_and_edge_range< Graph, VertexIterator, + EdgeIterator >::edge_descriptor e, + const vertex_and_edge_range< Graph, VertexIterator, EdgeIterator >& g) + { + return target(e, *g.g); + } + + template < typename Graph, typename VertexIterator, typename EdgeIterator > + inline vertex_and_edge_range< Graph, VertexIterator, EdgeIterator > + make_vertex_and_edge_range(const Graph& g, VertexIterator first_v, + VertexIterator last_v, EdgeIterator first_e, EdgeIterator last_e) + { + typedef vertex_and_edge_range< Graph, VertexIterator, EdgeIterator > + result_type; + return result_type(g, first_v, last_v, first_e, last_e); + } + +} // end namespace graph + +using graph::make_vertex_and_edge_range; +using graph::vertex_and_edge_range; + +} // end namespace boost +#endif // BOOST_GRAPH_VERTEX_AND_EDGE_RANGE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/vf2_sub_graph_iso.hpp b/contrib/restricted/boost/graph/include/boost/graph/vf2_sub_graph_iso.hpp new file mode 100644 index 0000000000..77f7496bd1 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/vf2_sub_graph_iso.hpp @@ -0,0 +1,1301 @@ +//======================================================================= +// Copyright (C) 2012 Flavio De Lorenzi (fdlorenzi@gmail.com) +// Copyright (C) 2013 Jakob Lykke Andersen, University of Southern Denmark +// (jlandersen@imada.sdu.dk) +// +// The algorithm implemented here is derived from original ideas by +// Pasquale Foggia and colaborators. For further information see +// e.g. Cordella et al. 2001, 2004. +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= + +// Revision History: +// 8 April 2013: Fixed a typo in vf2_print_callback. (Flavio De Lorenzi) + +#ifndef BOOST_VF2_SUB_GRAPH_ISO_HPP +#define BOOST_VF2_SUB_GRAPH_ISO_HPP + +#include <iostream> +#include <iomanip> +#include <iterator> +#include <vector> +#include <utility> + +#include <boost/assert.hpp> +#include <boost/concept/assert.hpp> +#include <boost/concept_check.hpp> +#include <boost/graph/graph_utility.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/graph/mcgregor_common_subgraphs.hpp> // for always_equivalent +#include <boost/graph/named_function_params.hpp> +#include <boost/type_traits/has_less.hpp> +#include <boost/mpl/int.hpp> +#include <boost/range/algorithm/sort.hpp> +#include <boost/tuple/tuple.hpp> +#include <boost/utility/enable_if.hpp> + +#ifndef BOOST_GRAPH_ITERATION_MACROS_HPP +#define BOOST_ISO_INCLUDED_ITER_MACROS // local macro, see bottom of file +#include <boost/graph/iteration_macros.hpp> +#endif + +namespace boost +{ + +// Default print_callback +template < typename Graph1, typename Graph2 > struct vf2_print_callback +{ + + vf2_print_callback(const Graph1& graph1, const Graph2& graph2) + : graph1_(graph1), graph2_(graph2) + { + } + + template < typename CorrespondenceMap1To2, typename CorrespondenceMap2To1 > + bool operator()(CorrespondenceMap1To2 f, CorrespondenceMap2To1) const + { + + // Print (sub)graph isomorphism map + BGL_FORALL_VERTICES_T(v, graph1_, Graph1) + std::cout << '(' << get(vertex_index_t(), graph1_, v) << ", " + << get(vertex_index_t(), graph2_, get(f, v)) << ") "; + + std::cout << std::endl; + + return true; + } + +private: + const Graph1& graph1_; + const Graph2& graph2_; +}; + +namespace detail +{ + + // State associated with a single graph (graph_this) + template < typename GraphThis, typename GraphOther, typename IndexMapThis, + typename IndexMapOther > + class base_state + { + + typedef typename graph_traits< GraphThis >::vertex_descriptor + vertex_this_type; + typedef typename graph_traits< GraphOther >::vertex_descriptor + vertex_other_type; + + typedef + typename graph_traits< GraphThis >::vertices_size_type size_type; + + const GraphThis& graph_this_; + const GraphOther& graph_other_; + + IndexMapThis index_map_this_; + IndexMapOther index_map_other_; + + std::vector< vertex_other_type > core_vec_; + typedef iterator_property_map< + typename std::vector< vertex_other_type >::iterator, IndexMapThis, + vertex_other_type, vertex_other_type& > + core_map_type; + core_map_type core_; + + std::vector< size_type > in_vec_, out_vec_; + typedef iterator_property_map< + typename std::vector< size_type >::iterator, IndexMapThis, + size_type, size_type& > + in_out_map_type; + in_out_map_type in_, out_; + + size_type term_in_count_, term_out_count_, term_both_count_, + core_count_; + + // Forbidden + base_state(const base_state&); + base_state& operator=(const base_state&); + + public: + base_state(const GraphThis& graph_this, const GraphOther& graph_other, + IndexMapThis index_map_this, IndexMapOther index_map_other) + : graph_this_(graph_this) + , graph_other_(graph_other) + , index_map_this_(index_map_this) + , index_map_other_(index_map_other) + , core_vec_(num_vertices(graph_this_), + graph_traits< GraphOther >::null_vertex()) + , core_(core_vec_.begin(), index_map_this_) + , in_vec_(num_vertices(graph_this_), 0) + , out_vec_(num_vertices(graph_this_), 0) + , in_(in_vec_.begin(), index_map_this_) + , out_(out_vec_.begin(), index_map_this_) + , term_in_count_(0) + , term_out_count_(0) + , term_both_count_(0) + , core_count_(0) + { + } + + // Adds a vertex pair to the state of graph graph_this + void push( + const vertex_this_type& v_this, const vertex_other_type& v_other) + { + + ++core_count_; + + put(core_, v_this, v_other); + + if (!get(in_, v_this)) + { + put(in_, v_this, core_count_); + ++term_in_count_; + if (get(out_, v_this)) + ++term_both_count_; + } + + if (!get(out_, v_this)) + { + put(out_, v_this, core_count_); + ++term_out_count_; + if (get(in_, v_this)) + ++term_both_count_; + } + + BGL_FORALL_INEDGES_T(v_this, e, graph_this_, GraphThis) + { + vertex_this_type w = source(e, graph_this_); + if (!get(in_, w)) + { + put(in_, w, core_count_); + ++term_in_count_; + if (get(out_, w)) + ++term_both_count_; + } + } + + BGL_FORALL_OUTEDGES_T(v_this, e, graph_this_, GraphThis) + { + vertex_this_type w = target(e, graph_this_); + if (!get(out_, w)) + { + put(out_, w, core_count_); + ++term_out_count_; + if (get(in_, w)) + ++term_both_count_; + } + } + } + + // Removes vertex pair from state of graph_this + void pop(const vertex_this_type& v_this, const vertex_other_type&) + { + + if (!core_count_) + return; + + if (get(in_, v_this) == core_count_) + { + put(in_, v_this, 0); + --term_in_count_; + if (get(out_, v_this)) + --term_both_count_; + } + + BGL_FORALL_INEDGES_T(v_this, e, graph_this_, GraphThis) + { + vertex_this_type w = source(e, graph_this_); + if (get(in_, w) == core_count_) + { + put(in_, w, 0); + --term_in_count_; + if (get(out_, w)) + --term_both_count_; + } + } + + if (get(out_, v_this) == core_count_) + { + put(out_, v_this, 0); + --term_out_count_; + if (get(in_, v_this)) + --term_both_count_; + } + + BGL_FORALL_OUTEDGES_T(v_this, e, graph_this_, GraphThis) + { + vertex_this_type w = target(e, graph_this_); + if (get(out_, w) == core_count_) + { + put(out_, w, 0); + --term_out_count_; + if (get(in_, w)) + --term_both_count_; + } + } + put(core_, v_this, graph_traits< GraphOther >::null_vertex()); + + --core_count_; + } + + // Returns true if the in-terminal set is not empty + bool term_in() const { return core_count_ < term_in_count_; } + + // Returns true if vertex belongs to the in-terminal set + bool term_in(const vertex_this_type& v) const + { + return (get(in_, v) > 0) + && (get(core_, v) == graph_traits< GraphOther >::null_vertex()); + } + + // Returns true if the out-terminal set is not empty + bool term_out() const { return core_count_ < term_out_count_; } + + // Returns true if vertex belongs to the out-terminal set + bool term_out(const vertex_this_type& v) const + { + return (get(out_, v) > 0) + && (get(core_, v) == graph_traits< GraphOther >::null_vertex()); + } + + // Returns true of both (in- and out-terminal) sets are not empty + bool term_both() const { return core_count_ < term_both_count_; } + + // Returns true if vertex belongs to both (in- and out-terminal) sets + bool term_both(const vertex_this_type& v) const + { + return (get(in_, v) > 0) && (get(out_, v) > 0) + && (get(core_, v) == graph_traits< GraphOther >::null_vertex()); + } + + // Returns true if vertex belongs to the core map, i.e. it is in the + // present mapping + bool in_core(const vertex_this_type& v) const + { + return get(core_, v) != graph_traits< GraphOther >::null_vertex(); + } + + // Returns the number of vertices in the mapping + size_type count() const { return core_count_; } + + // Returns the image (in graph_other) of vertex v (in graph_this) + vertex_other_type core(const vertex_this_type& v) const + { + return get(core_, v); + } + + // Returns the mapping + core_map_type get_map() const { return core_; } + + // Returns the "time" (or depth) when vertex was added to the + // in-terminal set + size_type in_depth(const vertex_this_type& v) const + { + return get(in_, v); + } + + // Returns the "time" (or depth) when vertex was added to the + // out-terminal set + size_type out_depth(const vertex_this_type& v) const + { + return get(out_, v); + } + + // Returns the terminal set counts + boost::tuple< size_type, size_type, size_type > term_set() const + { + return boost::make_tuple( + term_in_count_, term_out_count_, term_both_count_); + } + }; + + // Function object that checks whether a valid edge + // exists. For multi-graphs matched edges are excluded + template < typename Graph, typename Enable = void > + struct equivalent_edge_exists + { + typedef + typename boost::graph_traits< Graph >::edge_descriptor edge_type; + + BOOST_CONCEPT_ASSERT((LessThanComparable< edge_type >)); + + template < typename EdgePredicate > + bool operator()(typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + EdgePredicate is_valid_edge, const Graph& g) + { + + BGL_FORALL_OUTEDGES_T(s, e, g, Graph) + { + if ((target(e, g) == t) && is_valid_edge(e) + && (matched_edges_.find(e) == matched_edges_.end())) + { + matched_edges_.insert(e); + return true; + } + } + + return false; + } + + private: + std::set< edge_type > matched_edges_; + }; + + template < typename Graph > + struct equivalent_edge_exists< Graph, + typename boost::disable_if< is_multigraph< Graph > >::type > + { + template < typename EdgePredicate > + bool operator()(typename graph_traits< Graph >::vertex_descriptor s, + typename graph_traits< Graph >::vertex_descriptor t, + EdgePredicate is_valid_edge, const Graph& g) + { + + typename graph_traits< Graph >::edge_descriptor e; + bool found; + boost::tie(e, found) = edge(s, t, g); + if (!found) + return false; + else if (is_valid_edge(e)) + return true; + + return false; + } + }; + + // Generates a predicate for edge e1 given a binary predicate and a + // fixed edge e2 + template < typename Graph1, typename Graph2, + typename EdgeEquivalencePredicate > + struct edge1_predicate + { + + edge1_predicate(EdgeEquivalencePredicate edge_comp, + typename graph_traits< Graph2 >::edge_descriptor e2) + : edge_comp_(edge_comp), e2_(e2) + { + } + + bool operator()(typename graph_traits< Graph1 >::edge_descriptor e1) + { + return edge_comp_(e1, e2_); + } + + EdgeEquivalencePredicate edge_comp_; + typename graph_traits< Graph2 >::edge_descriptor e2_; + }; + + // Generates a predicate for edge e2 given given a binary predicate and a + // fixed edge e1 + template < typename Graph1, typename Graph2, + typename EdgeEquivalencePredicate > + struct edge2_predicate + { + + edge2_predicate(EdgeEquivalencePredicate edge_comp, + typename graph_traits< Graph1 >::edge_descriptor e1) + : edge_comp_(edge_comp), e1_(e1) + { + } + + bool operator()(typename graph_traits< Graph2 >::edge_descriptor e2) + { + return edge_comp_(e1_, e2); + } + + EdgeEquivalencePredicate edge_comp_; + typename graph_traits< Graph1 >::edge_descriptor e1_; + }; + + enum problem_selector + { + subgraph_mono, + subgraph_iso, + isomorphism + }; + + // The actual state associated with both graphs + template < typename Graph1, typename Graph2, typename IndexMap1, + typename IndexMap2, typename EdgeEquivalencePredicate, + typename VertexEquivalencePredicate, typename SubGraphIsoMapCallback, + problem_selector problem_selection > + class state + { + + typedef typename graph_traits< Graph1 >::vertex_descriptor vertex1_type; + typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_type; + + typedef typename graph_traits< Graph1 >::edge_descriptor edge1_type; + typedef typename graph_traits< Graph2 >::edge_descriptor edge2_type; + + typedef typename graph_traits< Graph1 >::vertices_size_type + graph1_size_type; + typedef typename graph_traits< Graph2 >::vertices_size_type + graph2_size_type; + + const Graph1& graph1_; + const Graph2& graph2_; + + IndexMap1 index_map1_; + + EdgeEquivalencePredicate edge_comp_; + VertexEquivalencePredicate vertex_comp_; + + base_state< Graph1, Graph2, IndexMap1, IndexMap2 > state1_; + base_state< Graph2, Graph1, IndexMap2, IndexMap1 > state2_; + + // Three helper functions used in Feasibility and Valid functions to + // test terminal set counts when testing for: + // - graph sub-graph monomorphism, or + inline bool comp_term_sets(graph1_size_type a, graph2_size_type b, + boost::mpl::int_< subgraph_mono >) const + { + return a <= b; + } + + // - graph sub-graph isomorphism, or + inline bool comp_term_sets(graph1_size_type a, graph2_size_type b, + boost::mpl::int_< subgraph_iso >) const + { + return a <= b; + } + + // - graph isomorphism + inline bool comp_term_sets(graph1_size_type a, graph2_size_type b, + boost::mpl::int_< isomorphism >) const + { + return a == b; + } + + // Forbidden + state(const state&); + state& operator=(const state&); + + public: + state(const Graph1& graph1, const Graph2& graph2, IndexMap1 index_map1, + IndexMap2 index_map2, EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) + : graph1_(graph1) + , graph2_(graph2) + , index_map1_(index_map1) + , edge_comp_(edge_comp) + , vertex_comp_(vertex_comp) + , state1_(graph1, graph2, index_map1, index_map2) + , state2_(graph2, graph1, index_map2, index_map1) + { + } + + // Add vertex pair to the state + void push(const vertex1_type& v, const vertex2_type& w) + { + state1_.push(v, w); + state2_.push(w, v); + } + + // Remove vertex pair from state + void pop(const vertex1_type& v, const vertex2_type&) + { + vertex2_type w = state1_.core(v); + state1_.pop(v, w); + state2_.pop(w, v); + } + + // Checks the feasibility of a new vertex pair + bool feasible(const vertex1_type& v_new, const vertex2_type& w_new) + { + + if (!vertex_comp_(v_new, w_new)) + return false; + + // graph1 + graph1_size_type term_in1_count = 0, term_out1_count = 0, + rest1_count = 0; + + { + equivalent_edge_exists< Graph2 > edge2_exists; + + BGL_FORALL_INEDGES_T(v_new, e1, graph1_, Graph1) + { + vertex1_type v = source(e1, graph1_); + + if (state1_.in_core(v) || (v == v_new)) + { + vertex2_type w = w_new; + if (v != v_new) + w = state1_.core(v); + if (!edge2_exists(w, w_new, + edge2_predicate< Graph1, Graph2, + EdgeEquivalencePredicate >(edge_comp_, e1), + graph2_)) + return false; + } + else + { + if (0 < state1_.in_depth(v)) + ++term_in1_count; + if (0 < state1_.out_depth(v)) + ++term_out1_count; + if ((state1_.in_depth(v) == 0) + && (state1_.out_depth(v) == 0)) + ++rest1_count; + } + } + } + + { + equivalent_edge_exists< Graph2 > edge2_exists; + + BGL_FORALL_OUTEDGES_T(v_new, e1, graph1_, Graph1) + { + vertex1_type v = target(e1, graph1_); + if (state1_.in_core(v) || (v == v_new)) + { + vertex2_type w = w_new; + if (v != v_new) + w = state1_.core(v); + + if (!edge2_exists(w_new, w, + edge2_predicate< Graph1, Graph2, + EdgeEquivalencePredicate >(edge_comp_, e1), + graph2_)) + return false; + } + else + { + if (0 < state1_.in_depth(v)) + ++term_in1_count; + if (0 < state1_.out_depth(v)) + ++term_out1_count; + if ((state1_.in_depth(v) == 0) + && (state1_.out_depth(v) == 0)) + ++rest1_count; + } + } + } + + // graph2 + graph2_size_type term_out2_count = 0, term_in2_count = 0, + rest2_count = 0; + + { + equivalent_edge_exists< Graph1 > edge1_exists; + + BGL_FORALL_INEDGES_T(w_new, e2, graph2_, Graph2) + { + vertex2_type w = source(e2, graph2_); + if (state2_.in_core(w) || (w == w_new)) + { + if (problem_selection != subgraph_mono) + { + vertex1_type v = v_new; + if (w != w_new) + v = state2_.core(w); + + if (!edge1_exists(v, v_new, + edge1_predicate< Graph1, Graph2, + EdgeEquivalencePredicate >( + edge_comp_, e2), + graph1_)) + return false; + } + } + else + { + if (0 < state2_.in_depth(w)) + ++term_in2_count; + if (0 < state2_.out_depth(w)) + ++term_out2_count; + if ((state2_.in_depth(w) == 0) + && (state2_.out_depth(w) == 0)) + ++rest2_count; + } + } + } + + { + equivalent_edge_exists< Graph1 > edge1_exists; + + BGL_FORALL_OUTEDGES_T(w_new, e2, graph2_, Graph2) + { + vertex2_type w = target(e2, graph2_); + if (state2_.in_core(w) || (w == w_new)) + { + if (problem_selection != subgraph_mono) + { + vertex1_type v = v_new; + if (w != w_new) + v = state2_.core(w); + + if (!edge1_exists(v_new, v, + edge1_predicate< Graph1, Graph2, + EdgeEquivalencePredicate >( + edge_comp_, e2), + graph1_)) + return false; + } + } + else + { + if (0 < state2_.in_depth(w)) + ++term_in2_count; + if (0 < state2_.out_depth(w)) + ++term_out2_count; + if ((state2_.in_depth(w) == 0) + && (state2_.out_depth(w) == 0)) + ++rest2_count; + } + } + } + + if (problem_selection != subgraph_mono) + { // subgraph_iso and isomorphism + return comp_term_sets(term_in1_count, term_in2_count, + boost::mpl::int_< problem_selection >()) + && comp_term_sets(term_out1_count, term_out2_count, + boost::mpl::int_< problem_selection >()) + && comp_term_sets(rest1_count, rest2_count, + boost::mpl::int_< problem_selection >()); + } + else + { // subgraph_mono + return comp_term_sets(term_in1_count, term_in2_count, + boost::mpl::int_< problem_selection >()) + && comp_term_sets(term_out1_count, term_out2_count, + boost::mpl::int_< problem_selection >()) + && comp_term_sets( + term_in1_count + term_out1_count + rest1_count, + term_in2_count + term_out2_count + rest2_count, + boost::mpl::int_< problem_selection >()); + } + } + + // Returns true if vertex v in graph1 is a possible candidate to + // be added to the current state + bool possible_candidate1(const vertex1_type& v) const + { + if (state1_.term_both() && state2_.term_both()) + return state1_.term_both(v); + else if (state1_.term_out() && state2_.term_out()) + return state1_.term_out(v); + else if (state1_.term_in() && state2_.term_in()) + return state1_.term_in(v); + else + return !state1_.in_core(v); + } + + // Returns true if vertex w in graph2 is a possible candidate to + // be added to the current state + bool possible_candidate2(const vertex2_type& w) const + { + if (state1_.term_both() && state2_.term_both()) + return state2_.term_both(w); + else if (state1_.term_out() && state2_.term_out()) + return state2_.term_out(w); + else if (state1_.term_in() && state2_.term_in()) + return state2_.term_in(w); + else + return !state2_.in_core(w); + } + + // Returns true if a mapping was found + bool success() const + { + return state1_.count() == num_vertices(graph1_); + } + + // Returns true if a state is valid + bool valid() const + { + boost::tuple< graph1_size_type, graph1_size_type, graph1_size_type > + term1; + boost::tuple< graph2_size_type, graph2_size_type, graph2_size_type > + term2; + + term1 = state1_.term_set(); + term2 = state2_.term_set(); + + return comp_term_sets(boost::get< 0 >(term1), + boost::get< 0 >(term2), + boost::mpl::int_< problem_selection >()) + && comp_term_sets(boost::get< 1 >(term1), + boost::get< 1 >(term2), + boost::mpl::int_< problem_selection >()) + && comp_term_sets(boost::get< 2 >(term1), + boost::get< 2 >(term2), + boost::mpl::int_< problem_selection >()); + } + + // Calls the user_callback with a graph (sub)graph mapping + bool call_back(SubGraphIsoMapCallback user_callback) const + { + return user_callback(state1_.get_map(), state2_.get_map()); + } + }; + + // Data structure to keep info used for back tracking during + // matching process + template < typename Graph1, typename Graph2, typename VertexOrder1 > + struct vf2_match_continuation + { + typename VertexOrder1::const_iterator graph1_verts_iter; + typename graph_traits< Graph2 >::vertex_iterator graph2_verts_iter; + }; + + // Non-recursive method that explores state space using a depth-first + // search strategy. At each depth possible pairs candidate are compute + // and tested for feasibility to extend the mapping. If a complete + // mapping is found, the mapping is output to user_callback in the form + // of a correspondence map (graph1 to graph2). Returning false from the + // user_callback will terminate the search. Function match will return + // true if the entire search space was explored. + template < typename Graph1, typename Graph2, typename IndexMap1, + typename IndexMap2, typename VertexOrder1, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphIsoMapCallback, problem_selector problem_selection > + bool match(const Graph1& graph1, const Graph2& graph2, + SubGraphIsoMapCallback user_callback, const VertexOrder1& vertex_order1, + state< Graph1, Graph2, IndexMap1, IndexMap2, EdgeEquivalencePredicate, + VertexEquivalencePredicate, SubGraphIsoMapCallback, + problem_selection >& s) + { + + typename VertexOrder1::const_iterator graph1_verts_iter; + + typedef typename graph_traits< Graph2 >::vertex_iterator + vertex2_iterator_type; + vertex2_iterator_type graph2_verts_iter, graph2_verts_iter_end; + + typedef vf2_match_continuation< Graph1, Graph2, VertexOrder1 > + match_continuation_type; + std::vector< match_continuation_type > k; + bool found_match = false; + + recur: + if (s.success()) + { + if (!s.call_back(user_callback)) + return true; + found_match = true; + + goto back_track; + } + + if (!s.valid()) + goto back_track; + + graph1_verts_iter = vertex_order1.begin(); + while (graph1_verts_iter != vertex_order1.end() + && !s.possible_candidate1(*graph1_verts_iter)) + { + ++graph1_verts_iter; + } + + boost::tie(graph2_verts_iter, graph2_verts_iter_end) = vertices(graph2); + while (graph2_verts_iter != graph2_verts_iter_end) + { + if (s.possible_candidate2(*graph2_verts_iter)) + { + if (s.feasible(*graph1_verts_iter, *graph2_verts_iter)) + { + match_continuation_type kk; + kk.graph1_verts_iter = graph1_verts_iter; + kk.graph2_verts_iter = graph2_verts_iter; + k.push_back(kk); + + s.push(*graph1_verts_iter, *graph2_verts_iter); + goto recur; + } + } + graph2_loop: + ++graph2_verts_iter; + } + + back_track: + if (k.empty()) + return found_match; + + const match_continuation_type kk = k.back(); + graph1_verts_iter = kk.graph1_verts_iter; + graph2_verts_iter = kk.graph2_verts_iter; + k.pop_back(); + + s.pop(*graph1_verts_iter, *graph2_verts_iter); + + goto graph2_loop; + } + + // Used to sort nodes by in/out degrees + template < typename Graph > struct vertex_in_out_degree_cmp + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_type; + + vertex_in_out_degree_cmp(const Graph& graph) : graph_(graph) {} + + bool operator()(const vertex_type& v, const vertex_type& w) const + { + // lexicographical comparison + return std::make_pair(in_degree(v, graph_), out_degree(v, graph_)) + < std::make_pair(in_degree(w, graph_), out_degree(w, graph_)); + } + + const Graph& graph_; + }; + + // Used to sort nodes by multiplicity of in/out degrees + template < typename Graph, typename FrequencyMap > + struct vertex_frequency_degree_cmp + { + typedef typename graph_traits< Graph >::vertex_descriptor vertex_type; + + vertex_frequency_degree_cmp(const Graph& graph, FrequencyMap freq) + : graph_(graph), freq_(freq) + { + } + + bool operator()(const vertex_type& v, const vertex_type& w) const + { + // lexicographical comparison + return std::make_pair( + freq_[v], in_degree(v, graph_) + out_degree(v, graph_)) + < std::make_pair( + freq_[w], in_degree(w, graph_) + out_degree(w, graph_)); + } + + const Graph& graph_; + FrequencyMap freq_; + }; + + // Sorts vertices of a graph by multiplicity of in/out degrees + template < typename Graph, typename IndexMap, typename VertexOrder > + void sort_vertices( + const Graph& graph, IndexMap index_map, VertexOrder& order) + { + typedef typename graph_traits< Graph >::vertices_size_type size_type; + + boost::range::sort(order, vertex_in_out_degree_cmp< Graph >(graph)); + + std::vector< size_type > freq_vec(num_vertices(graph), 0); + typedef iterator_property_map< + typename std::vector< size_type >::iterator, IndexMap, size_type, + size_type& > + frequency_map_type; + + frequency_map_type freq + = make_iterator_property_map(freq_vec.begin(), index_map); + + typedef typename VertexOrder::iterator order_iterator; + + for (order_iterator order_iter = order.begin(); + order_iter != order.end();) + { + size_type count = 0; + for (order_iterator count_iter = order_iter; + (count_iter != order.end()) + && (in_degree(*order_iter, graph) + == in_degree(*count_iter, graph)) + && (out_degree(*order_iter, graph) + == out_degree(*count_iter, graph)); + ++count_iter) + ++count; + + for (size_type i = 0; i < count; ++i) + { + freq[*order_iter] = count; + ++order_iter; + } + } + + boost::range::sort(order, + vertex_frequency_degree_cmp< Graph, frequency_map_type >( + graph, freq)); + } + + // Enumerates all graph sub-graph mono-/iso-morphism mappings between graphs + // graph_small and graph_large. Continues until user_callback returns true + // or the search space has been fully explored. + template < problem_selector problem_selection, typename GraphSmall, + typename GraphLarge, typename IndexMapSmall, typename IndexMapLarge, + typename VertexOrderSmall, typename EdgeEquivalencePredicate, + typename VertexEquivalencePredicate, typename SubGraphIsoMapCallback > + bool vf2_subgraph_morphism(const GraphSmall& graph_small, + const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback, + IndexMapSmall index_map_small, IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) + { + + // Graph requirements + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< GraphSmall >)); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< GraphSmall >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< GraphSmall >)); + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< GraphSmall >)); + + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< GraphLarge >)); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< GraphLarge >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< GraphLarge >)); + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< GraphLarge >)); + + typedef typename graph_traits< GraphSmall >::vertex_descriptor + vertex_small_type; + typedef typename graph_traits< GraphLarge >::vertex_descriptor + vertex_large_type; + + typedef typename graph_traits< GraphSmall >::vertices_size_type + size_type_small; + typedef typename graph_traits< GraphLarge >::vertices_size_type + size_type_large; + + // Property map requirements + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< IndexMapSmall, vertex_small_type >)); + typedef typename property_traits< IndexMapSmall >::value_type + IndexMapSmallValue; + BOOST_STATIC_ASSERT( + (is_convertible< IndexMapSmallValue, size_type_small >::value)); + + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< IndexMapLarge, vertex_large_type >)); + typedef typename property_traits< IndexMapLarge >::value_type + IndexMapLargeValue; + BOOST_STATIC_ASSERT( + (is_convertible< IndexMapLargeValue, size_type_large >::value)); + + // Edge & vertex requirements + typedef typename graph_traits< GraphSmall >::edge_descriptor + edge_small_type; + typedef typename graph_traits< GraphLarge >::edge_descriptor + edge_large_type; + + BOOST_CONCEPT_ASSERT((BinaryPredicateConcept< EdgeEquivalencePredicate, + edge_small_type, edge_large_type >)); + + BOOST_CONCEPT_ASSERT( + (BinaryPredicateConcept< VertexEquivalencePredicate, + vertex_small_type, vertex_large_type >)); + + // Vertex order requirements + BOOST_CONCEPT_ASSERT((ContainerConcept< VertexOrderSmall >)); + typedef typename VertexOrderSmall::value_type order_value_type; + BOOST_STATIC_ASSERT( + (is_same< vertex_small_type, order_value_type >::value)); + BOOST_ASSERT(num_vertices(graph_small) == vertex_order_small.size()); + + if (num_vertices(graph_small) > num_vertices(graph_large)) + return false; + + typename graph_traits< GraphSmall >::edges_size_type num_edges_small + = num_edges(graph_small); + typename graph_traits< GraphLarge >::edges_size_type num_edges_large + = num_edges(graph_large); + + // Double the number of edges for undirected graphs: each edge counts as + // in-edge and out-edge + if (is_undirected(graph_small)) + num_edges_small *= 2; + if (is_undirected(graph_large)) + num_edges_large *= 2; + if (num_edges_small > num_edges_large) + return false; + + detail::state< GraphSmall, GraphLarge, IndexMapSmall, IndexMapLarge, + EdgeEquivalencePredicate, VertexEquivalencePredicate, + SubGraphIsoMapCallback, problem_selection > + s(graph_small, graph_large, index_map_small, index_map_large, + edge_comp, vertex_comp); + + return detail::match( + graph_small, graph_large, user_callback, vertex_order_small, s); + } + +} // namespace detail + +// Returns vertex order (vertices sorted by multiplicity of in/out degrees) +template < typename Graph > +std::vector< typename graph_traits< Graph >::vertex_descriptor > +vertex_order_by_mult(const Graph& graph) +{ + + std::vector< typename graph_traits< Graph >::vertex_descriptor > + vertex_order; + std::copy(vertices(graph).first, vertices(graph).second, + std::back_inserter(vertex_order)); + + detail::sort_vertices(graph, get(vertex_index, graph), vertex_order); + return vertex_order; +} + +// Enumerates all graph sub-graph monomorphism mappings between graphs +// graph_small and graph_large. Continues until user_callback returns true or +// the search space has been fully explored. +template < typename GraphSmall, typename GraphLarge, typename IndexMapSmall, + typename IndexMapLarge, typename VertexOrderSmall, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphIsoMapCallback > +bool vf2_subgraph_mono(const GraphSmall& graph_small, + const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback, + IndexMapSmall index_map_small, IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeEquivalencePredicate edge_comp, VertexEquivalencePredicate vertex_comp) +{ + return detail::vf2_subgraph_morphism< detail::subgraph_mono >(graph_small, + graph_large, user_callback, index_map_small, index_map_large, + vertex_order_small, edge_comp, vertex_comp); +} + +// All default interface for vf2_subgraph_iso +template < typename GraphSmall, typename GraphLarge, + typename SubGraphIsoMapCallback > +bool vf2_subgraph_mono(const GraphSmall& graph_small, + const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback) +{ + return vf2_subgraph_mono(graph_small, graph_large, user_callback, + get(vertex_index, graph_small), get(vertex_index, graph_large), + vertex_order_by_mult(graph_small), always_equivalent(), + always_equivalent()); +} + +// Named parameter interface of vf2_subgraph_iso +template < typename GraphSmall, typename GraphLarge, typename VertexOrderSmall, + typename SubGraphIsoMapCallback, typename Param, typename Tag, + typename Rest > +bool vf2_subgraph_mono(const GraphSmall& graph_small, + const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback, + const VertexOrderSmall& vertex_order_small, + const bgl_named_params< Param, Tag, Rest >& params) +{ + return vf2_subgraph_mono(graph_small, graph_large, user_callback, + choose_const_pmap( + get_param(params, vertex_index1), graph_small, vertex_index), + choose_const_pmap( + get_param(params, vertex_index2), graph_large, vertex_index), + vertex_order_small, + choose_param( + get_param(params, edges_equivalent_t()), always_equivalent()), + choose_param( + get_param(params, vertices_equivalent_t()), always_equivalent())); +} + +// Enumerates all graph sub-graph isomorphism mappings between graphs +// graph_small and graph_large. Continues until user_callback returns true or +// the search space has been fully explored. +template < typename GraphSmall, typename GraphLarge, typename IndexMapSmall, + typename IndexMapLarge, typename VertexOrderSmall, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename SubGraphIsoMapCallback > +bool vf2_subgraph_iso(const GraphSmall& graph_small, + const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback, + IndexMapSmall index_map_small, IndexMapLarge index_map_large, + const VertexOrderSmall& vertex_order_small, + EdgeEquivalencePredicate edge_comp, VertexEquivalencePredicate vertex_comp) +{ + return detail::vf2_subgraph_morphism< detail::subgraph_iso >(graph_small, + graph_large, user_callback, index_map_small, index_map_large, + vertex_order_small, edge_comp, vertex_comp); +} + +// All default interface for vf2_subgraph_iso +template < typename GraphSmall, typename GraphLarge, + typename SubGraphIsoMapCallback > +bool vf2_subgraph_iso(const GraphSmall& graph_small, + const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback) +{ + + return vf2_subgraph_iso(graph_small, graph_large, user_callback, + get(vertex_index, graph_small), get(vertex_index, graph_large), + vertex_order_by_mult(graph_small), always_equivalent(), + always_equivalent()); +} + +// Named parameter interface of vf2_subgraph_iso +template < typename GraphSmall, typename GraphLarge, typename VertexOrderSmall, + typename SubGraphIsoMapCallback, typename Param, typename Tag, + typename Rest > +bool vf2_subgraph_iso(const GraphSmall& graph_small, + const GraphLarge& graph_large, SubGraphIsoMapCallback user_callback, + const VertexOrderSmall& vertex_order_small, + const bgl_named_params< Param, Tag, Rest >& params) +{ + + return vf2_subgraph_iso(graph_small, graph_large, user_callback, + choose_const_pmap( + get_param(params, vertex_index1), graph_small, vertex_index), + choose_const_pmap( + get_param(params, vertex_index2), graph_large, vertex_index), + vertex_order_small, + choose_param( + get_param(params, edges_equivalent_t()), always_equivalent()), + choose_param( + get_param(params, vertices_equivalent_t()), always_equivalent())); +} + +// Enumerates all isomorphism mappings between graphs graph1_ and graph2_. +// Continues until user_callback returns true or the search space has been +// fully explored. +template < typename Graph1, typename Graph2, typename IndexMap1, + typename IndexMap2, typename VertexOrder1, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate, + typename GraphIsoMapCallback > +bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, + GraphIsoMapCallback user_callback, IndexMap1 index_map1, + IndexMap2 index_map2, const VertexOrder1& vertex_order1, + EdgeEquivalencePredicate edge_comp, VertexEquivalencePredicate vertex_comp) +{ + + // Graph requirements + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< Graph1 >)); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph1 >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph1 >)); + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< Graph1 >)); + + BOOST_CONCEPT_ASSERT((BidirectionalGraphConcept< Graph2 >)); + BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph2 >)); + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph2 >)); + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< Graph2 >)); + + typedef typename graph_traits< Graph1 >::vertex_descriptor vertex1_type; + typedef typename graph_traits< Graph2 >::vertex_descriptor vertex2_type; + + typedef typename graph_traits< Graph1 >::vertices_size_type size_type1; + typedef typename graph_traits< Graph2 >::vertices_size_type size_type2; + + // Property map requirements + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< IndexMap1, vertex1_type >)); + typedef typename property_traits< IndexMap1 >::value_type IndexMap1Value; + BOOST_STATIC_ASSERT((is_convertible< IndexMap1Value, size_type1 >::value)); + + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< IndexMap2, vertex2_type >)); + typedef typename property_traits< IndexMap2 >::value_type IndexMap2Value; + BOOST_STATIC_ASSERT((is_convertible< IndexMap2Value, size_type2 >::value)); + + // Edge & vertex requirements + typedef typename graph_traits< Graph1 >::edge_descriptor edge1_type; + typedef typename graph_traits< Graph2 >::edge_descriptor edge2_type; + + BOOST_CONCEPT_ASSERT((BinaryPredicateConcept< EdgeEquivalencePredicate, + edge1_type, edge2_type >)); + + BOOST_CONCEPT_ASSERT((BinaryPredicateConcept< VertexEquivalencePredicate, + vertex1_type, vertex2_type >)); + + // Vertex order requirements + BOOST_CONCEPT_ASSERT((ContainerConcept< VertexOrder1 >)); + typedef typename VertexOrder1::value_type order_value_type; + BOOST_STATIC_ASSERT((is_same< vertex1_type, order_value_type >::value)); + BOOST_ASSERT(num_vertices(graph1) == vertex_order1.size()); + + if (num_vertices(graph1) != num_vertices(graph2)) + return false; + + typename graph_traits< Graph1 >::edges_size_type num_edges1 + = num_edges(graph1); + typename graph_traits< Graph2 >::edges_size_type num_edges2 + = num_edges(graph2); + + // Double the number of edges for undirected graphs: each edge counts as + // in-edge and out-edge + if (is_undirected(graph1)) + num_edges1 *= 2; + if (is_undirected(graph2)) + num_edges2 *= 2; + if (num_edges1 != num_edges2) + return false; + + detail::state< Graph1, Graph2, IndexMap1, IndexMap2, + EdgeEquivalencePredicate, VertexEquivalencePredicate, + GraphIsoMapCallback, detail::isomorphism > + s(graph1, graph2, index_map1, index_map2, edge_comp, vertex_comp); + + return detail::match(graph1, graph2, user_callback, vertex_order1, s); +} + +// All default interface for vf2_graph_iso +template < typename Graph1, typename Graph2, typename GraphIsoMapCallback > +bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, + GraphIsoMapCallback user_callback) +{ + + return vf2_graph_iso(graph1, graph2, user_callback, + get(vertex_index, graph1), get(vertex_index, graph2), + vertex_order_by_mult(graph1), always_equivalent(), always_equivalent()); +} + +// Named parameter interface of vf2_graph_iso +template < typename Graph1, typename Graph2, typename VertexOrder1, + typename GraphIsoMapCallback, typename Param, typename Tag, typename Rest > +bool vf2_graph_iso(const Graph1& graph1, const Graph2& graph2, + GraphIsoMapCallback user_callback, const VertexOrder1& vertex_order1, + const bgl_named_params< Param, Tag, Rest >& params) +{ + + return vf2_graph_iso(graph1, graph2, user_callback, + choose_const_pmap( + get_param(params, vertex_index1), graph1, vertex_index), + choose_const_pmap( + get_param(params, vertex_index2), graph2, vertex_index), + vertex_order1, + choose_param( + get_param(params, edges_equivalent_t()), always_equivalent()), + choose_param( + get_param(params, vertices_equivalent_t()), always_equivalent())); +} + +// Verifies a graph (sub)graph isomorphism map +template < typename Graph1, typename Graph2, typename CorresponenceMap1To2, + typename EdgeEquivalencePredicate, typename VertexEquivalencePredicate > +inline bool verify_vf2_subgraph_iso(const Graph1& graph1, const Graph2& graph2, + const CorresponenceMap1To2 f, EdgeEquivalencePredicate edge_comp, + VertexEquivalencePredicate vertex_comp) +{ + + BOOST_CONCEPT_ASSERT((EdgeListGraphConcept< Graph1 >)); + BOOST_CONCEPT_ASSERT((AdjacencyMatrixConcept< Graph2 >)); + + detail::equivalent_edge_exists< Graph2 > edge2_exists; + + BGL_FORALL_EDGES_T(e1, graph1, Graph1) + { + typename graph_traits< Graph1 >::vertex_descriptor s1, t1; + typename graph_traits< Graph2 >::vertex_descriptor s2, t2; + + s1 = source(e1, graph1); + t1 = target(e1, graph1); + s2 = get(f, s1); + t2 = get(f, t1); + + if (!vertex_comp(s1, s2) || !vertex_comp(t1, t2)) + return false; + + typename graph_traits< Graph2 >::edge_descriptor e2; + + if (!edge2_exists(s2, t2, + detail::edge2_predicate< Graph1, Graph2, + EdgeEquivalencePredicate >(edge_comp, e1), + graph2)) + return false; + } + + return true; +} + +// Variant of verify_subgraph_iso with all default parameters +template < typename Graph1, typename Graph2, typename CorresponenceMap1To2 > +inline bool verify_vf2_subgraph_iso( + const Graph1& graph1, const Graph2& graph2, const CorresponenceMap1To2 f) +{ + return verify_vf2_subgraph_iso( + graph1, graph2, f, always_equivalent(), always_equivalent()); +} + +} // namespace boost + +#ifdef BOOST_ISO_INCLUDED_ITER_MACROS +#undef BOOST_ISO_INCLUDED_ITER_MACROS +#include <boost/graph/iteration_macros_undef.hpp> +#endif + +#endif // BOOST_VF2_SUB_GRAPH_ISO_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/wavefront.hpp b/contrib/restricted/boost/graph/include/boost/graph/wavefront.hpp new file mode 100644 index 0000000000..aec2853671 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/wavefront.hpp @@ -0,0 +1,125 @@ +// +//======================================================================= +// Copyright 2002 Marc Wintermantel (wintermantel@even-ag.ch) +// ETH Zurich, Center of Structure Technologies +// (https://web.archive.org/web/20050307090307/http://www.structures.ethz.ch/) +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// + +#ifndef BOOST_GRAPH_WAVEFRONT_HPP +#define BOOST_GRAPH_WAVEFRONT_HPP + +#include <boost/config.hpp> +#include <boost/graph/graph_traits.hpp> +#include <boost/detail/numeric_traits.hpp> +#include <boost/graph/bandwidth.hpp> +#include <boost/config/no_tr1/cmath.hpp> +#include <vector> +#include <algorithm> // for std::min and std::max + +namespace boost +{ + +template < typename Graph, typename VertexIndexMap > +typename graph_traits< Graph >::vertices_size_type ith_wavefront( + typename graph_traits< Graph >::vertex_descriptor i, const Graph& g, + VertexIndexMap index) +{ + typename graph_traits< Graph >::vertex_descriptor v, w; + typename graph_traits< Graph >::vertices_size_type b = 1; + typename graph_traits< Graph >::out_edge_iterator edge_it2, edge_it2_end; + typename graph_traits< Graph >::vertices_size_type index_i = index[i]; + std::vector< bool > rows_active(num_vertices(g), false); + + rows_active[index_i] = true; + + typename graph_traits< Graph >::vertex_iterator ui, ui_end; + for (boost::tie(ui, ui_end) = vertices(g); ui != ui_end; ++ui) + { + v = *ui; + if (index[v] <= index_i) + { + for (boost::tie(edge_it2, edge_it2_end) = out_edges(v, g); + edge_it2 != edge_it2_end; ++edge_it2) + { + w = target(*edge_it2, g); + if ((index[w] >= index_i) && (!rows_active[index[w]])) + { + b++; + rows_active[index[w]] = true; + } + } + } + } + + return b; +} + +template < typename Graph > +typename graph_traits< Graph >::vertices_size_type ith_wavefront( + typename graph_traits< Graph >::vertex_descriptor i, const Graph& g) +{ + return ith_wavefront(i, g, get(vertex_index, g)); +} + +template < typename Graph, typename VertexIndexMap > +typename graph_traits< Graph >::vertices_size_type max_wavefront( + const Graph& g, VertexIndexMap index) +{ + BOOST_USING_STD_MAX(); + typename graph_traits< Graph >::vertices_size_type b = 0; + typename graph_traits< Graph >::vertex_iterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + b = max BOOST_PREVENT_MACRO_SUBSTITUTION( + b, ith_wavefront(*i, g, index)); + return b; +} + +template < typename Graph > +typename graph_traits< Graph >::vertices_size_type max_wavefront(const Graph& g) +{ + return max_wavefront(g, get(vertex_index, g)); +} + +template < typename Graph, typename VertexIndexMap > +double aver_wavefront(const Graph& g, VertexIndexMap index) +{ + double b = 0; + typename graph_traits< Graph >::vertex_iterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + b += ith_wavefront(*i, g, index); + + b /= num_vertices(g); + return b; +} + +template < typename Graph > double aver_wavefront(const Graph& g) +{ + return aver_wavefront(g, get(vertex_index, g)); +} + +template < typename Graph, typename VertexIndexMap > +double rms_wavefront(const Graph& g, VertexIndexMap index) +{ + double b = 0; + typename graph_traits< Graph >::vertex_iterator i, end; + for (boost::tie(i, end) = vertices(g); i != end; ++i) + b += std::pow(double(ith_wavefront(*i, g, index)), 2.0); + + b /= num_vertices(g); + + return std::sqrt(b); +} + +template < typename Graph > double rms_wavefront(const Graph& g) +{ + return rms_wavefront(g, get(vertex_index, g)); +} + +} // namespace boost + +#endif // BOOST_GRAPH_WAVEFRONT_HPP diff --git a/contrib/restricted/boost/graph/include/boost/graph/write_dimacs.hpp b/contrib/restricted/boost/graph/include/boost/graph/write_dimacs.hpp new file mode 100644 index 0000000000..36ab7f81e4 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/graph/write_dimacs.hpp @@ -0,0 +1,75 @@ +// Copyright (c) 2006, Stephan Diederich +// +// This code may be used under either of the following two licences: +// +// Permission is hereby granted, free of charge, to any person +// obtaining a copy of this software and associated documentation +// files (the "Software"), to deal in the Software without +// restriction, including without limitation the rights to use, +// copy, modify, merge, publish, distribute, sublicense, and/or +// sell copies of the Software, and to permit persons to whom the +// Software is furnished to do so, subject to the following +// conditions: +// +// The above copyright notice and this permission notice shall be +// included in all copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +// EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +// OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND +// NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT +// HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, +// WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING +// FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR +// OTHER DEALINGS IN THE SOFTWARE. OF SUCH DAMAGE. +// +// Or: +// +// Distributed under the Boost Software License, Version 1.0. +// (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +/* + Writes maximal flow problem in extended DIMACS format to an OutputIterator + Vertex indices are read from an IndexMap and shiftet by 1. + so their new range is [1..num_vertices(g)] +*/ + +/* ----------------------------------------------------------------- */ + +#include <vector> +#include <string> +#include <ostream> + +#include <boost/graph/graph_traits.hpp> + +namespace boost +{ + +template < class Graph, class CapacityMap, class IndexMap > +void write_dimacs_max_flow(const Graph& g, CapacityMap capacity, IndexMap idx, + typename graph_traits< Graph >::vertex_descriptor src, + typename graph_traits< Graph >::vertex_descriptor sink, std::ostream& out) +{ + typedef typename graph_traits< Graph >::edge_iterator edge_iterator; + + out << "c DIMACS max-flow file generated from boost::write_dimacs_max_flow" + << std::endl; + out << "p max " << num_vertices(g) << " " << num_edges(g) + << std::endl; // print problem description "max" and number of verts and + // edges + out << "n " << get(idx, src) + 1 << " s" << std::endl; + ; // say which one is source + out << "n " << get(idx, sink) + 1 << " t" + << std::endl; // say which one is sink + + // output the edges + edge_iterator ei, e_end; + for (boost::tie(ei, e_end) = edges(g); ei != e_end; ++ei) + { + out << "a " << idx[source(*ei, g)] + 1 << " " << idx[target(*ei, g)] + 1 + << " " << get(capacity, *ei) << std::endl; + } +} + +} // namespace boost diff --git a/contrib/restricted/boost/graph/include/boost/pending/bucket_sorter.hpp b/contrib/restricted/boost/graph/include/boost/pending/bucket_sorter.hpp new file mode 100644 index 0000000000..e39133d435 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/bucket_sorter.hpp @@ -0,0 +1,158 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +// +// Revision History: +// 13 June 2001: Changed some names for clarity. (Jeremy Siek) +// 01 April 2001: Modified to use new <boost/limits.hpp> header. (JMaddock) +// +#ifndef BOOST_GRAPH_DETAIL_BUCKET_SORTER_HPP +#define BOOST_GRAPH_DETAIL_BUCKET_SORTER_HPP + +#include <vector> +#include <cassert> +#include <boost/limits.hpp> +#include <boost/concept/assert.hpp> +#include <boost/property_map/property_map.hpp> + +namespace boost +{ + +template < class BucketType, class ValueType, class Bucket, + class ValueIndexMap > +class bucket_sorter +{ + BOOST_CONCEPT_ASSERT( + (ReadablePropertyMapConcept< ValueIndexMap, ValueType >)); + +public: + typedef BucketType bucket_type; + typedef ValueType value_type; + typedef typename std::vector< value_type >::size_type size_type; + + bucket_sorter(size_type _length, bucket_type _max_bucket, + const Bucket& _bucket = Bucket(), + const ValueIndexMap& _id = ValueIndexMap()) + : head(_max_bucket, invalid_value()) + , next(_length, invalid_value()) + , prev(_length, invalid_value()) + , id_to_value(_length) + , bucket(_bucket) + , id(_id) + { + } + + void remove(const value_type& x) + { + const size_type i = get(id, x); + const size_type& next_node = next[i]; + const size_type& prev_node = prev[i]; + + // check if i is the end of the bucket list + if (next_node != invalid_value()) + prev[next_node] = prev_node; + // check if i is the begin of the bucket list + if (prev_node != invalid_value()) + next[prev_node] = next_node; + else // need update head of current bucket list + head[bucket[x]] = next_node; + } + + void push(const value_type& x) + { + id_to_value[get(id, x)] = x; + (*this)[bucket[x]].push(x); + } + + void update(const value_type& x) + { + remove(x); + (*this)[bucket[x]].push(x); + } + // private: + // with KCC, the nested stack class is having access problems + // despite the friend decl. + static size_type invalid_value() + { + return (std::numeric_limits< size_type >::max)(); + } + + typedef typename std::vector< size_type >::iterator Iter; + typedef typename std::vector< value_type >::iterator IndexValueMap; + +public: + friend class stack; + + class stack + { + public: + stack(bucket_type _bucket_id, Iter h, Iter n, Iter p, IndexValueMap v, + const ValueIndexMap& _id) + : bucket_id(_bucket_id), head(h), next(n), prev(p), value(v), id(_id) + { + } + + // Avoid using default arg for ValueIndexMap so that the default + // constructor of the ValueIndexMap is not required if not used. + stack(bucket_type _bucket_id, Iter h, Iter n, Iter p, IndexValueMap v) + : bucket_id(_bucket_id), head(h), next(n), prev(p), value(v) + { + } + + void push(const value_type& x) + { + const size_type new_head = get(id, x); + const size_type current = head[bucket_id]; + if (current != invalid_value()) + prev[current] = new_head; + prev[new_head] = invalid_value(); + next[new_head] = current; + head[bucket_id] = new_head; + } + void pop() + { + size_type current = head[bucket_id]; + size_type next_node = next[current]; + head[bucket_id] = next_node; + if (next_node != invalid_value()) + prev[next_node] = invalid_value(); + } + value_type& top() { return value[head[bucket_id]]; } + const value_type& top() const { return value[head[bucket_id]]; } + bool empty() const { return head[bucket_id] == invalid_value(); } + + private: + bucket_type bucket_id; + Iter head; + Iter next; + Iter prev; + IndexValueMap value; + ValueIndexMap id; + }; + + stack operator[](const bucket_type& i) + { + assert(i < head.size()); + return stack(i, head.begin(), next.begin(), prev.begin(), + id_to_value.begin(), id); + } + +protected: + std::vector< size_type > head; + std::vector< size_type > next; + std::vector< size_type > prev; + std::vector< value_type > id_to_value; + Bucket bucket; + ValueIndexMap id; +}; + +} + +#endif diff --git a/contrib/restricted/boost/graph/include/boost/pending/detail/disjoint_sets.hpp b/contrib/restricted/boost/graph/include/boost/pending/detail/disjoint_sets.hpp new file mode 100644 index 0000000000..9a91b294b4 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/detail/disjoint_sets.hpp @@ -0,0 +1,93 @@ +// (C) Copyright Jeremy Siek 2004 +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_DETAIL_DISJOINT_SETS_HPP +#define BOOST_DETAIL_DISJOINT_SETS_HPP + +#include <cassert> + +namespace boost +{ + +namespace detail +{ + + template < class ParentPA, class Vertex > + Vertex find_representative_with_path_halving(ParentPA p, Vertex v) + { + Vertex parent = get(p, v); + Vertex grandparent = get(p, parent); + while (parent != grandparent) + { + put(p, v, grandparent); + v = grandparent; + parent = get(p, v); + grandparent = get(p, parent); + } + return parent; + } + + template < class ParentPA, class Vertex > + Vertex find_representative_with_full_compression(ParentPA parent, Vertex v) + { + Vertex old = v; + Vertex ancestor = get(parent, v); + while (ancestor != v) + { + v = ancestor; + ancestor = get(parent, v); + } + v = get(parent, old); + while (ancestor != v) + { + put(parent, old, ancestor); + old = v; + v = get(parent, old); + } + return ancestor; + } + + /* the postcondition of link sets is: + component_representative(i) == component_representative(j) + */ + template < class ParentPA, class RankPA, class Vertex> + inline void link_sets(ParentPA p, RankPA rank, Vertex i, Vertex j) + { + assert(i == get(p, i)); + assert(j == get(p, j)); + if (i == j) + return; + if (get(rank, i) > get(rank, j)) + put(p, j, i); + else + { + put(p, i, j); + if (get(rank, i) == get(rank, j)) + put(rank, j, get(rank, j) + 1); + } + } + + // normalize components has the following postcondidition: + // i >= p[i] + // that is, the representative is the node with the smallest index in its + // class as its precondition it it assumes that the node container is + // compressed + + template < class ParentPA, class Vertex > + inline void normalize_node(ParentPA p, Vertex i) + { + if (i > get(p, i) || get(p, get(p, i)) != get(p, i)) + put(p, i, get(p, get(p, i))); + else + { + put(p, get(p, i), i); + put(p, i, i); + } + } + +} // namespace detail +} // namespace boost + +#endif // BOOST_DETAIL_DISJOINT_SETS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/pending/disjoint_sets.hpp b/contrib/restricted/boost/graph/include/boost/pending/disjoint_sets.hpp new file mode 100644 index 0000000000..28bf3c3c3b --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/disjoint_sets.hpp @@ -0,0 +1,211 @@ +// +//======================================================================= +// Copyright 1997, 1998, 1999, 2000 University of Notre Dame. +// Authors: Andrew Lumsdaine, Lie-Quan Lee, Jeremy G. Siek +// +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +//======================================================================= +// +#ifndef BOOST_DISJOINT_SETS_HPP +#define BOOST_DISJOINT_SETS_HPP + +#include <vector> +#include <boost/graph/properties.hpp> +#include <boost/pending/detail/disjoint_sets.hpp> + +namespace boost +{ + +struct find_with_path_halving +{ + template < class ParentPA, class Vertex > + Vertex operator()(ParentPA p, Vertex v) + { + return detail::find_representative_with_path_halving(p, v); + } +}; + +struct find_with_full_path_compression +{ + template < class ParentPA, class Vertex > + Vertex operator()(ParentPA p, Vertex v) + { + return detail::find_representative_with_full_compression(p, v); + } +}; + +// This is a generalized functor to provide disjoint sets operations +// with "union by rank" and "path compression". A disjoint-set data +// structure maintains a collection S={S1, S2, ..., Sk} of disjoint +// sets. Each set is identified by a representative, which is some +// member of of the set. Sets are represented by rooted trees. Two +// heuristics: "union by rank" and "path compression" are used to +// speed up the operations. + +// Disjoint Set requires two vertex properties for internal use. A +// RankPA and a ParentPA. The RankPA must map Vertex to some Integral type +// (preferably the size_type associated with Vertex). The ParentPA +// must map Vertex to Vertex. +template < class RankPA, class ParentPA, + class FindCompress = find_with_full_path_compression > +class disjoint_sets +{ + typedef disjoint_sets self; + + inline disjoint_sets() {} + +public: + inline disjoint_sets(RankPA r, ParentPA p) : rank(r), parent(p) {} + + inline disjoint_sets(const self& c) : rank(c.rank), parent(c.parent) {} + + // Make Set -- Create a singleton set containing vertex x + template < class Element > inline void make_set(Element x) + { + put(parent, x, x); + typedef typename property_traits< RankPA >::value_type R; + put(rank, x, R()); + } + + // Link - union the two sets represented by vertex x and y + template < class Element > inline void link(Element x, Element y) + { + detail::link_sets(parent, rank, x, y); + } + + // Union-Set - union the two sets containing vertex x and y + template < class Element > inline void union_set(Element x, Element y) + { + link(find_set(x), find_set(y)); + } + + // Find-Set - returns the Element representative of the set + // containing Element x and applies path compression. + template < class Element > inline Element find_set(Element x) + { + return rep(parent, x); + } + + template < class ElementIterator > + inline std::size_t count_sets(ElementIterator first, ElementIterator last) + { + std::size_t count = 0; + for (; first != last; ++first) + if (get(parent, *first) == *first) + ++count; + return count; + } + + template < class ElementIterator > + inline void normalize_sets(ElementIterator first, ElementIterator last) + { + for (; first != last; ++first) + detail::normalize_node(parent, *first); + } + + template < class ElementIterator > + inline void compress_sets(ElementIterator first, ElementIterator last) + { + for (; first != last; ++first) + detail::find_representative_with_full_compression(parent, *first); + } + +protected: + RankPA rank; + ParentPA parent; + FindCompress rep; +}; + +template < class ID = identity_property_map, + class InverseID = identity_property_map, + class FindCompress = find_with_full_path_compression > +class disjoint_sets_with_storage +{ + typedef typename property_traits< ID >::value_type Index; + typedef std::vector< Index > ParentContainer; + typedef std::vector< unsigned char > RankContainer; + +public: + typedef typename ParentContainer::size_type size_type; + + disjoint_sets_with_storage( + size_type n = 0, ID id_ = ID(), InverseID inv = InverseID()) + : id(id_), id_to_vertex(inv), rank(n, 0), parent(n) + { + for (Index i = 0; i < n; ++i) + parent[i] = i; + } + // note this is not normally needed + template < class Element > inline void make_set(Element x) + { + parent[x] = x; + rank[x] = 0; + } + template < class Element > inline void link(Element x, Element y) + { + extend_sets(x, y); + detail::link_sets(&parent[0], &rank[0], get(id, x), get(id, y)); + } + template < class Element > inline void union_set(Element x, Element y) + { + Element rx = find_set(x); + Element ry = find_set(y); + link(rx, ry); + } + template < class Element > inline Element find_set(Element x) + { + return id_to_vertex[rep(&parent[0], get(id, x))]; + } + + template < class ElementIterator > + inline std::size_t count_sets(ElementIterator first, ElementIterator last) + { + std::size_t count = 0; + for (; first != last; ++first) + if (parent[*first] == *first) + ++count; + return count; + } + + template < class ElementIterator > + inline void normalize_sets(ElementIterator first, ElementIterator last) + { + for (; first != last; ++first) + detail::normalize_node(&parent[0], *first); + } + + template < class ElementIterator > + inline void compress_sets(ElementIterator first, ElementIterator last) + { + for (; first != last; ++first) + detail::find_representative_with_full_compression( + &parent[0], *first); + } + + const ParentContainer& parents() { return parent; } + +protected: + template < class Element > inline void extend_sets(Element x, Element y) + { + Index needed + = get(id, x) > get(id, y) ? get(id, x) + 1 : get(id, y) + 1; + if (needed > parent.size()) + { + rank.insert(rank.end(), needed - rank.size(), 0); + for (Index k = parent.size(); k < needed; ++k) + parent.push_back(k); + } + } + + ID id; + InverseID id_to_vertex; + RankContainer rank; + ParentContainer parent; + FindCompress rep; +}; + +} // namespace boost + +#endif // BOOST_DISJOINT_SETS_HPP diff --git a/contrib/restricted/boost/graph/include/boost/pending/fenced_priority_queue.hpp b/contrib/restricted/boost/graph/include/boost/pending/fenced_priority_queue.hpp new file mode 100644 index 0000000000..64d18692b9 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/fenced_priority_queue.hpp @@ -0,0 +1,160 @@ +// (C) Copyright Jeremiah Willcock 2004 +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_FENCED_PRIORITY_QUEUE_HPP +#define BOOST_FENCED_PRIORITY_QUEUE_HPP + +#include <vector> +#include <queue> +#include <functional> +#include <boost/pending/queue.hpp> + +// Fenced priority queue +// Jeremiah Willcock + +// This class implements a fenced priority queue. This is similar to +// a normal priority queue (sorts its members, and only returns the +// first), except that members cannot be sorted around a "fence" that +// can be placed into the buffer. This fence is inserted using the +// fence() member function or (possibly) implicitly by the top() and +// pop() methods, and is removed automatically when the elements +// around it are popped. + +// The implementation is as follows: Q is an unsorted queue that +// contains the already-sorted list data, and PQ is a priority queue +// that contains new elements (since the last fence) that have yet to +// be sorted. New elements are inserted into PQ, and a fence moves +// all elements in PQ into the back of Q in sorted order. Elements +// are then popped from the front of Q, and if that is empty the front +// of PQ. + +namespace boost +{ + +template < class T, class Compare = std::less< T >, bool implicit_fence = true, + class Buffer = boost::queue< T > > +class fenced_priority_queue +{ +public: + typedef T value_type; + typedef typename Buffer::size_type size_type; + + fenced_priority_queue(const Compare _comp = Compare()) : PQ(_comp) {} + + void push(const T& data); + void pop(void); + T& top(void); + const T& top(void) const; + size_type size(void) const; + bool empty(void) const; + void fence(void); + +private: + void fence(void) const; + + // let them mutable to allow const version of top and the same + // semantics with non-constant version. Rich Lee + mutable std::priority_queue< T, std::vector< T >, Compare > PQ; + mutable Buffer Q; +}; + +template < class T, class Compare, bool implicit_fence, class Buffer > +inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::push( + const T& t) +{ + // Push a new element after the last fence. This puts it into the + // priority queue to be sorted with all other elements in its + // partition. + PQ.push(t); +} + +template < class T, class Compare, bool implicit_fence, class Buffer > +inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::pop( + void) +{ + // Pop one element from the front of the queue. Removes from the + // already-sorted part of the queue if it is non-empty, otherwise + // removes from the new-element priority queue. Runs an implicit + // "fence" operation if the implicit_fence template argument is + // true. + if (implicit_fence) + fence(); + if (!Q.empty()) + Q.pop(); + else + PQ.pop(); +} + +template < class T, class Compare, bool implicit_fence, class Buffer > +inline T& fenced_priority_queue< T, Compare, implicit_fence, Buffer >::top(void) +{ + // Get the top element from the queue. This element comes from Q if + // possible, otherwise from PQ. Causes an implicit "fence" + // operation if the implicit_fence template argument is true. + if (implicit_fence) + fence(); + if (!Q.empty()) + return Q.top(); + else + // std::priority_queue only have const version of top. Rich Lee + return const_cast< T& >(PQ.top()); +} + +template < class T, class Compare, bool implicit_fence, class Buffer > +inline const T& +fenced_priority_queue< T, Compare, implicit_fence, Buffer >::top(void) const +{ + if (implicit_fence) + fence(); + if (!Q.empty()) + return Q.top(); + else + return PQ.top(); +} + +template < class T, class Compare, bool implicit_fence, class Buffer > +inline typename fenced_priority_queue< T, Compare, implicit_fence, + Buffer >::size_type +fenced_priority_queue< T, Compare, implicit_fence, Buffer >::size(void) const +{ + // Returns the size of the queue (both parts together). + return Q.size() + PQ.size(); +} + +template < class T, class Compare, bool implicit_fence, class Buffer > +inline bool fenced_priority_queue< T, Compare, implicit_fence, Buffer >::empty( + void) const +{ + // Returns if the queue is empty, i.e. both parts are empty. + return Q.empty() && PQ.empty(); +} + +template < class T, class Compare, bool implicit_fence, class Buffer > +inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::fence( + void) +{ + // Perform a fence operation. Remove elements from PQ in sorted + // order and insert them in the back of Q. + while (!PQ.empty()) + { + Q.push(PQ.top()); + PQ.pop(); + } +} +template < class T, class Compare, bool implicit_fence, class Buffer > +inline void fenced_priority_queue< T, Compare, implicit_fence, Buffer >::fence( + void) const +{ + // Perform a fence operation. Remove elements from PQ in sorted + // order and insert them in the back of Q. + while (!PQ.empty()) + { + Q.push(PQ.top()); + PQ.pop(); + } +} + +} +#endif /* BOOST_FENCED_PRIORITY_QUEUE_HPP */ diff --git a/contrib/restricted/boost/graph/include/boost/pending/fibonacci_heap.hpp b/contrib/restricted/boost/graph/include/boost/pending/fibonacci_heap.hpp new file mode 100644 index 0000000000..3be462369e --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/fibonacci_heap.hpp @@ -0,0 +1,320 @@ +// (C) Copyright Jeremy Siek 2004. +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) +#ifndef BOOST_FIBONACCI_HEAP_HPP +#define BOOST_FIBONACCI_HEAP_HPP + +#if defined(__sgi) && !defined(__GNUC__) +#include <math.h> +#else +#include <boost/config/no_tr1/cmath.hpp> +#endif +#include <iosfwd> +#include <vector> +#include <functional> +#include <boost/config.hpp> +#include <boost/property_map/property_map.hpp> + +// +// An adaptation of Knuth's Fibonacci heap implementation +// in "The Stanford Graph Base", pages 475-482. +// + +namespace boost +{ + +template < class T, class Compare = std::less< T >, + class ID = identity_property_map > +class fibonacci_heap +{ + typedef typename boost::property_traits< ID >::value_type size_type; + typedef T value_type; + +protected: + typedef fibonacci_heap self; + typedef std::vector< size_type > LinkVec; + typedef typename LinkVec::iterator LinkIter; + +public: + fibonacci_heap( + size_type n, const Compare& cmp, const ID& id = identity_property_map()) + : _key(n) + , _left(n) + , _right(n) + , _p(n) + , _mark(n) + , _degree(n) + , _n(0) + , _root(n) + , _id(id) + , _compare(cmp) + , _child(n) + , +#if defined(BOOST_MSVC) || defined(__ICL) // need a new macro? + new_roots(size_type(log(float(n))) + 5) + { + } +#else + new_roots(size_type(std::log(float(n))) + 5) + { + } +#endif + + // 33 + void push(const T& d) + { + ++_n; + size_type v = get(_id, d); + _key[v] = d; + _p[v] = nil(); + _degree[v] = 0; + _mark[v] = false; + _child[v] = nil(); + if (_root == nil()) + { + _root = _left[v] = _right[v] = v; + // std::cout << "root added" << std::endl; + } + else + { + size_type u = _left[_root]; + _left[v] = u; + _right[v] = _root; + _left[_root] = _right[u] = v; + if (_compare(d, _key[_root])) + _root = v; + // std::cout << "non-root node added" << std::endl; + } + } + T& top() { return _key[_root]; } + const T& top() const { return _key[_root]; } + + // 38 + void pop() + { + --_n; + int h = -1; + size_type v, w; + if (_root != nil()) + { + if (_degree[_root] == 0) + { + v = _right[_root]; + } + else + { + w = _child[_root]; + v = _right[w]; + _right[w] = _right[_root]; + for (w = v; w != _right[_root]; w = _right[w]) + _p[w] = nil(); + } + while (v != _root) + { + w = _right[v]; + add_tree_to_new_roots(v, new_roots.begin(), h); + v = w; + } + rebuild_root_list(new_roots.begin(), h); + } + } + // 39 + inline void add_tree_to_new_roots(size_type v, LinkIter new_roots, int& h) + { + int r; + size_type u; + r = _degree[v]; + while (1) + { + if (h < r) + { + do + { + ++h; + new_roots[h] = (h == r ? v : nil()); + } while (h < r); + break; + } + if (new_roots[r] == nil()) + { + new_roots[r] = v; + break; + } + u = new_roots[r]; + new_roots[r] = nil(); + if (_compare(_key[u], _key[v])) + { + _degree[v] = r; + _mark[v] = false; + std::swap(u, v); + } + make_child(u, v, r); + ++r; + } + _degree[v] = r; + _mark[v] = false; + } + // 40 + void make_child(size_type u, size_type v, size_type r) + { + if (r == 0) + { + _child[v] = u; + _left[u] = u; + _right[u] = u; + } + else + { + size_type t = _child[v]; + _right[u] = _right[t]; + _left[u] = t; + _right[t] = u; + _left[_right[u]] = u; + } + _p[u] = v; + } + // 41 + inline void rebuild_root_list(LinkIter new_roots, int& h) + { + size_type u, v, w; + if (h < 0) + _root = nil(); + else + { + T d; + u = v = new_roots[h]; + d = _key[u]; + _root = u; + for (h--; h >= 0; --h) + if (new_roots[h] != nil()) + { + w = new_roots[h]; + _left[w] = v; + _right[v] = w; + if (_compare(_key[w], d)) + { + _root = w; + d = _key[w]; + } + v = w; + } + _right[v] = u; + _left[u] = v; + } + } + + // 34 + void update(const T& d) + { + size_type v = get(_id, d); + assert(!_compare(_key[v], d)); + _key[v] = d; + size_type p = _p[v]; + if (p == nil()) + { + if (_compare(d, _key[_root])) + _root = v; + } + else if (_compare(d, _key[p])) + while (1) + { + size_type r = _degree[p]; + if (r >= 2) + remove_from_family(v, p); + insert_into_forest(v, d); + size_type pp = _p[p]; + if (pp == nil()) + { + --_degree[p]; + break; + } + if (_mark[p] == false) + { + _mark[p] = true; + --_degree[p]; + break; + } + else + --_degree[p]; + v = p; + p = pp; + } + } + + inline size_type size() const { return _n; } + inline bool empty() const { return _n == 0; } + + void print(std::ostream& os) + { + if (_root != nil()) + { + size_type i = _root; + do + { + print_recur(i, os); + os << std::endl; + i = _right[i]; + } while (i != _root); + } + } + +protected: + // 35 + inline void remove_from_family(size_type v, size_type p) + { + size_type u = _left[v]; + size_type w = _right[v]; + _right[u] = w; + _left[w] = u; + if (_child[p] == v) + _child[p] = w; + } + // 36 + inline void insert_into_forest(size_type v, const T& d) + { + _p[v] = nil(); + size_type u = _left[_root]; + _left[v] = u; + _right[v] = _root; + _left[_root] = _right[u] = v; + if (_compare(d, _key[_root])) + _root = v; + } + + void print_recur(size_type x, std::ostream& os) + { + if (x != nil()) + { + os << x; + if (_degree[x] > 0) + { + os << "("; + size_type i = _child[x]; + do + { + print_recur(i, os); + os << " "; + i = _right[i]; + } while (i != _child[x]); + os << ")"; + } + } + } + + size_type nil() const { return _left.size(); } + + std::vector< T > _key; + LinkVec _left, _right, _p; + std::vector< bool > _mark; + LinkVec _degree; + size_type _n, _root; + ID _id; + Compare _compare; + LinkVec _child; + LinkVec new_roots; +}; + +} // namespace boost + +#endif // BOOST_FIBONACCI_HEAP_HPP diff --git a/contrib/restricted/boost/graph/include/boost/pending/property_serialize.hpp b/contrib/restricted/boost/graph/include/boost/pending/property_serialize.hpp new file mode 100644 index 0000000000..cbdc163a4f --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/property_serialize.hpp @@ -0,0 +1,99 @@ +// (C) Copyright Jeremy Siek 2006 +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_PROPERTY_SERIALIZE_HPP +#define BOOST_PROPERTY_SERIALIZE_HPP + +#include <boost/pending/property.hpp> +#include <boost/serialization/is_bitwise_serializable.hpp> +#include <boost/serialization/base_object.hpp> +#include <boost/serialization/nvp.hpp> + +namespace boost +{ +template < class Archive > +inline void serialize(Archive&, no_property&, const unsigned int) +{ +} + +template < class Archive, class Tag, class T, class Base > +void serialize( + Archive& ar, property< Tag, T, Base >& prop, const unsigned int /*version*/) +{ + ar& serialization::make_nvp("property_value", prop.m_value); + ar& serialization::make_nvp("property_base", prop.m_base); +} + +#ifdef BOOST_GRAPH_USE_MPI + +// Setting the serialization properties of boost::property<> and +// boost::no_property to is_bitwise_serializable, object_serializable, +// track_never only when BOOST_GRAPH_USE_MPI is defined is dubious. +// +// This changes the serialization format of these classes, and hence +// of boost::adjacency_list, depending on whether BOOST_GRAPH_USE_MPI +// is defined. +// +// These serialization properties should probably be set in either case. +// +// Unfortunately, doing that now will change the serialization format +// of boost::adjacency_list in the non-MPI case, and could potentially +// break software that reads files serialized with an older release. + +namespace mpi +{ + + // forward declaration, to avoid including mpi + template < typename T > struct is_mpi_datatype; + + template < typename Tag, typename T, typename Base > + struct is_mpi_datatype< property< Tag, T, Base > > + : mpl::and_< is_mpi_datatype< T >, is_mpi_datatype< Base > > + { + }; +} + +namespace serialization +{ + template < typename Tag, typename T, typename Base > + struct is_bitwise_serializable< property< Tag, T, Base > > + : mpl::and_< is_bitwise_serializable< T >, is_bitwise_serializable< Base > > + { + }; + + template < typename Tag, typename T, typename Base > + struct implementation_level< property< Tag, T, Base > > + : mpl::int_< object_serializable > + { + }; + + template < typename Tag, typename T, typename Base > + struct tracking_level< property< Tag, T, Base > > : mpl::int_< track_never > + { + }; + +} +#endif // BOOST_GRAPH_USE_MPI + +} // end namespace boost + +#ifdef BOOST_GRAPH_USE_MPI +namespace boost +{ +namespace mpi +{ + template <> struct is_mpi_datatype< boost::no_property > : mpl::true_ + { + }; + +} +} // end namespace boost::mpi + +BOOST_IS_BITWISE_SERIALIZABLE(boost::no_property) +BOOST_CLASS_IMPLEMENTATION(boost::no_property, object_serializable) +BOOST_CLASS_TRACKING(boost::no_property, track_never) +#endif // BOOST_GRAPH_USE_MPI + +#endif // BOOST_PROPERTY_SERIALIZE_HPP diff --git a/contrib/restricted/boost/graph/include/boost/pending/relaxed_heap.hpp b/contrib/restricted/boost/graph/include/boost/pending/relaxed_heap.hpp new file mode 100644 index 0000000000..d7747d4d75 --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/relaxed_heap.hpp @@ -0,0 +1,743 @@ +// Copyright 2004 The Trustees of Indiana University. + +// Use, modification and distribution is subject to the Boost Software +// License, Version 1.0. (See accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +// Authors: Douglas Gregor +// Andrew Lumsdaine + +#ifndef BOOST_RELAXED_HEAP_HEADER +#define BOOST_RELAXED_HEAP_HEADER + +#include <boost/config/header_deprecated.hpp> +BOOST_HEADER_DEPRECATED("the standard heap functions") + +#include <functional> +#include <boost/property_map/property_map.hpp> +#include <boost/optional.hpp> +#include <vector> +#include <climits> // for CHAR_BIT +#include <boost/none.hpp> + +#ifdef BOOST_RELAXED_HEAP_DEBUG +#include <iostream> +#endif // BOOST_RELAXED_HEAP_DEBUG + +#if defined(BOOST_MSVC) +#pragma warning(push) +#pragma warning(disable : 4355) // complaint about using 'this' to +#endif // initialize a member + +namespace boost +{ + +template < typename IndexedType, typename Compare = std::less< IndexedType >, + typename ID = identity_property_map > +class relaxed_heap +{ + struct group; + + typedef relaxed_heap self_type; + typedef std::size_t rank_type; + +public: + typedef IndexedType value_type; + typedef rank_type size_type; + +private: + /** + * The kind of key that a group has. The actual values are discussed + * in-depth in the documentation of the @c kind field of the @c group + * structure. Note that the order of the enumerators *IS* important + * and must not be changed. + */ + enum group_key_kind + { + smallest_key, + stored_key, + largest_key + }; + + struct group + { + explicit group(group_key_kind kind = largest_key) + : kind(kind), parent(this), rank(0) + { + } + + /** The value associated with this group. This value is only valid + * when @c kind!=largest_key (which indicates a deleted + * element). Note that the use of boost::optional increases the + * memory requirements slightly but does not result in extraneous + * memory allocations or deallocations. The optional could be + * eliminated when @c value_type is a model of + * DefaultConstructible. + */ + ::boost::optional< value_type > value; + + /** + * The kind of key stored at this group. This may be @c + * smallest_key, which indicates that the key is infinitely small; + * @c largest_key, which indicates that the key is infinitely + * large; or @c stored_key, which means that the key is unknown, + * but its relationship to other keys can be determined via the + * comparison function object. + */ + group_key_kind kind; + + /// The parent of this group. Will only be NULL for the dummy root group + group* parent; + + /// The rank of this group. Equivalent to the number of children in + /// the group. + rank_type rank; + + /** The children of this group. For the dummy root group, these are + * the roots. This is an array of length log n containing pointers + * to the child groups. + */ + group** children; + }; + + size_type log_base_2(size_type n) // log2 is a macro on some platforms + { + size_type leading_zeroes = 0; + do + { + size_type next = n << 1; + if (n == (next >> 1)) + { + ++leading_zeroes; + n = next; + } + else + { + break; + } + } while (true); + return sizeof(size_type) * CHAR_BIT - leading_zeroes - 1; + } + +public: + relaxed_heap( + size_type n, const Compare& compare = Compare(), const ID& id = ID()) + : compare(compare), id(id), root(smallest_key), groups(n), smallest_value(0) + { + if (n == 0) + { + root.children = new group*[1]; + return; + } + + log_n = log_base_2(n); + if (log_n == 0) + log_n = 1; + size_type g = n / log_n; + if (n % log_n > 0) + ++g; + size_type log_g = log_base_2(g); + size_type r = log_g; + + // Reserve an appropriate amount of space for data structures, so + // that we do not need to expand them. + index_to_group.resize(g); + A.resize(r + 1, 0); + root.rank = r + 1; + root.children = new group*[(log_g + 1) * (g + 1)]; + for (rank_type i = 0; i < r + 1; ++i) + root.children[i] = 0; + + // Build initial heap + size_type idx = 0; + while (idx < g) + { + root.children[r] = &index_to_group[idx]; + idx = build_tree(root, idx, r, log_g + 1); + if (idx != g) + r = static_cast< size_type >(log_base_2(g - idx)); + } + } + + ~relaxed_heap() { delete[] root.children; } + + void push(const value_type& x) + { + groups[get(id, x)] = x; + update(x); + } + + void update(const value_type& x) + { + group* a = &index_to_group[get(id, x) / log_n]; + if (!a->value || *a->value == x || compare(x, *a->value)) + { + if (a != smallest_value) + smallest_value = 0; + a->kind = stored_key; + a->value = x; + promote(a); + } + } + + void remove(const value_type& x) + { + group* a = &index_to_group[get(id, x) / log_n]; + assert(groups[get(id, x)]); + a->value = x; + a->kind = smallest_key; + promote(a); + smallest_value = a; + pop(); + } + + value_type& top() + { + find_smallest(); + assert(smallest_value->value != none); + return *smallest_value->value; + } + + const value_type& top() const + { + find_smallest(); + assert(smallest_value->value != none); + return *smallest_value->value; + } + + bool empty() const + { + find_smallest(); + return !smallest_value || (smallest_value->kind == largest_key); + } + + bool contains(const value_type& x) const + { + return static_cast< bool >(groups[get(id, x)]); + } + + void pop() + { + // Fill in smallest_value. This is the group x. + find_smallest(); + group* x = smallest_value; + smallest_value = 0; + + // Make x a leaf, giving it the smallest value within its group + rank_type r = x->rank; + group* p = x->parent; + { + assert(x->value != none); + + // Find x's group + size_type start = get(id, *x->value) - get(id, *x->value) % log_n; + size_type end = start + log_n; + if (end > groups.size()) + end = groups.size(); + + // Remove the smallest value from the group, and find the new + // smallest value. + groups[get(id, *x->value)].reset(); + x->value.reset(); + x->kind = largest_key; + for (size_type i = start; i < end; ++i) + { + if (groups[i] && (!x->value || compare(*groups[i], *x->value))) + { + x->kind = stored_key; + x->value = groups[i]; + } + } + } + x->rank = 0; + + // Combine prior children of x with x + group* y = x; + for (size_type c = 0; c < r; ++c) + { + group* child = x->children[c]; + if (A[c] == child) + A[c] = 0; + y = combine(y, child); + } + + // If we got back something other than x, let y take x's place + if (y != x) + { + y->parent = p; + p->children[r] = y; + + assert(r == y->rank); + if (A[y->rank] == x) + A[y->rank] = do_compare(y, p) ? y : 0; + } + } + +#ifdef BOOST_RELAXED_HEAP_DEBUG + /************************************************************************* + * Debugging support * + *************************************************************************/ + void dump_tree() { dump_tree(std::cout); } + void dump_tree(std::ostream& out) { dump_tree(out, &root); } + + void dump_tree(std::ostream& out, group* p, bool in_progress = false) + { + if (!in_progress) + { + out << "digraph heap {\n" + << " edge[dir=\"back\"];\n"; + } + + size_type p_index = 0; + if (p != &root) + while (&index_to_group[p_index] != p) + ++p_index; + + for (size_type i = 0; i < p->rank; ++i) + { + group* c = p->children[i]; + if (c) + { + size_type c_index = 0; + if (c != &root) + while (&index_to_group[c_index] != c) + ++c_index; + + out << " "; + if (p == &root) + out << 'p'; + else + out << p_index; + out << " -> "; + if (c == &root) + out << 'p'; + else + out << c_index; + if (A[c->rank] == c) + out << " [style=\"dotted\"]"; + out << ";\n"; + dump_tree(out, c, true); + + // Emit node information + out << " "; + if (c == &root) + out << 'p'; + else + out << c_index; + out << " [label=\""; + if (c == &root) + out << 'p'; + else + out << c_index; + out << ":"; + size_type start = c_index * log_n; + size_type end = start + log_n; + if (end > groups.size()) + end = groups.size(); + while (start != end) + { + if (groups[start]) + { + out << " " << get(id, *groups[start]); + if (*groups[start] == *c->value) + out << "(*)"; + } + ++start; + } + out << '"'; + + if (do_compare(c, p)) + { + out << " "; + if (c == &root) + out << 'p'; + else + out << c_index; + out << ", style=\"filled\", fillcolor=\"gray\""; + } + out << "];\n"; + } + else + { + assert(p->parent == p); + } + } + if (!in_progress) + out << "}\n"; + } + + bool valid() + { + // Check that the ranks in the A array match the ranks of the + // groups stored there. Also, the active groups must be the last + // child of their parent. + for (size_type r = 0; r < A.size(); ++r) + { + if (A[r] && A[r]->rank != r) + return false; + + if (A[r] && A[r]->parent->children[A[r]->parent->rank - 1] != A[r]) + return false; + } + + // The root must have no value and a key of -Infinity + if (root.kind != smallest_key) + return false; + + return valid(&root); + } + + bool valid(group* p) + { + for (size_type i = 0; i < p->rank; ++i) + { + group* c = p->children[i]; + if (c) + { + // Check link structure + if (c->parent != p) + return false; + if (c->rank != i) + return false; + + // A bad group must be active + if (do_compare(c, p) && A[i] != c) + return false; + + // Check recursively + if (!valid(c)) + return false; + } + else + { + // Only the root may + if (p != &root) + return false; + } + } + return true; + } + +#endif // BOOST_RELAXED_HEAP_DEBUG + +private: + size_type build_tree( + group& parent, size_type idx, size_type r, size_type max_rank) + { + group& this_group = index_to_group[idx]; + this_group.parent = &parent; + ++idx; + + this_group.children = root.children + (idx * max_rank); + this_group.rank = r; + for (size_type i = 0; i < r; ++i) + { + this_group.children[i] = &index_to_group[idx]; + idx = build_tree(this_group, idx, i, max_rank); + } + return idx; + } + + void find_smallest() const + { + group** roots = root.children; + + if (!smallest_value) + { + std::size_t i; + for (i = 0; i < root.rank; ++i) + { + if (roots[i] + && (!smallest_value + || do_compare(roots[i], smallest_value))) + { + smallest_value = roots[i]; + } + } + for (i = 0; i < A.size(); ++i) + { + if (A[i] + && (!smallest_value || do_compare(A[i], smallest_value))) + smallest_value = A[i]; + } + } + } + + bool do_compare(group* x, group* y) const + { + return (x->kind < y->kind + || (x->kind == y->kind && x->kind == stored_key + && compare(*x->value, *y->value))); + } + + void promote(group* a) + { + assert(a != 0); + rank_type r = a->rank; + group* p = a->parent; + assert(p != 0); + if (do_compare(a, p)) + { + // s is the rank + 1 sibling + group* s = p->rank > r + 1 ? p->children[r + 1] : 0; + + // If a is the last child of p + if (r == p->rank - 1) + { + if (!A[r]) + A[r] = a; + else if (A[r] != a) + pair_transform(a); + } + else + { + assert(s != 0); + if (A[r + 1] == s) + active_sibling_transform(a, s); + else + good_sibling_transform(a, s); + } + } + } + + group* combine(group* a1, group* a2) + { + assert(a1->rank == a2->rank); + if (do_compare(a2, a1)) + do_swap(a1, a2); + a1->children[a1->rank++] = a2; + a2->parent = a1; + clean(a1); + return a1; + } + + void clean(group* q) + { + if (2 > q->rank) + return; + group* qp = q->children[q->rank - 1]; + rank_type s = q->rank - 2; + group* x = q->children[s]; + group* xp = qp->children[s]; + assert(s == x->rank); + + // If x is active, swap x and xp + if (A[s] == x) + { + q->children[s] = xp; + xp->parent = q; + qp->children[s] = x; + x->parent = qp; + } + } + + void pair_transform(group* a) + { +#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 + std::cerr << "- pair transform\n"; +#endif + rank_type r = a->rank; + + // p is a's parent + group* p = a->parent; + assert(p != 0); + + // g is p's parent (a's grandparent) + group* g = p->parent; + assert(g != 0); + + // a' <- A(r) + assert(A[r] != 0); + group* ap = A[r]; + assert(ap != 0); + + // A(r) <- nil + A[r] = 0; + + // let a' have parent p' + group* pp = ap->parent; + assert(pp != 0); + + // let a' have grandparent g' + group* gp = pp->parent; + assert(gp != 0); + + // Remove a and a' from their parents + assert(ap + == pp->children[pp->rank - 1]); // Guaranteed because ap is active + --pp->rank; + + // Guaranteed by caller + assert(a == p->children[p->rank - 1]); + --p->rank; + + // Note: a, ap, p, pp all have rank r + if (do_compare(pp, p)) + { + do_swap(a, ap); + do_swap(p, pp); + do_swap(g, gp); + } + + // Assuming k(p) <= k(p') + // make p' the rank r child of p + assert(r == p->rank); + p->children[p->rank++] = pp; + pp->parent = p; + + // Combine a, ap into a rank r+1 group c + group* c = combine(a, ap); + + // make c the rank r+1 child of g' + assert(gp->rank > r + 1); + gp->children[r + 1] = c; + c->parent = gp; + +#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 + std::cerr << "After pair transform...\n"; + dump_tree(); +#endif + + if (A[r + 1] == pp) + A[r + 1] = c; + else + promote(c); + } + + void active_sibling_transform(group* a, group* s) + { +#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 + std::cerr << "- active sibling transform\n"; +#endif + group* p = a->parent; + group* g = p->parent; + + // remove a, s from their parents + assert(s->parent == p); + assert(p->children[p->rank - 1] == s); + --p->rank; + assert(p->children[p->rank - 1] == a); + --p->rank; + + rank_type r = a->rank; + A[r + 1] = 0; + a = combine(p, a); + group* c = combine(a, s); + + // make c the rank r+2 child of g + assert(g->children[r + 2] == p); + g->children[r + 2] = c; + c->parent = g; + if (A[r + 2] == p) + A[r + 2] = c; + else + promote(c); + } + + void good_sibling_transform(group* a, group* s) + { +#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 + std::cerr << "- good sibling transform\n"; +#endif + rank_type r = a->rank; + group* c = s->children[s->rank - 1]; + assert(c->rank == r); + if (A[r] == c) + { +#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 + std::cerr << "- good sibling pair transform\n"; +#endif + A[r] = 0; + group* p = a->parent; + + // Remove c from its parent + --s->rank; + + // Make s the rank r child of p + s->parent = p; + p->children[r] = s; + + // combine a, c and let the result by the rank r+1 child of p + assert(p->rank > r + 1); + group* x = combine(a, c); + x->parent = p; + p->children[r + 1] = x; + + if (A[r + 1] == s) + A[r + 1] = x; + else + promote(x); + +#if defined(BOOST_RELAXED_HEAP_DEBUG) && BOOST_RELAXED_HEAP_DEBUG > 1 + dump_tree(std::cerr); +#endif + // pair_transform(a); + } + else + { + // Clean operation + group* p = a->parent; + s->children[r] = a; + a->parent = s; + p->children[r] = c; + c->parent = p; + + promote(a); + } + } + + static void do_swap(group*& x, group*& y) + { + group* tmp = x; + x = y; + y = tmp; + } + + /// Function object that compares two values in the heap + Compare compare; + + /// Mapping from values to indices in the range [0, n). + ID id; + + /** The root group of the queue. This group is special because it will + * never store a value, but it acts as a parent to all of the + * roots. Thus, its list of children is the list of roots. + */ + group root; + + /** Mapping from the group index of a value to the group associated + * with that value. If a value is not in the queue, then the "value" + * field will be empty. + */ + std::vector< group > index_to_group; + + /** Flat data structure containing the values in each of the + * groups. It will be indexed via the id of the values. The groups + * are each log_n long, with the last group potentially being + * smaller. + */ + std::vector< ::boost::optional< value_type > > groups; + + /** The list of active groups, indexed by rank. When A[r] is null, + * there is no active group of rank r. Otherwise, A[r] is the active + * group of rank r. + */ + std::vector< group* > A; + + /** The group containing the smallest value in the queue, which must + * be either a root or an active group. If this group is null, then we + * will need to search for this group when it is needed. + */ + mutable group* smallest_value; + + /// Cached value log_base_2(n) + size_type log_n; +}; + +} // end namespace boost + +#if defined(BOOST_MSVC) +#pragma warning(pop) +#endif + +#endif // BOOST_RELAXED_HEAP_HEADER diff --git a/contrib/restricted/boost/graph/include/boost/pending/stringtok.hpp b/contrib/restricted/boost/graph/include/boost/pending/stringtok.hpp new file mode 100644 index 0000000000..f64a4c45dd --- /dev/null +++ b/contrib/restricted/boost/graph/include/boost/pending/stringtok.hpp @@ -0,0 +1,116 @@ +// (C) Copyright Jeremy Siek 2004 +// Distributed under the Boost Software License, Version 1.0. (See +// accompanying file LICENSE_1_0.txt or copy at +// http://www.boost.org/LICENSE_1_0.txt) + +#ifndef BOOST_STRINGTOK_HPP +#define BOOST_STRINGTOK_HPP + +/* + * stringtok.hpp -- Breaks a string into tokens. This is an example for lib3. + * + * Template function looks like this: + * + * template <typename Container> + * void stringtok (Container &l, + * string const &s, + * char const * const ws = " \t\n"); + * + * A nondestructive version of strtok() that handles its own memory and can + * be broken up by any character(s). Does all the work at once rather than + * in an invocation loop like strtok() requires. + * + * Container is any type that supports push_back(a_string), although using + * list<string> and deque<string> are indicated due to their O(1) push_back. + * (I prefer deque<> because op[]/at() is available as well.) The first + * parameter references an existing Container. + * + * s is the string to be tokenized. From the parameter declaration, it can + * be seen that s is not affected. Since references-to-const may refer to + * temporaries, you could use stringtok(some_container, readline("")) when + * using the GNU readline library. + * + * The final parameter is an array of characters that serve as whitespace. + * Whitespace characters default to one or more of tab, space, and newline, + * in any combination. + * + * 'l' need not be empty on entry. On return, 'l' will have the token + * strings appended. + * + * + * [Example: + * list<string> ls; + * stringtok (ls, " this \t is\t\n a test "); + * for (list<string>::const_iterator i = ls.begin(); + * i != ls.end(); ++i) + * { + * cerr << ':' << (*i) << ":\n"; + * } + * + * would print + * :this: + * :is: + * :a: + * :test: + * -end example] + * + * pedwards@jaj.com May 1999 + */ + +#include <string> +#include <cstring> // for strchr + +/***************************************************************** + * This is the only part of the implementation that I don't like. + * It can probably be improved upon by the reader... + */ + +inline bool isws(char c, char const* const wstr) +{ + using namespace std; + return (strchr(wstr, c) != NULL); +} + +namespace boost +{ + +/***************************************************************** + * Simplistic and quite Standard, but a bit slow. This should be + * templatized on basic_string instead, or on a more generic StringT + * that just happens to support ::size_type, .substr(), and so on. + * I had hoped that "whitespace" would be a trait, but it isn't, so + * the user must supply it. Enh, this lets them break up strings on + * different things easier than traits would anyhow. + */ +template < typename Container > +void stringtok( + Container& l, std::string const& s, char const* const ws = " \t\n") +{ + typedef std::string::size_type size_type; + const size_type S = s.size(); + size_type i = 0; + + while (i < S) + { + // eat leading whitespace + while ((i < S) && (isws(s[i], ws))) + ++i; + if (i == S) + return; // nothing left but WS + + // find end of word + size_type j = i + 1; + while ((j < S) && (!isws(s[j], ws))) + ++j; + + // add word + l.push_back(s.substr(i, j - i)); + + // set up for next loop + i = j + 1; + } +} + +} // namespace boost + +#endif // BOOST_STRINGTOK_HPP |