Compare commits

..

119 Commits

Author SHA1 Message Date
Jeremy W. Murphy 198616d896 Merge pull request #377 from boostorg/develop
Merge a few years worth of changes
2024-05-20 16:12:26 +10:00
Jeremy W. Murphy 5557ccf921 Merge pull request #376 from sehe/pr-364
Fix security issue #364 and non-keyword subgraph parsing
2024-05-10 16:09:02 +10:00
Jeremy W. Murphy 17acf25da7 Merge pull request #375 from sehe/graphviz_test-refactor
Refactoring graphviz_test for review
2024-05-09 15:00:01 +10:00
Jeremy W. Murphy 64a3bae4f2 Merge pull request #374 from sehe/workaround-373
Fix and restore broken test_basic_csr_directed_graph
2024-05-09 14:50:52 +10:00
sehe 05aa9fd816 Include test for subgraph nesting limit
Eliminating need for manual re-test after review updates PR #376
2024-05-08 15:41:04 +02:00
sehe c71ceb8486 max_subgraph_nesting_level in read_graphviz_new 2024-05-08 14:48:06 +02:00
sehe 9c0ceda4c8 test_subgraphs verifies (keyword) subgraphs parse 2024-05-08 14:48:06 +02:00
sehe 5007b01ad5 Fix non-keyword subgraph parsing
Non-keyword graphs never worked (!). This was uncovered because of
security issue #364.

parse_subgraph() incorrectly dealt with first_token in the case
where the `subgraph` keyword wasn't used.
2024-05-08 14:48:06 +02:00
sehe 8126d97989 refactoring graphviz_test for review
The code was mostly fine (except for unhygienic `using namespace` in
places), but it was hard to see what was covered.

I've seperated fixtures (sample input + expected output) and this will
simplify invoking the ComparisonDriver (test_graph).
2024-05-08 14:43:53 +02:00
sehe 2154398906 Review comments 2024-05-08 14:39:27 +02:00
sehe b8150fac82 Restore broken test_basic_csr_directed_graph
Works around invalidation of bundle property maps (see #373).

The `#if SEHE_UNSTABLE_PROPERTY_MAPS_FIXED` section is there to signal
my intent to investigate a generalized fix under that issue. It doubles
as literate documentation of the need for the workaround, so it's less
likely to bite the unwary.
2024-05-03 04:20:45 +02:00
Jeremy W. Murphy 06339d6f44 Update cxxstd to 14
This choice is based on feedback to the Boost.Graph user survey.
2024-04-30 10:56:52 +10:00
Jeremy W. Murphy e7d0adb472 Replace Noel with myself as maintainer
I confirmed with Noel that he was happy with this and told him
that the door is always open if he wants to come back.
Thanks for all your help, Noel!
2024-04-30 10:44:45 +10:00
Jeremy W. Murphy a3fffa9c2b Merge pull request #370 from jcdong98/fix
Fix labeled_graph typo in name adjacenct_vertices.
2024-04-17 10:41:01 +10:00
Jeremy W. Murphy 6caa0baaec Merge pull request #349 from jan-grimo/isomorphism-no-contiguous-invariants
Isomorphism: Remove invariant contiguous range requirement
2024-04-15 11:19:20 +10:00
Jan-Grimo Sobez 044c7d65a5 Use unordered_flat_map, parameterize invariant map 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez 2e7d74b1a0 Remove iterator rename in multiplicities 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez 71cea99db3 Remove Invariant concept checking 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez b9fbc47bbb Remove C++20 reserved keyword namespace (concept) 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez 2c36c0f819 Replace is_detected_v w/ is_detected<...>::value 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez 2f5a3c2ccc Clean up bracket style 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez db7b3736d6 Refactor multiplicities() with iterators 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez 8f3139bed4 Avoid reference member in multiplicity functor 2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez 0be4c876bd Avoid requiring invariant default-constructibility
Avoid requiring invariant default-constructibility
- Refactor concept checking with boost type_traits
2024-04-14 09:48:36 +02:00
Jan-Grimo Sobez 5ec4327816 Invariant contiguous range requirement removal
Invariant contiguous range requirement removal
- Vertex invariants for use in isomorphism algorithm must no longer have
  low upper bounds due to a hidden allocation linear in the maximum
  encountered vertex invariant.
- Vertex invariants must no longer be convertible to `size_t`, but can
  be any comparable and hashable types
- Build `unordered_map`-backed invariant multiplicity map efficiently
  from sorted vertex invariants
2024-04-14 09:48:36 +02:00
Jeremy W. Murphy 4375631fa6 Remove MSVC 14.0 from github workflow 2024-04-14 07:24:22 +10:00
Jiachen Dong 81ead6e595 Fix typo in name adjacenct_vertices. 2024-04-12 17:17:15 +08:00
Jeremy W. Murphy 158eebd082 Merge pull request #368 from andrea-cassioli-maersk/fix-single-solution-rcsp
Fix issue #368 in the single solution RCSP
2024-04-04 09:46:39 +11:00
andrea-cassioli-maersk fa8caeeffa fix wrong naming 2024-04-03 16:07:08 +02:00
andrea-cassioli-maersk 33a2510c54 Update rcsp_single_solution.cpp 2024-03-22 11:00:59 +01:00
andrea-cassioli-maersk 57fdbf4093 Update rcsp_single_solution.cpp 2024-03-22 10:31:14 +01:00
andrea-cassioli-maersk 3fd626fa71 Update .gitignore 2024-03-22 10:08:17 +01:00
andrea-cassioli-maersk 46a2823a94 fix issue in the single solution rcsp 2024-03-22 10:04:32 +01:00
Jeremy W. Murphy 46ddc517a2 Merge pull request #361 from Lastique/feature/update_filesystem_usage
Update Boost.Filesystem usage
2024-01-31 13:40:38 +11:00
Jeremy W. Murphy 9c9f9f4b49 Merge pull request #360 from andrea-cassioli-maersk/andrea-cassioli-maersk-reverse-graph-doc-broken-link-to-example
Minor fixes to reverse_graph and r_c_shortest_paths documentation

reverse_graph example link was broken, r_c_shortest_paths had some stray > symbols.
2024-01-29 11:09:48 +11:00
Andrey Semashev a052dcdd06 Updated Boost.Filesystem usage.
This commit updates tests to avoid using Boost.Filesystem APIs that
were deprecated and then removed.
2024-01-27 00:35:52 +03:00
andrea-cassioli-maersk 72cad02a0b fix reverse graph example example broken link; fix rcsp functions parameters 2024-01-26 11:41:05 +01:00
Jeremy W. Murphy a7c3845f28 Merge pull request #352 from Romain-Geissler-1A/remove-link-against-boost-regex
Remove link against boost regex library, as normally it is header only when using C++ >= 11.
2024-01-01 14:50:25 +11:00
Romain Geissler e522561485 Remove link against boost regex library, as normally it is header only when using C++ >= 11. 2023-12-08 00:00:37 +00:00
Jeremy W. Murphy 1f6bb4adfa Remove Clang 3.x from Drone config 2023-12-07 16:15:25 +11:00
Jeremy W. Murphy a63690ac60 Merge pull request #357 from vslashg/develop
Add missing includes to graph headers
2023-12-07 16:07:29 +11:00
vslashg 3d6b1d4c9b Add missing includes to graph headers
Some graph .hpp files are using APIs without including the associated
headers.  This can cause compile errors if these headers are included
first in a .cpp file.
2023-12-06 16:08:16 +00:00
Jeremy W. Murphy 5235d7dd49 Merge pull request #355 from vslashg/patch-2
Move an #include outside of the boost namespace declaration.
2023-12-02 14:54:14 +11:00
vslashg 372355b045 Move an #include outside of the boost namespace declaration.
iteration_macros.hpp itself includes <utility>, so this inclusion ends up effectively doing

```
namespace boost {
#include <utility>
}
```

which is disallowed per [using.headers].
2023-12-01 19:03:05 -05:00
Jeremy W. Murphy fa2636d69d Merge pull request #354 from DeuceBox/remove-labeled-vertex
Fix labeled_graph::remove_vertex(Label const&) so that it removes the label too
2023-11-28 11:48:46 +11:00
George Williams e94408cf41 test/labeled_graph: added test for multiple associative container 2023-11-27 13:42:58 -05:00
George Williams 8dc51f8bdc test/labeled_graph: added test for removing a labeled vertex 2023-11-20 08:41:55 -05:00
George Williams 52c216c0aa graph/labeled_graph: added remove_labeled_vertex
I took this patch from this ticket:
https://svn.boost.org/trac/boost/ticket/9493
2023-11-18 17:34:09 -05:00
Jeremy W. Murphy f3158683b5 Merge pull request #341 from mglisse/small_prop
Compress boost::property using BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS
2023-09-13 11:11:59 +10:00
Jeremy W. Murphy 77c07d131e Merge pull request #321 from derek-mcblane/fixup-challenge-doc
Fix hyperlink for disjoint sets in "Challenge and To-Do Items"
2023-09-12 13:32:15 +10:00
Jeremy W. Murphy 2e63766abb Merge pull request #331 from mglisse/link-disjoint
Don't look for disjoint-sets representatives in link
2023-09-12 13:30:51 +10:00
Jeremy W. Murphy f2d0ae7827 Merge pull request #350 from vslashg/patch-1
Add a missing include for shared_ptr to topology.hpp
2023-09-12 13:26:55 +10:00
Jeremy W. Murphy d09128fc7b Reordered incluldes 2023-09-12 10:54:02 +10:00
Jeremy W. Murphy 0fd61671ae Merge pull request #348 from jeremy-murphy/drone
Remove GCC 4.x, Clang 3.5 and C++03
2023-09-11 10:52:09 +10:00
Jeremy W. Murphy c3574b1f2d Remove 03 from GitHub CI 2023-09-11 09:48:16 +10:00
vslashg e5ccf7977e Add a missing include to topology.hpp
boost::shared_ptr is used in this file without the corresponding include, so currently this file does not compile on its own.
2023-09-08 14:11:07 -04:00
Jeremy W. Murphy 3e2b86ab81 Remove C++03 testing 2023-09-04 13:30:23 +10:00
Jeremy W. Murphy 2cff7c5207 Remove GCC 4.x and Clang 3.5
Also remove old commented-out Xcode stuff.
2023-09-04 13:29:04 +10:00
Jeremy W. Murphy 7a469ec47a Merge pull request #207 from jargonzombies/map-disconnected-vertices
Isomorphism: Map disconnected vertices
2023-09-04 13:00:16 +10:00
Jeremy W. Murphy 1a3dab98cd Remove redundant scope braces 2023-08-02 13:52:38 +10:00
Jan-Grimo Sobez b48bf93057 Move disconnected vertex matching to member fn 2023-08-01 12:31:50 +02:00
Jeremy W. Murphy 942829ee68 Merge pull request #329 from francoisk/develop
Don't include graphviz.hpp from graphml.hpp (#326)
2023-07-18 15:56:11 +10:00
Jeremy W. Murphy 4fc6b0b65e Merge pull request #206 from jargonzombies/isomorphism-max-invariant
Isomorphism: Replace vertex_max_invariant with internal calculation
2023-07-18 15:06:54 +10:00
Jan-Grimo Sobez 9f36ca3a1d Add overflow assert and doc explanation for bound 2023-07-17 09:52:58 +02:00
Jan-Grimo Sobez 047fff647f Variable renames, doc update 2023-07-09 16:13:32 +02:00
Jan-Grimo Sobez 2097d8ffed Replace lowest with min for int case 2023-07-09 15:56:24 +02:00
Jan-Grimo Sobez 98e7bfa10a Isomorphism: Map disconnected vertices
Isomorphism: Map disconnected vertices
- Adds O(V) algorithm at return_point_true to match disconnected
  vertices in the isomorphism map
- Adds colored isomorphism test ensuring no null vertices are in the
  isomorphism map
2023-07-09 15:56:24 +02:00
Jan-Grimo Sobez ec28611026 Remove max since invar?_arrays are equal 2023-07-09 15:54:08 +02:00
Jan-Grimo Sobez b14f16b472 Revert empty checks 2023-07-09 08:43:23 +02:00
Marc Glisse 41aa91891d [[no_unique_address]] on the base of property
The chain typically ends with no_property, which is empty and wastes
space otherwise.
2023-07-07 21:10:20 +02:00
Jan-Grimo Sobez 38efd9dc1d max_invariant initialization, expand doc
max_invariant initialization
- Zero-initialize `max_invariant` and ensure no UB happens since
  `invar?_array` vecs may be empty if their corresponding graph is empty

expand doc
- More explanation on why `vertex_max_invariant` is ignored
2023-07-07 20:34:20 +02:00
Jeremy W. Murphy 8c9f2dcaf5 Merge pull request #313 from mattpulver/develop
Silence maybe-uninitialized warning in adj_list_edge_iterator::operator++()
2023-07-07 11:49:56 +10:00
Jeremy W. Murphy ee2cdcc805 Merge pull request #205 from jargonzombies/isomorphism-docs
Isomorphism docs: AdaptableUnaryFn, null vertices
2023-07-07 10:32:23 +10:00
Jeremy W. Murphy e56883f789 Merge pull request #339 from svengato/develop
Make comments refer to variables rather than duplicating values
2023-05-08 14:45:05 +10:00
Sven Gato Redsun 0182f7490e Generalize comments to be valid for any values of N and P 2023-05-07 22:02:19 -06:00
Sven Gato Redsun 05e099335a Make comments match actual values of the random graph's number of vertices and probability of edge connection 2023-05-07 20:24:48 -06:00
Jeremy W. Murphy 5ef6a074e7 Merge pull request #315 from svengato/develop
Optionally specify a maximum circuit length in Hawick circuits algorithm
2023-05-08 11:57:33 +10:00
Sven Gato Redsun 2573812229 Add unit tests for max_length from 0 to 10 2023-05-04 07:43:58 -05:00
Jeremy W. Murphy b5fa4d9758 Merge pull request #337 from daankolthof/mas
Maximum Adjacency Search: refactor existing tests + create new tests
2023-05-01 09:22:10 +10:00
Daan Kolthof 12a57f9c01 Merge branch 'develop' into mas 2023-04-27 10:16:49 +01:00
Jeremy W. Murphy 985bfbd765 Merge pull request #336 from daankolthof/ubuntu_bionic_deprecation
Remove Ubuntu Bionic platform from GitHub workflows

Also, fix use of deprecated header for boost::timer::progress_display.
2023-04-27 14:21:45 +10:00
Daan Kolthof 634f5fb1dd Merge branch 'progress_hpp_deprecated' into ubuntu_bionic_deprecation 2023-04-25 11:43:05 +01:00
Daan Kolthof a981db8b1f Remove Ubuntu Bionic from ci.yml 2023-04-25 11:38:02 +01:00
Daan Kolthof a3001ec2e6 Merge branch 'progress_hpp_deprecated' into develop 2023-04-23 23:40:12 +01:00
Daan Kolthof 5308f29b6a Fix small coding errors 2023-04-23 21:35:27 +01:00
Daan Kolthof eb0ab8bd4b Fix deprecation of boost/progress.hpp 2023-04-23 19:00:57 +01:00
Daan Kolthof 0714892239 Fix mas_test compatibility issues with C++98, 0x, 03 2023-04-23 17:41:22 +01:00
Daan Kolthof 0fb5562d43 More mas_test unit tests + refactoring test helper functions 2023-04-21 22:51:37 +01:00
Daan Kolthof 088714f052 Change arity for d-ary-heaps in testing 2023-04-21 14:55:36 +01:00
Daan Kolthof 4d968a2972 Reorganise mas_test, add some simple new tests 2023-04-21 14:35:30 +01:00
Daan Kolthof 1cf87d5558 Cleanup based on static code analysis 2023-04-21 01:00:54 +01:00
Daan Kolthof b460995095 More small cleanups to mas_test 2023-04-21 00:47:39 +01:00
Daan Kolthof 2eea120320 Small cleanup on mas_test 2023-04-21 00:46:05 +01:00
Daan Kolthof 21a9c6588f Refactor existing tests 2023-04-21 00:40:27 +01:00
Jeremy W. Murphy aa0a4d3c93 Merge pull request #332 from ams2990/develop
Add missing break to switch
2023-03-29 10:20:17 +11:00
Andy Shulman e8e47eacbb Add missing break to switch 2023-03-27 23:02:01 -04:00
Marc Glisse 68ee7972df Don't look for representatives in link
The arguments are already required to be the representative of their
class. If we do not know the representatives, we are supposed to call
union_set instead, which first finds them.
2023-03-19 09:44:20 +01:00
Francois Kritzinger 04a213038c Don't include graphviz.hpp from graphml.hpp (#326) 2023-03-13 14:17:18 +02:00
Sven Gato Redsun d95b3d477d Modify unit tests to compare computed and expected number of cycles, and report any errors 2023-03-12 23:19:43 -06:00
Sven Gato Redsun 5a9e2aa794 Add unit tests for nonzero max_length 2023-03-09 21:29:38 -07:00
Sven Gato Redsun a07f3532ad Do not use 'const' with value parameters 2023-03-09 21:26:33 -07:00
Sven Gato Redsun e17d6f9ff8 Use snake case (max_length) for style consistency 2023-03-09 18:17:35 -07:00
Sven Gato Redsun b9509fd9a8 Enforce 80-column line limit 2023-03-09 18:09:25 -07:00
Jeremy W. Murphy 00028767d8 Merge pull request #324 from weenchvd/patch-1
Fix r_c_shortest_paths example
2023-02-15 15:33:08 +11:00
Jeremy W. Murphy 1cf05f2b3f Merge pull request #325 from ams2990/develop
Add missing include on boost/config.hpp
2023-02-15 15:25:09 +11:00
Andy Shulman b33c1eb37d Add missing include on boost/config.hpp
exception.hpp uses BOOST_SYMBOL_VISIBLE, which is defined in boost/config.hpp. Without this, compiling just exception.hpp is broken.
2023-02-09 19:00:19 -05:00
ꓪꓱꓱꓠꓛꓧ 5ccd0852b7 Fix r_c_shortest_paths example 2023-01-26 15:10:46 +03:00
Derek McBlane a3148837c2 fixed hyperlink for disjoint sets 2022-12-27 22:14:20 -05:00
Jeremy W. Murphy 231de4c573 Merge pull request #318 from hdu-sdlzx/develop
Don't run performance test in CI
2022-12-20 09:52:24 +11:00
l00574988 f58f3df2bf Don't run performance test in CI 2022-12-15 21:31:43 -05:00
Sven Gato Redsun 3f75ea7aa3 Optionally specify a maximum circuit length in Hawick circuits algorithm 2022-11-26 10:02:08 -07:00
Jeremy W. Murphy c9f515347b Merge pull request #314 from poelmanc/c++23-fix-add-parentheses
Fix compilation using C++23 by adding parentheses around comma operator inside square brackets
2022-11-23 11:54:47 +11:00
Conrad Poelman 6f1f605ac8 Add parentheses so compiles in C++23 mode
e.g. [a,b] -> [(a,b)] to avoid confusion with C++23 array subscript operator[]
2022-11-21 20:24:02 -05:00
Matt Pulver dd77077747 Silence maybe-uninitialized warning in adj_list_edge_iterator::operator++(). Resolves boostorg/graph#312. 2022-11-14 11:41:34 -05:00
Jeremy W. Murphy ed75fd3e03 Merge pull request #310 from sebrockm/fix-boykov-kolmogorov-all-defaults-overload
Add tests for the all defaults overload of `boykov_kolmogorov_max_flow`
2022-10-25 09:43:52 +11:00
Sebastian Brockmeyer a487ba019d Add a test for the all defaults overload with custom properties 2022-10-23 20:28:02 +02:00
Sebastian Brockmeyer e9852ef6a0 Add test for the all defaults overload with interior properties 2022-10-23 20:27:23 +02:00
Jan-Grimo Sobez e5f9471984 Isomorphism: Ignore vertex_max_invariant
Isomorphism: Ignore vertex_max_invariant
- vertex_max_invariant and invariant2.max() are misnomers since what is
  expected is an upper exclusive bound on the possible invariant values,
  not their maximum value.
- The parameter can be ignored and the upper exclusive bound found
  cheaply at the start of test_isomorphism
- Removes the additional requirement of a nullary max member function on
  invariant2
2020-02-16 11:21:45 +01:00
Jan-Grimo Sobez 70d7fca2ce Isomorphism docs: AdaptableUnaryFn, null vertices
Isomorphism docs
- The expected concept for invariant functors is AdaptableUnaryFunction,
  not UnaryFunction
- Null vertices can appear in the isomorphism map output if both graphs
  contain disconnected vertices, add a note to that parameter's
  documentation
2020-02-16 11:12:30 +01:00
57 changed files with 1620 additions and 709 deletions
-82
View File
@@ -14,38 +14,22 @@ windowsglobalimage="cppalliance/dronevs2019"
def main(ctx):
return [
linux_cxx("g++-4.4 98", "g++", packages="g++-4.4", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.4', 'CXXSTD': '98', }, globalenv=globalenv),
linux_cxx("g++-4.4 0x", "g++", packages="g++-4.4", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.4', 'CXXSTD': '0x', }, globalenv=globalenv),
linux_cxx("g++-4.6 03", "g++", packages="g++-4.6", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.6', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-4.6 0x", "g++", packages="g++-4.6", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.6', 'CXXSTD': '0x', }, globalenv=globalenv),
linux_cxx("g++-4.7 03", "g++-4.7", packages="g++-4.7", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.7', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-4.7 11", "g++-4.7", packages="g++-4.7", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.7', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-4.8 03", "g++-4.8", packages="g++-4.8", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.8', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-4.8 11", "g++-4.8", packages="g++-4.8", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.8', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-4.9 03", "g++-4.9", packages="g++-4.9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.9', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-4.9 11", "g++-4.9", packages="g++-4.9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-4.9', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-5 03", "g++-5", packages="g++-5", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-5 11", "g++-5", packages="g++-5", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-5 14", "g++-5", packages="g++-5", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("g++-5 1z", "g++-5", packages="g++-5", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-5', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("g++-6 03", "g++-6", packages="g++-6", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-6 11", "g++-6", packages="g++-6", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-6 14", "g++-6", packages="g++-6", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("g++-6 1z", "g++-6", packages="g++-6", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-6', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("g++-7 03", "g++-7", packages="g++-7", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-7 11", "g++-7", packages="g++-7", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-7 14", "g++-7", packages="g++-7", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("g++-7 17", "g++-7", packages="g++-7", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-7', 'CXXSTD': '17', }, globalenv=globalenv),
linux_cxx("g++-8 03", "g++-8", packages="g++-8", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-8', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-8 11", "g++-8", packages="g++-8", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-8', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-8 14", "g++-8", packages="g++-8", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-8', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("g++-8 17", "g++-8", packages="g++-8", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-8', 'CXXSTD': '17', }, globalenv=globalenv),
linux_cxx("g++-9 03", "g++-9", packages="g++-9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-9', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("g++-9 11", "g++-9", packages="g++-9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-9', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("g++-9 14", "g++-9", packages="g++-9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-9', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("g++-9 17", "g++-9", packages="g++-9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-9', 'CXXSTD': '17', }, globalenv=globalenv),
@@ -56,107 +40,41 @@ def main(ctx):
linux_cxx("g++-10 17", "g++-10", packages="g++-10", image="cppalliance/droneubuntu2004:1", buildtype="boost", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-10', 'CXXSTD': '17', }, globalenv=globalenv),
linux_cxx("g++-10 20", "g++-10", packages="g++-10", image="cppalliance/droneubuntu2004:1", buildtype="boost", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-10', 'CXXSTD': '20', }, globalenv=globalenv),
linux_cxx("clang++-3.5 03", "clang++", packages="clang-3.5", llvm_os="precise", llvm_ver="3.5", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.5', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-3.5 11", "clang++", packages="clang-3.5", llvm_os="precise", llvm_ver="3.5", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.5', 'CXXSTD': '11', }, globalenv=globalenv),
#linux_cxx("clang++-3.5 14", "clang++", packages="clang-3.5", llvm_os="precise", llvm_ver="3.5", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.5', 'CXXSTD': '14', }, globalenv=globalenv),
#linux_cxx("clang++-3.5 1z", "clang++", packages="clang-3.5", llvm_os="precise", llvm_ver="3.5", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.5', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-3.6 03", "clang++", packages="clang-3.6", llvm_os="precise", llvm_ver="3.6", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.6', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-3.6 11", "clang++", packages="clang-3.6", llvm_os="precise", llvm_ver="3.6", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.6', 'CXXSTD': '11', }, globalenv=globalenv),
#linux_cxx("clang++-3.6 14", "clang++", packages="clang-3.6", llvm_os="precise", llvm_ver="3.6", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.6', 'CXXSTD': '14', }, globalenv=globalenv),
#linux_cxx("clang++-3.6 1z", "clang++", packages="clang-3.6", llvm_os="precise", llvm_ver="3.6", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.6', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-3.7 03", "clang++", packages="clang-3.7", llvm_os="precise", llvm_ver="3.7", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.7', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-3.7 11", "clang++", packages="clang-3.7", llvm_os="precise", llvm_ver="3.7", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.7', 'CXXSTD': '11', }, globalenv=globalenv),
#linux_cxx("clang++-3.7 14", "clang++", packages="clang-3.7", llvm_os="precise", llvm_ver="3.7", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.7', 'CXXSTD': '14', }, globalenv=globalenv),
#linux_cxx("clang++-3.7 1z", "clang++", packages="clang-3.7", llvm_os="precise", llvm_ver="3.7", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.7', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-3.8 03", "clang++-3.8", packages="clang-3.8", llvm_os="precise", llvm_ver="3.8", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.8', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-3.8 11", "clang++-3.8", packages="clang-3.8", llvm_os="precise", llvm_ver="3.8", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.8', 'CXXSTD': '11', }, globalenv=globalenv),
# These have issues not of our making:
#linux_cxx("clang++-3.8 14", "clang++-3.8", packages="clang-3.8", llvm_os="precise", llvm_ver="3.8", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.8', 'CXXSTD': '14', }, globalenv=globalenv),
#linux_cxx("clang++-3.8 1z", "clang++-3.8", packages="clang-3.8", llvm_os="precise", llvm_ver="3.8", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.8', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-3.9 03", "clang++-3.9", packages="clang-3.9", llvm_os="precise", llvm_ver="3.9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.9', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-3.9 11", "clang++-3.9", packages="clang-3.9", llvm_os="precise", llvm_ver="3.9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.9', 'CXXSTD': '11', }, globalenv=globalenv),
# These have issues not of our making:
#linux_cxx("clang++-3.9 14", "clang++-3.9", packages="clang-3.9", llvm_os="precise", llvm_ver="3.9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.9', 'CXXSTD': '14', }, globalenv=globalenv),
#linux_cxx("clang++-3.9 1z", "clang++-3.9", packages="clang-3.9", llvm_os="precise", llvm_ver="3.9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-3.9', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-4.0 03", "clang++-4.0", packages="clang-4.0", llvm_os="xenial", llvm_ver="4.0", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-4.0', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-4.0 11", "clang++-4.0", packages="clang-4.0", llvm_os="xenial", llvm_ver="4.0", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-4.0', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("clang++-4.0 14", "clang++-4.0", packages="clang-4.0", llvm_os="xenial", llvm_ver="4.0", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-4.0', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("clang++-4.0 1z", "clang++-4.0", packages="clang-4.0", llvm_os="xenial", llvm_ver="4.0", buildtype="boost", image=linuxglobalimage, environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-4.0', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-5.0 03", "clang++-5.0", packages="clang-5.0", llvm_os="xenial", llvm_ver="5.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-5.0', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-5.0 11", "clang++-5.0", packages="clang-5.0", llvm_os="xenial", llvm_ver="5.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-5.0', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("clang++-5.0 14", "clang++-5.0", packages="clang-5.0", llvm_os="xenial", llvm_ver="5.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-5.0', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("clang++-5.0 1z", "clang++-5.0", packages="clang-5.0", llvm_os="xenial", llvm_ver="5.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-5.0', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-6.0 03", "clang++-6.0", packages="clang-6.0", llvm_os="xenial", llvm_ver="6.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-6.0', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-6.0 11", "clang++-6.0", packages="clang-6.0", llvm_os="xenial", llvm_ver="6.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-6.0', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("clang++-6.0 14", "clang++-6.0", packages="clang-6.0", llvm_os="xenial", llvm_ver="6.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-6.0', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("clang++-6.0 1z", "clang++-6.0", packages="clang-6.0", llvm_os="xenial", llvm_ver="6.0", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-6.0', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-7 03", "clang++-7", packages="clang-7", llvm_os="xenial", llvm_ver="7", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-7', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-7 14", "clang++-7", packages="clang-7", llvm_os="xenial", llvm_ver="7", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-7', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("clang++-7 17", "clang++-7", packages="clang-7", llvm_os="xenial", llvm_ver="7", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-7', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("clang++-7 1z", "clang++-7", packages="clang-7", llvm_os="xenial", llvm_ver="7", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-7', 'CXXSTD': '1z', }, globalenv=globalenv),
linux_cxx("clang++-8 03", "clang++-8", packages="clang-8", llvm_os="xenial", llvm_ver="8", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-8', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-8 11", "clang++-8", packages="clang-8", llvm_os="xenial", llvm_ver="8", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-8', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("clang++-8 14", "clang++-8", packages="clang-8", llvm_os="xenial", llvm_ver="8", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-8', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("clang++-8 17", "clang++-8", packages="clang-8", llvm_os="xenial", llvm_ver="8", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-8', 'CXXSTD': '17', }, globalenv=globalenv),
linux_cxx("clang++-8 2a", "clang++-8", packages="clang-8", llvm_os="xenial", llvm_ver="8", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-8', 'CXXSTD': '2a', }, globalenv=globalenv),
linux_cxx("clang++-9 03", "clang++-9", packages="clang-9", llvm_os="xenial", llvm_ver="9", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-9', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-9 11", "clang++-9", packages="clang-9", llvm_os="xenial", llvm_ver="9", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-9', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("clang++-9 14", "clang++-9", packages="clang-9", llvm_os="xenial", llvm_ver="9", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-9', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("clang++-9 17", "clang++-9", packages="clang-9", llvm_os="xenial", llvm_ver="9", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-9', 'CXXSTD': '17', }, globalenv=globalenv),
linux_cxx("clang++-9 2a", "clang++-9", packages="clang-9", llvm_os="xenial", llvm_ver="9", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-9', 'CXXSTD': '2a', }, globalenv=globalenv),
linux_cxx("clang++-10 03", "clang++-10", packages="clang-10", llvm_os="xenial", llvm_ver="10", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-10', 'CXXSTD': '03', }, globalenv=globalenv),
linux_cxx("clang++-10 11", "clang++-10", packages="clang-10", llvm_os="xenial", llvm_ver="10", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-10', 'CXXSTD': '11', }, globalenv=globalenv),
linux_cxx("clang++-10 14", "clang++-10", packages="clang-10", llvm_os="xenial", llvm_ver="10", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-10', 'CXXSTD': '14', }, globalenv=globalenv),
linux_cxx("clang++-10 17", "clang++-10", packages="clang-10", llvm_os="xenial", llvm_ver="10", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-10', 'CXXSTD': '17', }, globalenv=globalenv),
linux_cxx("clang++-10 20", "clang++-10", packages="clang-10", llvm_os="xenial", llvm_ver="10", buildtype="boost", image="cppalliance/droneubuntu1804:1", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++-10', 'CXXSTD': '20', }, globalenv=globalenv),
osx_cxx("XCode-11.7 03", "clang++", packages="", buildtype="boost", xcode_version="11.7", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
osx_cxx("XCode-11.7 11", "clang++", packages="", buildtype="boost", xcode_version="11.7", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
osx_cxx("XCode-11.7 14", "clang++", packages="", buildtype="boost", xcode_version="11.7", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
osx_cxx("XCode-11.7 17", "clang++", packages="", buildtype="boost", xcode_version="11.7", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '17', }, globalenv=globalenv),
osx_cxx("XCode-11.7 2a", "clang++", packages="", buildtype="boost", xcode_version="11.7", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '2a', }, globalenv=globalenv),
# We don't support these old versions of Xcode any more, but you are welcome to take up the challenge for doing so if you need them.
# osx_cxx("XCode-10.2 03", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
# osx_cxx("XCode-10.2 11", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
# osx_cxx("XCode-10.2 14", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
# osx_cxx("XCode-10.2 17", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '17', }, globalenv=globalenv),
# osx_cxx("XCode-10.2 2a", "clang++", packages="", buildtype="boost", xcode_version="10.2", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '2a', }, globalenv=globalenv),
# osx_cxx("XCode-9.4 03", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
# osx_cxx("XCode-9.4 11", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
# osx_cxx("XCode-9.4 14", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
# osx_cxx("XCode-9.4 1z", "clang++", packages="", buildtype="boost", xcode_version="9.4", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
# osx_cxx("XCode-9.0 03", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
# osx_cxx("XCode-9.0 11", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
# osx_cxx("XCode-9.0 14", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
# osx_cxx("XCode-9.0 1z", "clang++", packages="", buildtype="boost", xcode_version="9", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
# osx_cxx("XCode-8.3 03", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
# osx_cxx("XCode-8.3 11", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
# osx_cxx("XCode-8.3 14", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
# osx_cxx("XCode-8.3 1z", "clang++", packages="", buildtype="boost", xcode_version="8.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
# osx_cxx("XCode-8.0 03", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
# osx_cxx("XCode-8.0 11", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
# osx_cxx("XCode-8.0 14", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
# osx_cxx("XCode-8.0 1z", "clang++", packages="", buildtype="boost", xcode_version="8", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
# osx_cxx("XCode-7.3 03", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '03', }, globalenv=globalenv),
# osx_cxx("XCode-7.3 11", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '11', }, globalenv=globalenv),
]
# from https://github.com/boostorg/boost-ci
+4 -92
View File
@@ -51,57 +51,10 @@ jobs:
run: 'echo "using $TOOLSET : : ${{ matrix.compiler }} ;" > ~/user-config.jam'
working-directory: ../boost-root
- name: Config info
run: ../../../b2 print_config_info toolset=$TOOLSET cxxstd=03,11,14,17,2a
run: ../../../b2 print_config_info toolset=$TOOLSET cxxstd=11,14,17,2a
working-directory: ../boost-root/libs/config/test
- name: Test
run: ../../../b2 toolset=$TOOLSET cxxstd=03,11,14,17,2a
working-directory: ../boost-root/libs/graph/test
ubuntu-bionic:
runs-on: ubuntu-18.04
strategy:
fail-fast: false
matrix:
compiler: [ g++-7, g++-8, clang++-7, clang++-8 ]
steps:
- uses: actions/checkout@v2
with:
fetch-depth: '0'
- uses: mstachniuk/ci-skip@v1
with:
commit-filter: '[skip ci];[ci skip];[CI SKIP];[SKIP CI];***CI SKIP***;***SKIP CI***;[windows];[Windows];[WINDOWS];[apple];[Apple];[APPLE]'
commit-filter-separator: ';'
fail-fast: true
- name: Set TOOLSET
run: echo ${{ matrix.compiler }} | awk '/^g/ { print "TOOLSET=gcc" } /^clang/ { print "TOOLSET=clang" }' >> $GITHUB_ENV
- name: Add repository
run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
- name: Install packages
run: sudo apt install g++-7 g++-8 clang-7 clang-8
- name: Checkout main boost
run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root
- name: Update tools/boostdep
run: git submodule update --init tools/boostdep
working-directory: ../boost-root
- name: Copy files
run: cp -r $GITHUB_WORKSPACE/* libs/graph
working-directory: ../boost-root
- name: Install deps
run: python tools/boostdep/depinst/depinst.py graph
working-directory: ../boost-root
- name: Bootstrap
run: ./bootstrap.sh
working-directory: ../boost-root
- name: Generate headers
run: ./b2 headers
working-directory: ../boost-root
- name: Generate user config
run: 'echo "using $TOOLSET : : ${{ matrix.compiler }} ;" > ~/user-config.jam'
working-directory: ../boost-root
- name: Config info install
run: ../../../b2 print_config_info toolset=$TOOLSET cxxstd=03,11,14,17
working-directory: ../boost-root/libs/config/test
- name: Test
run: ../../../b2 toolset=$TOOLSET cxxstd=03,11,14,17
run: ../../../b2 toolset=$TOOLSET cxxstd=11,14,17,2a
working-directory: ../boost-root/libs/graph/test
macos:
runs-on: macos-latest
@@ -136,51 +89,10 @@ jobs:
run: ./b2 headers
working-directory: ../boost-root
- name: Config info
run: ../../../b2 print_config_info toolset=${{ matrix.toolset }} cxxstd=03,11,14,17,2a
run: ../../../b2 print_config_info toolset=${{ matrix.toolset }} cxxstd=11,14,17,2a
working-directory: ../boost-root/libs/config/test
- name: Test
run: ../../../b2 toolset=${{ matrix.toolset }} cxxstd=03,11,14,17,2a define=CI_SUPPRESS_KNOWN_ISSUES
working-directory: ../boost-root/libs/graph/test
windows_msvc_14_0:
runs-on: windows-2019
defaults:
run:
shell: cmd
strategy:
fail-fast: false
matrix:
toolset: [ msvc-14.0 ]
steps:
- uses: actions/checkout@v2
with:
fetch-depth: '0'
- uses: mstachniuk/ci-skip@v1
with:
commit-filter: '[skip ci];[ci skip];[CI SKIP];[SKIP CI];***CI SKIP***;***SKIP CI***;[apple];[Apple];[APPLE];[linux];[Linux];[LINUX]'
commit-filter-separator: ';'
fail-fast: true
- name: Checkout main boost
run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root
- name: Update tools/boostdep
run: git submodule update --init tools/boostdep
working-directory: ../boost-root
- name: Copy files
run: xcopy /s /e /q %GITHUB_WORKSPACE% libs\graph
working-directory: ../boost-root
- name: Install deps
run: python tools/boostdep/depinst/depinst.py graph
working-directory: ../boost-root
- name: Bootstrap
run: bootstrap
working-directory: ../boost-root
- name: Generate headers
run: b2 headers
working-directory: ../boost-root
- name: Config info
run: ..\..\..\b2 print_config_info cxxstd=14,17 address-model=64 toolset=msvc-14.0
working-directory: ../boost-root/libs/config/test
- name: Test
run: ..\..\..\b2 --hash address-model=64 cxxstd=14,17 toolset=msvc-14.0
run: ../../../b2 toolset=${{ matrix.toolset }} cxxstd=11,14,17,2a define=CI_SUPPRESS_KNOWN_ISSUES
working-directory: ../boost-root/libs/graph/test
windows_msvc_14_2:
runs-on: windows-2019
+4
View File
@@ -6,3 +6,7 @@ kevin-bacon2.dat
random.dot
triangular-fr.dot
triangular-kk.dot
test/*.dot
example/routing-table.dat
example/figs/ospf-sptree.dot
CMakeFiles/
-1
View File
@@ -16,7 +16,6 @@ lib boost_graph
read_graphviz_new.cpp
graphml.cpp
:
<library>../../regex/build//boost_regex
<link>shared:<define>BOOST_GRAPH_DYN_LINK=1
# Without these flags, MSVC 7.1 and 8.0 crash
# User reports that VC++ 8.0 does not fail anymore, so that is removed
+1 -1
View File
@@ -37,7 +37,7 @@ review. The pending items are:</li>
<tt>mutable_queue.hpp</tt>, <tt>fibonacci_heap.hpp</tt>.
Somehow merge implementation with Dietmer's heaps and queues.</li>
<li><tt>disjoint_sets</tt> (see <a href="disjoint_sets.html">)</li>
<li><tt>disjoint_sets</tt> (see <a href="disjoint_sets.html">Disjoint Sets</a>)</li>
</ul>
<li>Construct a set of planar graph algorithms.</li>
+9 -3
View File
@@ -13,13 +13,13 @@
<h1 id="hawick_circuits"><code>hawick_circuits</code></h1>
<pre><code>template &lt;typename Graph, typename Visitor, typename VertexIndexMap&gt;
void hawick_circuits(Graph const&amp; graph, Visitor visitor, VertexIndexMap const&amp; vim = get(vertex_index, graph));
void hawick_circuits(Graph const&amp; graph, Visitor visitor, VertexIndexMap const&amp; vim = get(vertex_index, graph), unsigned int max_length = 0);
template &lt;typename Graph, typename Visitor, typename VertexIndexMap&gt;
void hawick_unique_circuits(Graph const&amp; graph, Visitor visitor, VertexIndexMap const&amp; vim = get(vertex_index, graph));
void hawick_unique_circuits(Graph const&amp; graph, Visitor visitor, VertexIndexMap const&amp; vim = get(vertex_index, graph), unsigned int max_length = 0);
</code></pre>
<p>Enumerate all the elementary circuits in a directed multigraph. Specifically,
<p>Enumerate all the elementary circuits (of length &le; <code>max_length</code>, if nonzero) in a directed multigraph. Specifically,
self-loops and redundant circuits caused by parallel edges are enumerated too.
<code>hawick_unique_circuits</code> may be used if redundant circuits caused by parallel
edges are not desired.</p>
@@ -59,6 +59,12 @@ edges are not desired.</p>
the vertex index map provided by the <code>graph</code>.</p>
</blockquote>
<p><strong>IN:</strong> <code>unsigned int max_length = 0</code></p>
<blockquote>
<p>The maximum circuit length to consider. Beyond this it truncates the depth-first search, reducing the computation time by ignoring longer circuits. The default value of <code>max_length = 0</code> implies no maximum.</p>
</blockquote>
<hr />
<div class="footer">
+8 -15
View File
@@ -92,8 +92,8 @@ href="./VertexListGraph.html">Vertex List Graph</a>.
OUT: <tt>isomorphism_map(IsoMap f)</tt>
<blockquote>
The mapping from vertices in graph 1 to vertices in graph 2. This must
be a <a href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write
The mapping from vertices in graph 1 to vertices in graph 2. <tt>IsoMap</tt>
must be a <a href="../../property_map/doc/ReadWritePropertyMap.html">Read/Write
Property Map</a>.<br> <b>Default:</b> an <a
href="../../property_map/doc/iterator_property_map.html"><tt>iterator_property_map</tt></a>
constructed from a <tt>std::vector</tt> of graph 2's vertex
@@ -111,12 +111,11 @@ This mapping can be used either to speed up the search (as is done by the
default value, which requires that the degrees of <i>v1</i> and <i>v2</i> are
equal) or to impose extra conditions on the result. The
<tt>VertexInvariant1</tt> and <tt>VertexInvariant2</tt> types must model <a
href="http://www.boost.org/sgi/stl/UnaryFunction.html">UnaryFunction</a>, with
the argument type of <tt>vertex_invariant1</tt> being <tt>Graph1</tt>'s vertex
href="http://www.boost.org/sgi/stl/AdaptableUnaryFunction.html">AdaptableUnaryFunction</a>,
with the argument type of <tt>vertex_invariant1</tt> being <tt>Graph1</tt>'s vertex
descriptor type, the argument type of <tt>vertex_invariant2</tt> being
<tt>Graph2</tt>'s vertex descriptor type, and both functions having integral
result types. The values returned by these two functions must be in the range
[0, <tt>vertex_max_invariant</tt>).
<tt>Graph2</tt>'s vertex descriptor type, and both functions sharing a
result type that is totally ordered and hashable, such as an integer.
<br>
<b>Default:</b> <tt>degree_vertex_invariant</tt> for both arguments<br>
<b>Python</b>: Unsupported parameter.
@@ -124,14 +123,8 @@ result types. The values returned by these two functions must be in the range
IN: <tt>vertex_max_invariant(std::size_t max_invariant)</tt>
<blockquote>
An upper bound on the possible values returned from either
vertex_invariant1 or vertex_invariant2.
<br>
<b>Default:</b> <tt>vertex_invariant2.max()</tt>. The default
<tt>vertex_invariant2</tt> parameter, an instance of
<tt>degree_vertex_invariant</tt>, defines this function to
return <tt>num_vertices(g2) * (num_vertices(g2)+1)</tt>.<br>
<b>Python</b>: Unsupported parameter.
This parameter is ignored as it is no longer necessary, but kept for backwards
compatibility.
</blockquote>
IN: <tt>vertex_index1_map(VertexIndex1Map i1_map)</tt>
+3 -3
View File
@@ -57,7 +57,7 @@ void r_c_shortest_paths( const Graph&amp; g,
typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
typename graph_traits&lt;Graph&gt;::vertex_descriptor t,
std::vector&lt;typename graph_traits&lt;Graph&gt;::edge_descriptor&gt;&amp; pareto_optimal_solution,
Resource_Container&gt;&amp; pareto_optimal_resource_container,
Resource_Container&amp; pareto_optimal_resource_container,
const Resource_Container&amp; rc,
const Resource_Extension_Function&amp; ref,
const Dominance_Function&amp; dominance,
@@ -93,7 +93,7 @@ void r_c_shortest_paths( const Graph&amp; g,
typename graph_traits&lt;Graph&gt;::vertex_descriptor s,
typename graph_traits&lt;Graph&gt;::vertex_descriptor t,
std::vector&lt;typename graph_traits&lt;Graph&gt;::edge_descriptor&gt;&amp; pareto_optimal_solution,
Resource_Container&gt;&amp; pareto_optimal_resource_container,
Resource_Container&amp; pareto_optimal_resource_container,
const Resource_Container&amp; rc,
const Resource_Extension_Function&amp; ref,
const Dominance_Function&amp; dominance )
@@ -554,7 +554,7 @@ When <tt>b_result_must_be_equal_to_desired_final_resource_levels==true</tt> (<tt
<p>
The file <a href="../example/r_c_shortest_paths_example.cpp">
<rr>example/r_c_shortest_paths_example.cpp</tt></a> provides examples for how SPPRCs can be solved with the <tt>r_c_shortest_paths</tt> functions. There is an example for an SPP without resource constraints and an example for a shortest path problem with time windows.<br>
<tt>example/r_c_shortest_paths_example.cpp</tt></a> provides examples for how SPPRCs can be solved with the <tt>r_c_shortest_paths</tt> functions. There is an example for an SPP without resource constraints and an example for a shortest path problem with time windows.<br>
It is obvious that one would not use the algorithm for SPPs without resource constraints, because there are faster algorithms for this problem, but one would expect a code for the SPP with resource constraints to be able to handle such a case.
</p>
+2 -2
View File
@@ -181,8 +181,8 @@ bool status = read_graphviz(gvgraph,graph,dp,&quot;node_id&quot;);
<div class="section" id="building-the-graphviz-readers">
<h1><a class="toc-backref" href="#id5">Building the GraphViz Readers</a></h1>
<p>To use the GraphViz readers, you will need to build and link against
the &quot;boost_graph&quot; and &quot;boost_regex&quot; libraries. These libraries can be built by following the
<a class="reference external" href="../../../more/getting_started.html#Build_Install">Boost Jam Build Instructions</a> for the subdirectories <tt class="docutils literal"><span class="pre">libs/graph/build</span></tt> and <tt class="docutils literal"><span class="pre">libs/regex/build</span></tt>.</p>
the &quot;boost_graph&quot; library. This library can be built by following the
<a class="reference external" href="../../../more/getting_started.html#Build_Install">Boost Jam Build Instructions</a> for the subdirectory <tt class="docutils literal"><span class="pre">libs/graph/build</span></tt>.</p>
</div>
<div class="section" id="notes">
<h1><a class="toc-backref" href="#id6">Notes</a></h1>
+2 -2
View File
@@ -182,8 +182,8 @@ GraphViz reader to populate an ``adjacency_list`` graph
Building the GraphViz Readers
-----------------------------
To use the GraphViz readers, you will need to build and link against
the "boost_graph" and "boost_regex" libraries. These libraries can be built by following the
`Boost Jam Build Instructions`_ for the subdirectories ``libs/graph/build`` and ``libs/regex/build``.
the "boost_graph" library. This library can be built by following the
`Boost Jam Build Instructions`_ for the subdirectory ``libs/graph/build``.
Notes
+1 -1
View File
@@ -33,7 +33,7 @@ way to obtain a transposed view of a graph.
<H3>Example</H3>
The example from <a
href="../example/reverse-graph-eg.cpp"><tt>examples/reverse-graph-eg.cpp</tt></a>.
href="../example/reverse_graph.cpp"><tt>example/reverse_graph.cpp</tt></a>.
<pre>
int
+3 -3
View File
@@ -16,7 +16,7 @@
#include <map>
#include <vector>
#include <boost/random/linear_congruential.hpp>
#include <boost/progress.hpp>
#include <boost/timer/progress_display.hpp>
#include <boost/shared_ptr.hpp>
using namespace boost;
@@ -67,7 +67,7 @@ class progress_cooling : public linear_cooling< double >
public:
explicit progress_cooling(std::size_t iterations) : inherited(iterations)
{
display.reset(new progress_display(iterations + 1, std::cerr));
display.reset(new boost::timer::progress_display(iterations + 1, std::cerr));
}
double operator()()
@@ -77,7 +77,7 @@ public:
}
private:
shared_ptr< boost::progress_display > display;
shared_ptr< boost::timer::progress_display > display;
};
int main(int argc, char* argv[])
+8 -2
View File
@@ -78,7 +78,8 @@ int main(int argc, char const* argv[])
{
if (argc < 2)
{
std::cout << "usage: " << argv[0] << " num_vertices < input\n";
std::cout << "usage: " << argv[0] << " <num_vertices>";
std::cout << " <max_length (optional)>\n";
return EXIT_FAILURE;
}
@@ -88,7 +89,12 @@ int main(int argc, char const* argv[])
build_graph(graph, num_vertices, first_vertex, last_vertex);
cycle_printer< std::ostream > visitor(std::cout);
boost::hawick_circuits(graph, visitor);
if (argc == 2) {
boost::hawick_circuits(graph, visitor);
} else {
unsigned int max_length = boost::lexical_cast< unsigned int >(argv[2]);
boost::hawick_circuits(graph, visitor, max_length);
}
return EXIT_SUCCESS;
}
+2 -2
View File
@@ -288,8 +288,8 @@ int main()
std::cout << "SPP with time windows:" << std::endl;
std::cout << "Number of optimal solutions: ";
std::cout << static_cast< int >(opt_solutions.size()) << std::endl;
for (int i = 0; i < static_cast< int >(opt_solutions.size()); ++i)
std::cout << static_cast< int >(opt_solutions_spptw.size()) << std::endl;
for (int i = 0; i < static_cast< int >(opt_solutions_spptw.size()); ++i)
{
std::cout << "The " << i << "th shortest path from A to E is: ";
std::cout << std::endl;
+1
View File
@@ -10,6 +10,7 @@
#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
@@ -14,6 +14,7 @@
#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
+1
View File
@@ -14,6 +14,7 @@
#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
@@ -2189,8 +2189,12 @@ public:
}
// Copy the edges by adding each edge and copying its
// property object.
#ifdef BOOST_NO_CXX17_STRUCTURED_BINDINGS
edge_iterator ei, ei_end;
for (boost::tie(ei, ei_end) = edges(x); ei != ei_end; ++ei)
#else // Silences -Wmaybe-uninitialized in adj_list_edge_iterator::operator++().
for (auto [ei, ei_end] = edges(x); ei != ei_end; ++ei)
#endif
{
edge_descriptor e;
bool inserted;
+1
View File
@@ -8,6 +8,7 @@
#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
@@ -171,7 +171,7 @@ namespace detail
= construct_< std::string >(arg1, arg2)];
a_list = list_p(
ID[(a_list.key = arg1), (a_list.value = "true")] >> !(
ID[((a_list.key = arg1), (a_list.value = "true"))] >> !(
ch_p('=') >> ID[a_list.value = arg1])[phoenix::bind(
&definition::call_prop_actor)(
var(*this), a_list.key, a_list.value)],
@@ -213,8 +213,8 @@ namespace detail
// (directed/undirected)
edgeop = ch_p('-') >> ch_p(boost::ref(edge_head));
edgeRHS = +(edgeop[(data_stmt.sources = data_stmt.dests),
(data_stmt.dests = construct_< nodes_t >())]
edgeRHS = +(edgeop[((data_stmt.sources = data_stmt.dests),
(data_stmt.dests = construct_< nodes_t >()))]
>> (subgraph[data_stmt.dests = arg1]
| node_id[phoenix::bind(&definition::insert_node)(
var(*this), data_stmt.dests, arg1)])
@@ -225,10 +225,10 @@ namespace detail
// To avoid backtracking, edge, node, and subgraph
// statements are processed as one nonterminal.
data_stmt
= (subgraph[(data_stmt.dests
= (subgraph[((data_stmt.dests
= arg1), // will get moved in rhs
(data_stmt.saw_node = false)]
| node_id[(phoenix::bind(
(data_stmt.saw_node = false))]
| node_id[((phoenix::bind(
&definition::insert_node)(
var(*this), data_stmt.dests, arg1)),
(data_stmt.saw_node = true),
@@ -236,7 +236,7 @@ namespace detail
(std::cout << val("AcTive Node: ") << arg1
<< "\n"),
#endif // BOOST_GRAPH_DEBUG
(data_stmt.active_node = arg1)])
(data_stmt.active_node = arg1))])
>> if_p(edgeRHS)[!attr_list(actor_t(phoenix::bind(
&definition::edge_prop)(
var(*this), arg1, arg2)))]
@@ -252,11 +252,11 @@ namespace detail
stmt_list = *(stmt >> !ch_p(';'));
subgraph = !(as_lower_d[keyword_p("subgraph")]
>> (!ID[(subgraph.name = arg1),
>> (!ID[((subgraph.name = arg1),
(subgraph.nodes
= (var(subgraph_nodes))[arg1]),
(subgraph.edges
= (var(subgraph_edges))[arg1])]))
= (var(subgraph_edges))[arg1]))]))
>> ch_p('{')[++var(subgraph_depth)] >> stmt_list
>> ch_p('}')[--var(subgraph_depth)]
[(var(subgraph_nodes))[subgraph.name]
@@ -265,19 +265,19 @@ namespace detail
= subgraph.edges]
| as_lower_d[keyword_p("subgraph")]
>> ID[(subgraph.nodes
>> ID[((subgraph.nodes
= (var(subgraph_nodes))[arg1]),
(subgraph.edges = (var(subgraph_edges))[arg1])];
(subgraph.edges = (var(subgraph_edges))[arg1]))];
the_grammar = (!as_lower_d[keyword_p("strict")])
>> (as_lower_d[keyword_p(
"graph")][(var(edge_head) = '-'),
"graph")][((var(edge_head) = '-'),
(phoenix::bind(&definition::check_undirected)(
var(*this)))]
var(*this))))]
| as_lower_d[keyword_p(
"digraph")][(var(edge_head) = '>'),
"digraph")][((var(edge_head) = '>'),
(phoenix::bind(&definition::check_directed)(
var(*this)))])
var(*this))))])
>> (!ID) >> ch_p('{') >> stmt_list >> ch_p('}');
} // definition()
+1
View File
@@ -18,6 +18,7 @@
#include <vector>
#include <queue>
#include <boost/assert.hpp>
#include <boost/throw_exception.hpp>
namespace boost
{
@@ -16,6 +16,7 @@
#include <vector>
#include <set>
#include <algorithm>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/edmonds_karp_max_flow.hpp>
namespace boost
+49
View File
@@ -13,6 +13,8 @@
#include <stdexcept>
#include <string>
#include <boost/config.hpp>
namespace boost
{
@@ -51,6 +53,53 @@ struct BOOST_SYMBOL_VISIBLE not_complete : public bad_graph
not_complete() : bad_graph("The graph must be complete.") {}
};
struct BOOST_SYMBOL_VISIBLE graph_exception : public std::exception
{
~graph_exception() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE = 0;
};
struct BOOST_SYMBOL_VISIBLE bad_parallel_edge : public graph_exception
{
std::string from;
std::string to;
mutable std::string statement;
bad_parallel_edge(const std::string& i, const std::string& j)
: from(i), to(j)
{
}
~bad_parallel_edge() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE
{
if (statement.empty())
statement = std::string("Failed to add parallel edge: (") + from
+ "," + to + ")\n";
return statement.c_str();
}
};
struct BOOST_SYMBOL_VISIBLE directed_graph_error : public graph_exception
{
~directed_graph_error() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE
{
return "read_graphviz: "
"Tried to read a directed graph into an undirected graph.";
}
};
struct BOOST_SYMBOL_VISIBLE undirected_graph_error : public graph_exception
{
~undirected_graph_error() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE
{
return "read_graphviz: "
"Tried to read an undirected graph into a directed graph.";
}
};
} // namespace boost
#endif // BOOST_GRAPH_EXCEPTION_HPP
@@ -11,6 +11,7 @@
#include <boost/mpl/if.hpp>
#include <boost/mpl/and.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/type_traits/is_same.hpp>
namespace boost
+2
View File
@@ -11,7 +11,9 @@
#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
+1 -2
View File
@@ -19,6 +19,7 @@
#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>
@@ -448,8 +449,6 @@ namespace graph
} // namespace graph
#include <boost/graph/iteration_macros.hpp>
template < class PropertyIn, class PropertyOut, class Graph >
void copy_vertex_property(PropertyIn p_in, PropertyOut p_out, Graph& g)
{
+5 -1
View File
@@ -16,12 +16,16 @@
#include <boost/lexical_cast.hpp>
#include <boost/any.hpp>
#include <boost/type_traits/is_convertible.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/dll_import_export.hpp>
#include <boost/graph/graphviz.hpp> // for exceptions
#include <boost/graph/exception.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/vector.hpp>
#include <boost/mpl/find.hpp>
#include <boost/mpl/for_each.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/property_tree/detail/xml_parser_utils.hpp>
#include <boost/throw_exception.hpp>
#include <exception>
+1 -47
View File
@@ -18,6 +18,7 @@
#include <string>
#include <boost/property_map/property_map.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/graph/exception.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/graph/properties.hpp>
#include <boost/graph/subgraph.hpp>
@@ -649,53 +650,6 @@ void write_graphviz_dp(std::ostream& out, const Graph& g,
/////////////////////////////////////////////////////////////////////////////
// Graph reader exceptions
/////////////////////////////////////////////////////////////////////////////
struct BOOST_SYMBOL_VISIBLE graph_exception : public std::exception
{
~graph_exception() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE = 0;
};
struct BOOST_SYMBOL_VISIBLE bad_parallel_edge : public graph_exception
{
std::string from;
std::string to;
mutable std::string statement;
bad_parallel_edge(const std::string& i, const std::string& j)
: from(i), to(j)
{
}
~bad_parallel_edge() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE
{
if (statement.empty())
statement = std::string("Failed to add parallel edge: (") + from
+ "," + to + ")\n";
return statement.c_str();
}
};
struct BOOST_SYMBOL_VISIBLE directed_graph_error : public graph_exception
{
~directed_graph_error() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE
{
return "read_graphviz: "
"Tried to read a directed graph into an undirected graph.";
}
};
struct BOOST_SYMBOL_VISIBLE undirected_graph_error : public graph_exception
{
~undirected_graph_error() throw() BOOST_OVERRIDE {}
const char* what() const throw() BOOST_OVERRIDE
{
return "read_graphviz: "
"Tried to read an undirected graph into a directed graph.";
}
};
struct BOOST_SYMBOL_VISIBLE bad_graphviz_syntax : public graph_exception
{
std::string errmsg;
+37 -15
View File
@@ -153,13 +153,14 @@ namespace hawick_circuits_detail
public:
hawick_circuits_from(Graph const& graph, Visitor& visitor,
VertexIndexMap const& vim, Stack& stack, ClosedMatrix& closed,
VerticesSize n_vertices)
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());
@@ -224,6 +225,10 @@ namespace hawick_circuits_detail
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
@@ -249,13 +254,19 @@ namespace hawick_circuits_detail
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;
}
if (found_circuit)
bool const finish_circuit = (found_circuit || truncate_search);
if (finish_circuit)
unblock(v);
else
for (AdjacencyIterator w_it = boost::begin(adj_vertices);
@@ -274,7 +285,7 @@ namespace hawick_circuits_detail
BOOST_ASSERT(v == stack_.back());
stack_.pop_back();
return found_circuit;
return finish_circuit;
}
public:
@@ -287,12 +298,14 @@ namespace hawick_circuits_detail
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)
Visitor /* by value */ visitor, VertexIndexMap const& vertex_index_map,
unsigned int max_length)
{
typedef graph_traits< Graph > Traits;
typedef typename Traits::vertex_descriptor Vertex;
@@ -322,7 +335,8 @@ namespace hawick_circuits_detail
// 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);
graph, visitor, vertex_index_map, stack, closed, n_vertices,
max_length);
sub_algo(*start);
stack.clear();
typename ClosedMatrix::iterator row, last_row = closed.end();
@@ -333,30 +347,35 @@ namespace hawick_circuits_detail
template < typename GetAdjacentVertices, typename Graph, typename Visitor >
void call_hawick_circuits(
Graph const& graph, BOOST_FWD_REF(Visitor) visitor)
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));
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)
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));
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)
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));
boost::forward< Graph >(graph), boost::forward< Visitor >(visitor),
max_length);
}
/*!
@@ -366,21 +385,24 @@ void hawick_circuits(BOOST_FWD_REF(Graph) graph, BOOST_FWD_REF(Visitor) visitor)
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)
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));
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)
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));
boost::forward< Graph >(graph), boost::forward< Visitor >(visitor),
max_length);
}
} // end namespace boost
+109 -37
View File
@@ -15,6 +15,8 @@
#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>
@@ -31,22 +33,20 @@ namespace detail
template < typename Graph1, typename Graph2, typename IsoMapping,
typename Invariant1, typename Invariant2, typename IndexMap1,
typename IndexMap2 >
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 invar1_value;
typedef typename Invariant2::result_type invar2_value;
typedef typename Invariant1::result_type invariant_t;
const Graph1& G1;
const Graph2& G2;
IsoMapping f;
Invariant1 invariant1;
Invariant2 invariant2;
std::size_t max_invariant;
IndexMap1 index_map1;
IndexMap2 index_map2;
@@ -81,17 +81,20 @@ namespace detail
friend struct compare_multiplicity;
struct compare_multiplicity
{
compare_multiplicity(Invariant1 invariant1, size_type* multiplicity)
: invariant1(invariant1), multiplicity(multiplicity)
compare_multiplicity(Invariant1 invariant1, const InvariantCountMap& multiplicity)
: invariant1(invariant1), multiplicity(&multiplicity)
{
}
bool operator()(const vertex1_t& x, const vertex1_t& y) const
{
return multiplicity[invariant1(x)]
< multiplicity[invariant1(y)];
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;
size_type* multiplicity;
const InvariantCountMap* multiplicity;
};
struct record_dfs_order : default_dfs_visitor
@@ -138,14 +141,13 @@ namespace detail
public:
isomorphism_algo(const Graph1& G1, const Graph2& G2, IsoMapping f,
Invariant1 invariant1, Invariant2 invariant2,
std::size_t max_invariant, IndexMap1 index_map1,
std::size_t /* max_invariant */, IndexMap1 index_map1,
IndexMap2 index_map2)
: G1(G1)
, G2(G2)
, f(f)
, invariant1(invariant1)
, invariant2(invariant2)
, max_invariant(max_invariant)
, index_map1(index_map1)
, index_map2(index_map2)
{
@@ -159,36 +161,63 @@ namespace detail
);
}
// 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();
{
std::vector< invar1_value > invar1_array;
BGL_FORALL_VERTICES_T(v, G1, Graph1)
invar1_array.push_back(invariant1(v));
sort(invar1_array);
// 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< invar2_value > invar2_array;
BGL_FORALL_VERTICES_T(v, G2, Graph2)
invar2_array.push_back(invariant2(v));
sort(invar2_array);
if (!equal(invar1_array, invar2_array))
return false;
}
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);
{
std::vector< size_type > multiplicity(max_invariant, 0);
BGL_FORALL_VERTICES_T(v, G1, Graph1)
++multiplicity.at(invariant1(v));
sort(
V_mult, compare_multiplicity(invariant1, &multiplicity[0]));
}
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<
@@ -366,6 +395,9 @@ namespace detail
{
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:
@@ -413,6 +445,42 @@ namespace detail
}
}
}
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 >
@@ -486,7 +554,7 @@ 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,
Invariant1 invariant1, Invariant2 invariant2, std::size_t /* max_invariant */,
IndexMap1 index_map1, IndexMap2 index_map2)
{
@@ -500,11 +568,16 @@ bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f,
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, size_type, vertex1_t >));
(AdaptableUnaryFunctionConcept< Invariant1, invariant1_t, vertex1_t >));
BOOST_CONCEPT_ASSERT(
(AdaptableUnaryFunctionConcept< Invariant2, size_type, vertex2_t >));
(AdaptableUnaryFunctionConcept< Invariant2, invariant2_t, vertex2_t >));
// Property map requirements
BOOST_CONCEPT_ASSERT(
@@ -527,7 +600,7 @@ bool isomorphism(const Graph1& G1, const Graph2& G2, IsoMapping f,
detail::isomorphism_algo< Graph1, Graph2, IsoMapping, Invariant1,
Invariant2, IndexMap1, IndexMap2 >
algo(G1, G2, f, invariant1, invariant2, max_invariant, index_map1,
algo(G1, G2, f, invariant1, invariant2, 0, index_map1,
index_map2);
return algo.test_isomorphism();
}
@@ -574,8 +647,7 @@ namespace detail
return isomorphism(G1, G2, f,
choose_param(get_param(params, vertex_invariant1_t()), invariant1),
choose_param(get_param(params, vertex_invariant2_t()), invariant2),
choose_param(get_param(params, vertex_max_invariant_t()),
(invariant2.max)()),
0,
index_map1, index_map2);
}
@@ -654,7 +726,7 @@ namespace graph
make_shared_array_property_map(
num_vertices(g1), vertex2_t(), index1_map)),
invariant1, invariant2,
arg_pack[_vertex_max_invariant | (invariant2.max)()],
0,
index1_map, index2_map);
}
};
+52 -2
View File
@@ -18,7 +18,9 @@
#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.
@@ -260,6 +262,54 @@ namespace graph_detail
}
//@}
/** @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
@@ -451,7 +501,7 @@ public:
/** Remove the vertex with the given label. */
void remove_vertex(Label const& l)
{
return boost::remove_vertex(vertex(l), _graph);
return graph_detail::remove_labeled_vertex(_map, _graph, l);
}
/** Return a descriptor for the given label. */
@@ -734,7 +784,7 @@ inline typename LABELED_GRAPH::degree_size_type degree(
template < LABELED_GRAPH_PARAMS >
inline std::pair< typename LABELED_GRAPH::adjacency_iterator,
typename LABELED_GRAPH::adjacency_iterator >
adjacenct_vertices(
adjacent_vertices(
typename LABELED_GRAPH::vertex_descriptor v, LABELED_GRAPH const& g)
{
return adjacent_vertices(v, g.graph());
+2
View File
@@ -24,6 +24,8 @@
#include <vector>
#include <algorithm>
#include <boost/throw_exception.hpp>
namespace boost
{
namespace graph
@@ -14,6 +14,7 @@
#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
+2
View File
@@ -9,6 +9,8 @@
#ifndef BOOST_GRAPH_POINT_TRAITS_HPP
#define BOOST_GRAPH_POINT_TRAITS_HPP
#include <cstddef>
namespace boost
{
namespace graph
@@ -431,6 +431,10 @@ namespace detail
}
}
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
@@ -11,6 +11,7 @@
#include <iterator>
#include <utility>
#include <boost/graph/graph_traits.hpp>
#include <boost/random/uniform_01.hpp>
#include <boost/random/uniform_int.hpp>
@@ -15,6 +15,7 @@
#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>
+7 -5
View File
@@ -10,14 +10,16 @@
#ifndef BOOST_GRAPH_TOPOLOGY_HPP
#define BOOST_GRAPH_TOPOLOGY_HPP
#include <boost/config/no_tr1/cmath.hpp>
#include <cmath>
#include <boost/random/uniform_01.hpp>
#include <boost/random/linear_congruential.hpp>
#include <boost/math/constants/constants.hpp> // For root_two
#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
+2
View File
@@ -41,6 +41,8 @@
#include <string>
#include <ostream>
#include <boost/graph/graph_traits.hpp>
namespace boost
{
@@ -6,6 +6,8 @@
#ifndef BOOST_DETAIL_DISJOINT_SETS_HPP
#define BOOST_DETAIL_DISJOINT_SETS_HPP
#include <cassert>
namespace boost
{
@@ -50,13 +52,11 @@ namespace detail
/* the postcondition of link sets is:
component_representative(i) == component_representative(j)
*/
template < class ParentPA, class RankPA, class Vertex,
class ComponentRepresentative >
inline void link_sets(ParentPA p, RankPA rank, Vertex i, Vertex j,
ComponentRepresentative comp_rep)
template < class ParentPA, class RankPA, class Vertex>
inline void link_sets(ParentPA p, RankPA rank, Vertex i, Vertex j)
{
i = comp_rep(p, i);
j = comp_rep(p, j);
assert(i == get(p, i));
assert(j == get(p, j));
if (i == j)
return;
if (get(rank, i) > get(rank, j))
+2 -2
View File
@@ -72,7 +72,7 @@ public:
// 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, rep);
detail::link_sets(parent, rank, x, y);
}
// Union-Set - union the two sets containing vertex x and y
@@ -146,7 +146,7 @@ public:
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), rep);
detail::link_sets(&parent[0], &rank[0], get(id, x), get(id, y));
}
template < class Element > inline void union_set(Element x, Element y)
{
+2 -1
View File
@@ -6,6 +6,7 @@
#ifndef BOOST_PROPERTY_HPP
#define BOOST_PROPERTY_HPP
#include <boost/config.hpp>
#include <boost/mpl/bool.hpp>
#include <boost/mpl/if.hpp>
#include <boost/mpl/has_xxx.hpp>
@@ -30,7 +31,7 @@ template < class Tag, class T, class Base = no_property > struct property
// copy constructor and assignment operator will be generated by compiler
T m_value;
Base m_base;
BOOST_ATTRIBUTE_NO_UNIQUE_ADDRESS Base m_base;
};
// Kinds of properties
+2 -2
View File
@@ -11,7 +11,7 @@
"Iterators"
],
"maintainers": [
"K. Noel Belcourt <kbelco -at- sandia.gov>"
"Jeremy W. Murphy <jeremy.william.murphy -at- gmail.com>"
],
"cxxstd": "03"
"cxxstd": "14"
}
+27 -11
View File
@@ -53,6 +53,7 @@ namespace boost
namespace read_graphviz_detail
{
static const long max_subgraph_nesting_level = 255;
struct token
{
enum token_type
@@ -207,7 +208,7 @@ namespace read_graphviz_detail
tokenizer(const std::string& str) : begin(str.begin()), end(str.end())
{
std::string end_of_token = "(?=(?:\\W))";
// std::string end_of_token = "(?=(?:\\W))"; // SEHE: unused?
std::string whitespace = "(?:\\s+)";
std::string slash_slash_comment = "(?://.*?$)";
std::string slash_star_comment = "(?:/\\*.*?\\*/)";
@@ -527,6 +528,7 @@ namespace read_graphviz_detail
std::map< subgraph_name, subgraph_info > subgraphs;
std::string current_subgraph_name;
int sgcounter; // Counter for anonymous subgraphs
long sgnesting_level;
std::set< std::pair< node_name, node_name > >
existing_edges; // Used for checking in strict graphs
@@ -538,7 +540,7 @@ namespace read_graphviz_detail
subgraph_member_list& current_members() { return current().members; }
parser(const std::string& gr, parser_result& result)
: the_tokenizer(gr), lookahead(), r(result), sgcounter(0)
: the_tokenizer(gr), lookahead(), r(result), sgcounter(0), sgnesting_level(0)
{
current_subgraph_name = "___root___";
current() = subgraph_info(); // Initialize root graph
@@ -773,10 +775,18 @@ namespace read_graphviz_detail
bool is_anonymous = true;
if (first_token.type == token::kw_subgraph)
{
if (peek().type == token::identifier)
switch (peek().type)
{
case token::identifier:
name = get().normalized_value;
is_anonymous = false;
break;
case token::left_brace:
is_anonymous = true;
break;
default:
error("Subgraph reference needs a name");
break;
}
}
if (is_anonymous)
@@ -790,25 +800,30 @@ namespace read_graphviz_detail
= current(); // Initialize properties and defaults
subgraphs[name].members.clear(); // Except member list
}
if (first_token.type == token::kw_subgraph
&& peek().type != token::left_brace)
if (!is_anonymous && peek().type != token::left_brace)
{
if (is_anonymous)
error("Subgraph reference needs a name");
return name;
}
subgraph_name old_sg = current_subgraph_name;
if (++sgnesting_level > max_subgraph_nesting_level)
{
error("Exceeded maximum subgraph nesting level");
}
current_subgraph_name = name;
if (peek().type == token::left_brace)
get();
else
error("Wanted left brace to start subgraph");
if (first_token.type != token::left_brace)
{
if (peek().type == token::left_brace)
get();
else
error("Wanted left brace to start subgraph");
}
parse_stmt_list();
if (peek().type == token::right_brace)
get();
else
error("Wanted right brace to end subgraph");
current_subgraph_name = old_sg;
sgnesting_level -= 1;
return name;
}
@@ -882,6 +897,7 @@ namespace read_graphviz_detail
"port location");
}
}
break;
default:
break;
}
+7 -4
View File
@@ -47,7 +47,10 @@ alias graph_test_regular :
[ run undirected_dfs.cpp ]
[ compile dfs_cc.cpp ]
[ compile dijkstra_cc.cpp ]
[ run dijkstra_heap_performance.cpp /boost/timer//boost_timer : 10000 ]
# Performance benchmark
#[ run dijkstra_heap_performance.cpp /boost/timer//boost_timer : 10000 ]
[ run dijkstra_no_color_map_compare.cpp : 10000 ]
[ run disjoint_set_test.cpp ]
[ run dominator_tree_test.cpp ]
@@ -70,8 +73,7 @@ alias graph_test_regular :
[ run graph.cpp : : : <define>TEST=9 : graph_9 ]
[ compile graph_concepts.cpp ]
[ run graphviz_test.cpp
../build//boost_graph
../../regex/build//boost_regex : --log_level=all ]
../build//boost_graph : --log_level=all ]
[ run metis_test.cpp : $(METIS_INPUT_FILE) ]
[ run gursoy_atun_layout_test.cpp : : : [ requires cxx11_noexcept cxx11_rvalue_references sfinae_expr cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_tuple cxx11_hdr_initializer_list cxx11_hdr_chrono cxx11_thread_local cxx11_constexpr cxx11_nullptr cxx11_numeric_limits cxx11_decltype cxx11_hdr_array cxx11_hdr_atomic cxx11_hdr_type_traits cxx11_allocator cxx11_explicit_conversion_operators ] ]
[ run layout_test.cpp : : : <test-info>always_show_run_output <toolset>intel:<debug-symbols>off [ requires cxx11_noexcept cxx11_rvalue_references sfinae_expr cxx11_auto_declarations cxx11_lambdas cxx11_unified_initialization_syntax cxx11_hdr_tuple cxx11_hdr_initializer_list cxx11_hdr_chrono cxx11_thread_local cxx11_constexpr cxx11_nullptr cxx11_numeric_limits cxx11_decltype cxx11_hdr_array cxx11_hdr_atomic cxx11_hdr_type_traits cxx11_allocator cxx11_explicit_conversion_operators ] ]
@@ -114,7 +116,7 @@ alias graph_test_regular :
[ run weighted_matching_test.cpp ]
[ run max_flow_test.cpp ]
[ run boykov_kolmogorov_max_flow_test.cpp ]
[ run cycle_ratio_tests.cpp ../build//boost_graph ../../regex/build//boost_regex : $(CYCLE_RATIO_INPUT_FILE) ]
[ run cycle_ratio_tests.cpp ../build//boost_graph : $(CYCLE_RATIO_INPUT_FILE) ]
[ run basic_planarity_test.cpp ]
[ run make_connected_test.cpp ]
[ run make_bicon_planar_test.cpp ]
@@ -122,6 +124,7 @@ alias graph_test_regular :
[ run named_vertices_test.cpp ]
[ run r_c_shortest_paths_test.cpp ]
[ run rcsp_custom_vertex_id.cpp ]
[ run rcsp_single_solution.cpp ]
[ run is_straight_line_draw_test.cpp ]
[ run metric_tsp_approx.cpp /boost/timer//boost_timer : metric_tsp_approx.graph : : ]
[ compile dimacs.cpp ]
+1 -1
View File
@@ -233,7 +233,7 @@ int main(int argc, char* argv[])
if (dir_itr->path().extension() != dimacs_extension)
continue;
std::cout << "Testing " << dir_itr->path().leaf() << "... ";
std::cout << "Testing " << dir_itr->path().filename() << "... ";
BOOST_TEST(test_graph(dir_itr->path().string()) == 0);
std::cout << std::endl;
+114 -7
View File
@@ -174,14 +174,109 @@ template < typename EdgeDescriptor > struct Link
EdgeDescriptor edge_reverse;
};
typedef adjacency_list_traits< vecS, vecS, directedS > tTraits;
typedef Node< tTraits::edge_descriptor > tVertex;
typedef Link< tTraits::edge_descriptor > tEdge;
typedef adjacency_list< vecS, vecS, directedS, tVertex, tEdge > tBundleGraph;
namespace boost
{
template <> struct property_map< tBundleGraph, edge_capacity_t >
{
typedef adj_list_edge_property_map< directed_tag, long, long&, size_t,
tEdge, long tEdge::* >
type;
typedef adj_list_edge_property_map< directed_tag, long, const long&, size_t,
const tEdge, long tEdge::* >
const_type;
};
template <> struct property_map< tBundleGraph, edge_residual_capacity_t >
{
typedef adj_list_edge_property_map< directed_tag, long, long&, size_t,
tEdge, long tEdge::* >
type;
typedef adj_list_edge_property_map< directed_tag, long, const long&, size_t,
const tEdge, long tEdge::* >
const_type;
};
template <> struct property_map< tBundleGraph, edge_reverse_t >
{
typedef adj_list_edge_property_map< directed_tag, tTraits::edge_descriptor,
tTraits::edge_descriptor&, size_t, tEdge,
tTraits::edge_descriptor tEdge::* >
type;
typedef adj_list_edge_property_map< directed_tag, tTraits::edge_descriptor,
const tTraits::edge_descriptor&, size_t, const tEdge,
tTraits::edge_descriptor tEdge::* >
const_type;
};
template <> struct property_map< tBundleGraph, vertex_predecessor_t >
{
typedef vec_adj_list_vertex_property_map< tBundleGraph, tBundleGraph*,
tTraits::edge_descriptor, tTraits::edge_descriptor&,
tTraits::edge_descriptor tVertex::* >
type;
typedef vec_adj_list_vertex_property_map< tBundleGraph, const tBundleGraph*,
tTraits::edge_descriptor, const tTraits::edge_descriptor&,
tTraits::edge_descriptor tVertex::* >
const_type;
};
template <> struct property_map< tBundleGraph, vertex_color_t >
{
typedef vec_adj_list_vertex_property_map< tBundleGraph, tBundleGraph*,
default_color_type, default_color_type&, default_color_type tVertex::* >
type;
typedef vec_adj_list_vertex_property_map< tBundleGraph, const tBundleGraph*,
default_color_type, const default_color_type&,
default_color_type tVertex::* >
const_type;
};
template <> struct property_map< tBundleGraph, vertex_distance_t >
{
typedef vec_adj_list_vertex_property_map< tBundleGraph, tBundleGraph*, long,
long&, long tVertex::* >
type;
typedef vec_adj_list_vertex_property_map< tBundleGraph, const tBundleGraph*,
long, const long&, long tVertex::* >
const_type;
};
}
property_map< tBundleGraph, edge_capacity_t >::const_type get(
edge_capacity_t, const tBundleGraph& g)
{
return get(&tEdge::edge_capacity, g);
}
property_map< tBundleGraph, edge_residual_capacity_t >::type get(
edge_residual_capacity_t, tBundleGraph& g)
{
return get(&tEdge::edge_residual_capacity, g);
}
property_map< tBundleGraph, edge_reverse_t >::const_type get(
edge_reverse_t, const tBundleGraph& g)
{
return get(&tEdge::edge_reverse, g);
}
property_map< tBundleGraph, vertex_predecessor_t >::type get(
vertex_predecessor_t, tBundleGraph& g)
{
return get(&tVertex::vertex_predecessor, g);
}
property_map< tBundleGraph, vertex_color_t >::type get(
vertex_color_t, tBundleGraph& g)
{
return get(&tVertex::vertex_color, g);
}
property_map< tBundleGraph, vertex_distance_t >::type get(
vertex_distance_t, tBundleGraph& g)
{
return get(&tVertex::vertex_distance, g);
}
long test_bundled_properties(int n_verts, int n_edges, std::size_t seed)
{
typedef adjacency_list_traits< vecS, vecS, directedS > tTraits;
typedef Node< tTraits::edge_descriptor > tVertex;
typedef Link< tTraits::edge_descriptor > tEdge;
typedef adjacency_list< vecS, vecS, directedS, tVertex, tEdge >
tBundleGraph;
tBundleGraph g;
graph_traits< tBundleGraph >::vertex_descriptor src, sink;
@@ -189,6 +284,8 @@ long test_bundled_properties(int n_verts, int n_edges, std::size_t seed)
= fill_random_max_flow_graph(g, get(&tEdge::edge_capacity, g),
get(&tEdge::edge_reverse, g), n_verts, n_edges, seed);
long flow_all_defaults_overload = boykov_kolmogorov_max_flow(g, src, sink);
long flow_unnamed_overload = boykov_kolmogorov_max_flow(g,
get(&tEdge::edge_capacity, g), get(&tEdge::edge_residual_capacity, g),
get(&tEdge::edge_reverse, g), get(&tVertex::vertex_predecessor, g),
@@ -204,6 +301,7 @@ long test_bundled_properties(int n_verts, int n_edges, std::size_t seed)
.distance_map(get(&tVertex::vertex_distance, g))
.vertex_index_map(get(vertex_index, g)));
BOOST_TEST(flow_all_defaults_overload == flow_unnamed_overload);
BOOST_TEST(flow_unnamed_overload == flow_named_overload);
return flow_named_overload;
}
@@ -211,11 +309,17 @@ long test_bundled_properties(int n_verts, int n_edges, std::size_t seed)
long test_overloads(int n_verts, int n_edges, std::size_t seed)
{
typedef adjacency_list_traits< vecS, vecS, directedS > tTraits;
typedef property< vertex_index_t, long,
property< vertex_predecessor_t, tTraits::edge_descriptor,
property< vertex_color_t, default_color_type,
property< vertex_distance_t, long > > > >
tVertexProperty;
typedef property< edge_capacity_t, long,
property< edge_residual_capacity_t, long,
property< edge_reverse_t, tTraits::edge_descriptor > > >
tEdgeProperty;
typedef adjacency_list< vecS, vecS, directedS, no_property, tEdgeProperty >
typedef adjacency_list< vecS, vecS, directedS, tVertexProperty,
tEdgeProperty >
tGraph;
tGraph g;
@@ -240,7 +344,10 @@ long test_overloads(int n_verts, int n_edges, std::size_t seed)
color_vec.begin(), get(vertex_index, g)),
get(vertex_index, g), src, sink);
long flow_overload_3 = boykov_kolmogorov_max_flow(g, src, sink);
BOOST_TEST(flow_overload_1 == flow_overload_2);
BOOST_TEST(flow_overload_2 == flow_overload_3);
return flow_overload_1;
}
+1 -1
View File
@@ -51,7 +51,7 @@ template < typename Graph > void test()
{
typedef erdos_renyi_iterator< boost::minstd_rand, Graph > er;
// Generate random graphs with 15 vertices and 15% probability
// Generate random graph with N vertices and probability P
// of edge connection.
static const size_t N = 20;
static const double P = 0.1;
+12 -5
View File
@@ -10,6 +10,7 @@
#define BOOST_GRAPH_TEST_CYCLE_TEST_HPP
#include <boost/assert.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/graph/directed_graph.hpp>
#include <boost/graph/erdos_renyi_generator.hpp>
#include <boost/graph/graph_traits.hpp>
@@ -52,11 +53,11 @@ struct cycle_validator
};
template < typename Graph, typename Algorithm >
void test_one(Algorithm algorithm)
void test_one(Algorithm algorithm, std::size_t num_cycles_expected)
{
typedef erdos_renyi_iterator< minstd_rand, Graph > er;
// Generate random graphs with 15 vertices and 15% probability
// Generate random graph with N vertices and probability P
// of edge connection.
static std::size_t const N = 20;
static double const P = 0.1;
@@ -70,16 +71,22 @@ void test_one(Algorithm algorithm)
cycle_validator vis(cycles);
algorithm(g, vis);
std::cout << "# cycles: " << vis.cycles << "\n";
BOOST_TEST(vis.cycles == num_cycles_expected);
}
} // end namespace cycle_test_detail
template < typename Algorithm > void cycle_test(Algorithm const& algorithm)
template < typename Algorithm > void cycle_test(Algorithm const& algorithm,
std::size_t num_cycles_expected_undirected,
std::size_t num_cycles_expected_directed)
{
std::cout << "*** undirected ***\n";
cycle_test_detail::test_one< boost::undirected_graph<> >(algorithm);
cycle_test_detail::test_one< boost::undirected_graph<> >(algorithm,
num_cycles_expected_undirected);
std::cout << "*** directed ***\n";
cycle_test_detail::test_one< boost::directed_graph<> >(algorithm);
cycle_test_detail::test_one< boost::directed_graph<> >(algorithm,
num_cycles_expected_directed);
}
#endif // !BOOST_GRAPH_TEST_CYCLE_TEST_HPP
+335 -266
View File
@@ -1,151 +1,192 @@
// Copyright 2004-5 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)
//
// graphviz_test.cpp - Test cases for the Boost.Spirit implementation of a
// Graphviz DOT Language reader.
// graphviz_test.cpp - Test cases for the Graphviz DOT Language reader
//
// Author: Ronald Garcia
#define BOOST_GRAPHVIZ_USE_ISTREAM
#include <boost/regex.hpp>
#include <boost/graph/graphviz.hpp>
#include <boost/assign/std/map.hpp>
#include <boost/assign.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/compressed_sparse_row_graph.hpp>
#include <boost/graph/graph_traits.hpp>
#include <boost/tuple/tuple.hpp>
#include <boost/property_map/dynamic_property_map.hpp>
#include <boost/core/lightweight_test.hpp>
#include <algorithm>
#include <string>
#include <boost/property_map/function_property_map.hpp>
#include <iostream>
#include <iterator>
#include <map>
#include <utility>
#include <cmath>
template<class T>
class close_to {
public:
explicit close_to(T f)
: f_(f) { }
typedef std::string node_t;
typedef std::pair< node_t, node_t > edge_t;
bool operator()(T l, T r) const {
return std::abs(l - r) <=
(std::max)(f_ * (std::max)(std::abs(l), std::abs(r)), T());
typedef float Mass;
typedef double Weight;
typedef std::map< node_t, Mass > expected_masses_t;
typedef std::map< edge_t, Weight > expected_weights_t;
#define MAP_MASSES boost::assign::list_of< std::pair< node_t, Mass > >
#define MAP_WEIGHTS boost::assign::list_of< std::pair< edge_t, Weight > >
struct Fixture
{
std::string graphviz_text;
size_t correct_num_vertices;
expected_masses_t masses;
expected_weights_t weights;
};
namespace Samples
{
namespace Directed
{
static Fixture const basic {
"digraph { a node [mass = 7.7] c e [mass = 6.66] }",
3,
MAP_MASSES("a", 0.0f)("c", 7.7f)("e", 6.66f),
expected_weights_t(),
};
static Fixture const basic_aliased {
"digraph { a node [mass = 7.7] \"a\" e [mass = 6.66] }",
2,
MAP_MASSES("a", 0.0f)("e", 6.66f),
expected_weights_t(),
};
static Fixture const full {
"digraph { a -> b eDge [weight = 7.7] "
"c -> d e-> f [weight = 6.66] "
"d ->e->a [weight=.5]}",
6,
expected_masses_t(),
MAP_WEIGHTS(edge_t("a", "b"), 0.0)(edge_t("c", "d"), 7.7)(
edge_t("e", "f"), 6.66)(edge_t("d", "e"), 0.5)(
edge_t("e", "a"), 0.5),
};
}
namespace Undirected
{
static Fixture const basic {
"graph { a nodE [mass = 7.7] c e [mass =\\\n6.66] }",
3,
MAP_MASSES("a", 0.0f)("c", 7.7f)("e", 6.66f),
expected_weights_t(),
};
static Fixture const full {
"graph { a -- b eDge [weight = 7.7] "
"c -- d e -- f [weight = 6.66] }",
6,
expected_masses_t(),
MAP_WEIGHTS(edge_t("a", "b"), 0.0)(edge_t("c", "d"), 7.7)(
edge_t("e", "f"), 6.66),
};
}
Fixture const all_directed[] {
Directed::basic,
Directed::basic_aliased,
Directed::full,
};
Fixture const all_undirected[] {
Undirected::basic,
Undirected::full,
};
} // Samples
namespace ComparisonDriver
{
template < class T > class close_to
{
public:
explicit close_to(T f) : f_(f) { assert(f >= 0); }
bool operator()(T l, T r) const
{
using std::abs;
return abs(l - r) <= f_ * (std::max)(abs(l), abs(r));
}
private:
T f_;
};
using namespace std;
using namespace boost;
using namespace boost::assign;
typedef std::string node_t;
typedef std::pair< node_t, node_t > edge_t;
typedef std::map< node_t, float > mass_map_t;
typedef std::map< edge_t, double > weight_map_t;
template < typename graph_t, typename NameMap, typename MassMap,
typename WeightMap >
bool test_graph(std::istream& dotfile, graph_t& graph,
std::size_t correct_num_vertices, mass_map_t const& masses,
weight_map_t const& weights, std::string const& node_id,
std::string const& g_name, NameMap name, MassMap mass, WeightMap weight);
template < typename graph_t >
bool test_graph(std::istream& dotfile, std::size_t correct_num_vertices,
mass_map_t const& masses, weight_map_t const& weights,
std::string const& node_id = "node_id",
std::string const& g_name = std::string())
bool test_graph(std::string const& text, graph_t& graph,
std::size_t correct_num_vertices, expected_masses_t const& expected_masses,
expected_weights_t const& expected_weights, std::string const& node_id,
std::string const& g_name, NameMap name_map, MassMap mass_map,
WeightMap weight_map)
{
graph_t g;
return test_graph(dotfile, g, correct_num_vertices, masses, weights,
node_id, g_name, get(vertex_name, g), get(vertex_color, g),
get(edge_weight, g));
}
template < typename graph_t, typename NameMap, typename MassMap,
typename WeightMap >
bool test_graph(std::istream& dotfile, graph_t& graph,
std::size_t correct_num_vertices, mass_map_t const& masses,
weight_map_t const& weights, std::string const& node_id,
std::string const& g_name, NameMap name, MassMap mass, WeightMap weight)
{
// Construct a graph and set up the dynamic_property_maps.
dynamic_properties dp(ignore_other_properties);
dp.property(node_id, name);
dp.property("mass", mass);
dp.property("weight", weight);
boost::dynamic_properties dp(boost::ignore_other_properties);
dp.property(node_id, name_map);
dp.property("mass", mass_map);
dp.property("weight", weight_map);
boost::ref_property_map< graph_t*, std::string > gname(
get_property(graph, graph_name));
get_property(graph, boost::graph_name));
dp.property("name", gname);
bool result = true;
#ifdef BOOST_GRAPHVIZ_USE_ISTREAM
if (read_graphviz(dotfile, graph, dp, node_id))
{
std::istringstream is(text);
if (read_graphviz(is, graph, dp, node_id))
#else
std::string data;
dotfile >> std::noskipws;
std::copy(std::istream_iterator< char >(dotfile),
std::istream_iterator< char >(), std::back_inserter(data));
if (read_graphviz(data.begin(), data.end(), graph, dp, node_id))
{
if (read_graphviz(text.begin(), text.end(), graph, dp, node_id))
#endif
{
// check correct vertex count
BOOST_TEST_EQ(num_vertices(graph), correct_num_vertices);
// check masses
if (!masses.empty())
if (!expected_masses.empty())
{
// assume that all the masses have been set
// for each vertex:
typename graph_traits< graph_t >::vertex_iterator i, j;
typename boost::graph_traits< graph_t >::vertex_iterator i, j;
for (boost::tie(i, j) = vertices(graph); i != j; ++i)
{
// - get its name
std::string node_name = get(name, *i);
// - get its mass
float node_mass = get(mass, *i);
BOOST_TEST(masses.find(node_name) != masses.end());
float ref_mass = masses.find(node_name)->second;
std::string node_name = get(name_map, *i);
Mass node_mass = get(mass_map, *i);
BOOST_TEST(
expected_masses.find(node_name) != expected_masses.end());
Mass ref_mass = expected_masses.find(node_name)->second;
// - compare the mass to the result in the table
BOOST_TEST_WITH(node_mass, ref_mass, close_to<float>(0.01f));
BOOST_TEST_WITH(node_mass, ref_mass, close_to< Mass >(0.0001f));
}
}
// check weights
if (!weights.empty())
if (!expected_weights.empty())
{
// assume that all weights have been set
/// for each edge:
typename graph_traits< graph_t >::edge_iterator i, j;
typename boost::graph_traits< graph_t >::edge_iterator i, j;
for (boost::tie(i, j) = edges(graph); i != j; ++i)
{
// - get its name
std::pair< std::string, std::string > edge_name = make_pair(
get(name, source(*i, graph)), get(name, target(*i, graph)));
std::pair< std::string, std::string > edge_name
= make_pair(get(name_map, source(*i, graph)),
get(name_map, target(*i, graph)));
// - get its weight
double edge_weight = get(weight, *i);
BOOST_TEST(weights.find(edge_name) != weights.end());
double ref_weight = weights.find(edge_name)->second;
// - compare the weight to teh result in the table
BOOST_TEST_WITH(edge_weight, ref_weight, close_to<double>(0.01));
Weight edge_weight = get(weight_map, *i);
BOOST_TEST(
expected_weights.find(edge_name) != expected_weights.end());
Weight ref_weight = expected_weights.find(edge_name)->second;
// - compare the weight to the result in the table
BOOST_TEST_WITH(
edge_weight, ref_weight, close_to< Weight >(0.000001));
}
}
if (!g_name.empty())
{
std::string parsed_name = get_property(graph, graph_name);
std::string parsed_name = get_property(graph, boost::graph_name);
BOOST_TEST(parsed_name == g_name);
}
}
@@ -158,262 +199,288 @@ bool test_graph(std::istream& dotfile, graph_t& graph,
return result;
}
// int test_main(int, char*[]) {
template < typename graph_t, typename NameMap, typename MassMap,
typename WeightMap >
bool test_graph(Fixture const& sample, graph_t& g, std::string const& node_id,
std::string const& g_name, NameMap name_map, MassMap mass_map,
WeightMap weight_map)
{
return test_graph(sample.graphviz_text, g, sample.correct_num_vertices,
sample.masses, sample.weights, node_id, g_name, name_map, mass_map,
weight_map);
}
typedef istringstream gs_t;
template < typename graph_t >
bool test_graph(std::string const& dottext, std::size_t correct_num_vertices,
expected_masses_t const& masses, expected_weights_t const& weights,
std::string const& node_id = "node_id", std::string const& g_name = "")
{
graph_t g;
return test_graph(dottext, g, correct_num_vertices, masses, weights,
node_id, g_name, get(boost::vertex_name, g),
get(boost::vertex_color, g), get(boost::edge_weight, g));
}
typedef property< vertex_name_t, std::string,
property< vertex_color_t, float > >
template < typename graph_t >
bool test_graph(Fixture const& sample, std::string const& node_id = "node_id",
std::string const& g_name = "")
{
graph_t g;
return test_graph(sample.graphviz_text, g, sample.correct_num_vertices,
sample.masses, sample.weights, node_id, g_name, //
get(boost::vertex_name, g), //
get(boost::vertex_color, g), //
get(boost::edge_weight, g) //
);
}
}
namespace Models
{
typedef boost::property< boost::vertex_name_t, std::string,
boost::property< boost::vertex_color_t, Mass > >
vertex_p;
typedef property< edge_weight_t, double > edge_p;
typedef property< graph_name_t, std::string > graph_p;
typedef boost::property< boost::edge_weight_t, Weight > edge_p;
typedef boost::property< boost::graph_name_t, std::string > graph_p;
struct vertex_p_bundled
typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::undirectedS,
vertex_p, edge_p, graph_p >
Graph;
typedef boost::adjacency_list< boost::vecS, boost::vecS, boost::directedS,
vertex_p, edge_p, graph_p >
DiGraph;
typedef boost::adjacency_list< boost::setS, boost::vecS, boost::directedS,
vertex_p, edge_p, graph_p >
DiGraphNoParallel;
struct VertexBundle
{
std::string name;
float color;
Mass mass;
};
struct edge_p_bundled
struct EdgeBundle
{
double weight;
Weight weight;
};
typedef boost::compressed_sparse_row_graph< boost::directedS, VertexBundle,
EdgeBundle, graph_p >
CSRBundledGraph;
typedef boost::compressed_sparse_row_graph< boost::directedS,
boost::no_property, boost::no_property, graph_p >
CSRGraph;
} // Models
// SEHE I intended for this to be able to pass __FUNCTION__ for reporting
// failures, but there seems to be no way to achieve this with lightweight_test
#define TEST_GRAPH(Model, ...) \
BOOST_TEST((ComparisonDriver::test_graph< Model >(__VA_ARGS__)));
// Basic directed graph tests
void test_basic_directed_graph_1()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 7.7f)("e", 6.66f);
gs_t gs("digraph { a node [mass = 7.7] c e [mass = 6.66] }");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST((test_graph< graph_t >(gs, 3, masses, weight_map_t())));
TEST_GRAPH(Models::DiGraph, Samples::Directed::basic);
}
void test_basic_directed_graph_2()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("e", 6.66f);
gs_t gs("digraph { a node [mass = 7.7] \"a\" e [mass = 6.66] }");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST((test_graph< graph_t >(gs, 2, masses, weight_map_t())));
TEST_GRAPH(Models::DiGraph, Samples::Directed::basic_aliased);
}
void test_basic_directed_graph_3()
{
weight_map_t weights;
insert(weights)(make_pair("a", "b"), 0.0)(make_pair("c", "d"), 7.7)(
make_pair("e", "f"), 6.66)(make_pair("d", "e"), 0.5)(
make_pair("e", "a"), 0.5);
gs_t gs("digraph { a -> b eDge [weight = 7.7] "
"c -> d e-> f [weight = 6.66] "
"d ->e->a [weight=.5]}");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST((test_graph< graph_t >(gs, 6, mass_map_t(), weights)));
TEST_GRAPH(Models::DiGraph, Samples::Directed::full);
}
// undirected graph with alternate node_id property name
void test_undirected_graph_alternate_node_id()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 7.7f)("e", 6.66f);
gs_t gs("graph { a node [mass = 7.7] c e [mass = 6.66] }");
typedef adjacency_list< vecS, vecS, undirectedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST(
(test_graph< graph_t >(gs, 3, masses, weight_map_t(), "nodenames")));
TEST_GRAPH(Models::Graph, Samples::Undirected::basic, "nodenames");
}
// Basic undirected graph tests
void test_basic_undirected_graph_1()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 7.7f)("e", 6.66f);
gs_t gs("graph { a node [mass = 7.7] c e [mass =\\\n6.66] }");
typedef adjacency_list< vecS, vecS, undirectedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST((test_graph< graph_t >(gs, 3, masses, weight_map_t())));
TEST_GRAPH(Models::Graph, Samples::Undirected::basic);
}
void test_basic_undirected_graph_2()
{
weight_map_t weights;
insert(weights)(make_pair("a", "b"), 0.0)(make_pair("c", "d"), 7.7)(
make_pair("e", "f"), 6.66);
gs_t gs("graph { a -- b eDge [weight = 7.7] "
"c -- d e -- f [weight = 6.66] }");
typedef adjacency_list< vecS, vecS, undirectedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST((test_graph< graph_t >(gs, 6, mass_map_t(), weights)));
TEST_GRAPH(Models::Graph, Samples::Undirected::full);
}
// Mismatch directed graph test
void test_mismatch_directed_graph()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 7.7f)("e", 6.66f);
gs_t gs("graph { a nodE [mass = 7.7] c e [mass = 6.66] }");
try
{
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p,
graph_p >
graph_t;
test_graph< graph_t >(gs, 3, masses, weight_map_t());
BOOST_ERROR("Failed to throw boost::undirected_graph_error.");
}
catch (boost::undirected_graph_error&)
{
}
catch (boost::directed_graph_error&)
{
BOOST_ERROR("Threw boost::directed_graph_error, should have thrown "
"boost::undirected_graph_error.");
}
BOOST_TEST_THROWS(TEST_GRAPH(Models::DiGraph, Samples::Undirected::basic),
boost::undirected_graph_error);
}
// Mismatch undirected graph test
void test_mismatch_undirected_graph()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 7.7f)("e", 6.66f);
gs_t gs("digraph { a node [mass = 7.7] c e [mass = 6.66] }");
try
{
typedef adjacency_list< vecS, vecS, undirectedS, vertex_p, edge_p,
graph_p >
graph_t;
test_graph< graph_t >(gs, 3, masses, weight_map_t());
BOOST_ERROR("Failed to throw boost::directed_graph_error.");
}
catch (boost::directed_graph_error&)
{
}
BOOST_TEST_THROWS(TEST_GRAPH(Models::Graph, Samples::Directed::basic),
boost::directed_graph_error);
}
// Complain about parallel edges
void test_complain_about_parallel_edges()
void test_parallel_edges()
{
weight_map_t weights;
insert(weights)(make_pair("a", "b"), 7.7);
gs_t gs("diGraph { a -> b [weight = 7.7] a -> b [weight = 7.7] }");
try
{
typedef adjacency_list< setS, vecS, directedS, vertex_p, edge_p,
graph_p >
graph_t;
test_graph< graph_t >(gs, 2, mass_map_t(), weights);
BOOST_ERROR("Failed to throw boost::bad_parallel_edge.");
}
catch (boost::bad_parallel_edge&)
{
}
}
// Handle parallel edges gracefully
void test_handle_parallel_edges_gracefully()
{
weight_map_t weights;
insert(weights)(make_pair("a", "b"), 7.7);
gs_t gs("digraph { a -> b [weight = 7.7] a -> b [weight = 7.7] }");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST((test_graph< graph_t >(gs, 2, mass_map_t(), weights)));
Fixture parallel {
"diGraph { a -> b [weight = 7.7] a -> b [weight = 7.7] }",
2,
expected_masses_t(),
MAP_WEIGHTS(edge_t("a", "b"), 7.7),
};
TEST_GRAPH(Models::DiGraph, parallel);
BOOST_TEST_THROWS(TEST_GRAPH(Models::DiGraphNoParallel, parallel),
boost::bad_parallel_edge);
}
// Graph Property Test 1
void test_graph_property_test_1()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 0.0f)("e", 6.66f);
gs_t gs("digraph { graph [name=\"foo \\\"escaped\\\"\"] a c e [mass = "
"6.66] }");
std::string graph_name("foo \"escaped\"");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST(
(test_graph< graph_t >(gs, 3, masses, weight_map_t(), "", graph_name)));
Fixture named {
"digraph { graph [name=\"foo \\\"escaped\\\"\"] a c e [mass = 6.66] "
"}",
3,
MAP_MASSES("a", 0.0f)("c", 0.0f)("e", 6.66f),
expected_weights_t(),
};
TEST_GRAPH(Models::DiGraph, named, "", "foo \"escaped\"");
}
// Graph Property Test 2
void test_graph_property_test_2()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 0.0f)("e", 6.66f);
gs_t gs("digraph { name=\"fo\"+ \"\\\no\" a c e [mass = 6.66] }");
std::string graph_name("foo");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST(
(test_graph< graph_t >(gs, 3, masses, weight_map_t(), "", graph_name)));
Fixture named {
"digraph { name=\"fo\"+ \"\\\no\" a c e [mass = 6.66] }",
3,
MAP_MASSES("a", 0.0f)("c", 0.0f)("e", 6.66f),
expected_weights_t(),
};
TEST_GRAPH(Models::DiGraph, named, "", "foo"); // SEHE why not "foo\no"?
}
// Graph Property Test 3 (HTML)
void test_graph_property_test_3()
{
mass_map_t masses;
insert(masses)("a", 0.0f)("c", 0.0f)("e", 6.66f);
std::string graph_name
= "<html title=\"x'\" title2='y\"'>foo<b><![CDATA[><bad "
"tag&>]]>bar</b>\n<br/>\nbaz</html>";
gs_t gs("digraph { name=" + graph_name + " a c e [mass = 6.66] }");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST(
(test_graph< graph_t >(gs, 3, masses, weight_map_t(), "", graph_name)));
Fixture html_named {
"digraph { name=" + graph_name + " a c e [mass = 6.66] }",
3,
MAP_MASSES("a", 0.0f)("c", 0.0f)("e", 6.66f),
expected_weights_t(),
};
TEST_GRAPH(Models::DiGraph, html_named, "", graph_name);
}
// Comments embedded in strings
void test_comments_embedded_in_strings()
{
gs_t gs("digraph { "
"a0 [ label = \"//depot/path/to/file_14#4\" ];"
"a1 [ label = \"//depot/path/to/file_29#9\" ];"
"a0 -> a1 [ color=gray ];"
"}");
typedef adjacency_list< vecS, vecS, directedS, vertex_p, edge_p, graph_p >
graph_t;
BOOST_TEST((test_graph< graph_t >(gs, 2, mass_map_t(), weight_map_t())));
std::string gv("digraph { "
"a0 [ label = \"//depot/path/to/file_14#4\" ];"
"a1 [ label = \"//depot/path/to/file_29#9\" ];"
"a0 -> a1 [ color=gray ];"
"}");
TEST_GRAPH(
Models::DiGraph, gv, 2, expected_masses_t(), expected_weights_t());
}
#if 0 // Currently broken
void test_basic_csr_directed_graph() {
weight_map_t weights;
insert( weights )(make_pair("a","b"),0.0)
(make_pair("c","d"),7.7)(make_pair("e","f"),6.66)
(make_pair("d","e"),0.5)(make_pair("e","a"),0.5);
gs_t gs("digraph { a -> b eDge [weight = 7.7] "
"c -> d e-> f [weight = 6.66] "
"d ->e->a [weight=.5]}");
typedef compressed_sparse_row_graph<directedS, vertex_p_bundled, edge_p_bundled, graph_p > graph_t;
BOOST_TEST((test_graph<graph_t>(gs,6,mass_map_t(),weights,"node_id","",&vertex_p_bundled::name,&vertex_p_bundled::color,&edge_p_bundled::weight)));
}
void test_basic_csr_directed_graph()
{
auto sample = Samples::Directed::full;
typedef Models::CSRBundledGraph graph_t;
graph_t g;
#ifdef UNSTABLE_PROPERTY_MAPS_FIXED // https://github.com/boostorg/graph/issues/373
BOOST_TEST((test_graph(gs, g, 6, mass_map_t(), weights, "node_id", "",
get(&vertex_p_bundled::name, g), // Warning, currently broken
get(&vertex_p_bundled::color, g), // Warning, currently broken
get(&edge_p_bundled::weight, g)) // Warning, currently broken
));
#else
typedef graph_t::vertex_descriptor V;
typedef graph_t::edge_descriptor E;
TEST_GRAPH(graph_t, sample, g, "node_id", "", //
boost::make_function_property_map< V >(
[&g](V v) -> std::string& { return g[v].name; }),
boost::make_function_property_map< V >(
[&g](V v) -> Mass& { return g[v].mass; }),
boost::make_function_property_map< E >(
[&g](E e) -> Weight& { return g[e].weight; }) //
);
#endif
}
void test_basic_csr_directed_graph_ext_props()
{
weight_map_t weights;
insert(weights)(make_pair("a", "b"), 0.0)(make_pair("c", "d"), 7.7)(
make_pair("e", "f"), 6.66)(make_pair("d", "e"), 0.5)(
make_pair("e", "a"), 0.5);
gs_t gs("digraph { a -> b eDge [weight = 7.7] "
"c -> d e-> f [weight = 6.66] "
"d ->e->a [weight=.5]}");
typedef compressed_sparse_row_graph< directedS, no_property, no_property,
graph_p >
graph_t;
graph_t g;
vector_property_map< std::string,
property_map< graph_t, vertex_index_t >::const_type >
vertex_name(get(vertex_index, g));
vector_property_map< float,
property_map< graph_t, vertex_index_t >::const_type >
vertex_color(get(vertex_index, g));
vector_property_map< double,
property_map< graph_t, edge_index_t >::const_type >
edge_weight(get(edge_index, g));
BOOST_TEST((test_graph(gs, g, 6, mass_map_t(), weights, "node_id", "",
vertex_name, vertex_color, edge_weight)));
auto sample = Samples::Directed::full;
using Models::CSRGraph;
CSRGraph g;
boost::property_map< CSRGraph, boost::vertex_index_t >::const_type vidx
= get(boost::vertex_index, g);
boost::property_map< CSRGraph, boost::edge_index_t >::const_type eidx
= get(boost::edge_index, g);
boost::vector_property_map< std::string,
boost::property_map< CSRGraph, boost::vertex_index_t >::const_type >
vertex_name(vidx);
boost::vector_property_map< Mass,
boost::property_map< CSRGraph, boost::vertex_index_t >::const_type >
vertex_mass(vidx);
boost::vector_property_map< Weight,
boost::property_map< CSRGraph, boost::edge_index_t >::const_type >
edge_weight(eidx);
TEST_GRAPH(CSRGraph, sample, g, "node_id", "", vertex_name, vertex_mass,
edge_weight);
}
void test_subgraphs()
{
// on the BGL side, the new parser doesn't support subgraphs
// however, the docs promise to support reading them on the input side as
// "syntactic sugar".
for (auto gv : {
Fixture { "digraph {}" },
Fixture { "digraph { 1 -> {} }", 1 },
Fixture { "digraph { 1 -> {2} }", 2 },
Fixture { "digraph { 1; { 2; 3; } }", 3 },
Fixture { "digraph { { 2; 3; } 1; }", 3 },
Fixture { "digraph { 1; subgraph { 2; 3; } }", 3 },
Fixture { "digraph { 1 -> subgraph { 2; 3; } }", 3 },
Fixture { "digraph { 1 -> subgraph hello { 2; 3; } }", 3 },
Fixture { "digraph { 1 -> subgraph clust_Hello { 2; 3; } }", 3 },
Fixture { "digraph { 1 -> subgraph \"hello\" { 2; 3; } }", 3 },
Fixture {
"digraph { {2} -> subgraph \"hello\" {{{{ 2; 3; }}}} }", 2 },
})
{
TEST_GRAPH(Models::DiGraph, gv);
}
}
void test_subgraph_nesting_limit() // issue #364
{
auto independent_nests = [=](unsigned level)
{
auto sg = std::string(level, '{') + " 2; 3; " + std::string(level, '}');
ComparisonDriver::test_graph< Models::DiGraph >(
{ "digraph{1->" + sg + "}", 3 });
ComparisonDriver::test_graph< Models::DiGraph >(
{ "digraph{1->" + sg + ";4->" + sg + "}", 4 });
};
constexpr unsigned limit = 255;
independent_nests(1);
independent_nests(limit / 2);
independent_nests(limit - 1);
independent_nests(limit); // edge-case
BOOST_TEST_THROWS(independent_nests(limit + 1), boost::bad_graphviz_syntax);
}
int main()
@@ -426,12 +493,14 @@ int main()
test_basic_undirected_graph_2();
test_mismatch_directed_graph();
test_mismatch_undirected_graph();
test_complain_about_parallel_edges();
test_handle_parallel_edges_gracefully();
test_parallel_edges();
test_graph_property_test_1();
test_graph_property_test_2();
test_graph_property_test_3();
test_comments_embedded_in_strings();
test_basic_csr_directed_graph_ext_props();
test_basic_csr_directed_graph();
test_subgraphs();
test_subgraph_nesting_limit();
return boost::report_errors();
}
+35 -4
View File
@@ -10,27 +10,58 @@
struct call_hawick_circuits
{
unsigned int max_length;
call_hawick_circuits(unsigned int ml = 0) : max_length(ml) {}
template < typename Graph, typename Visitor >
void operator()(Graph const& g, Visitor const& v) const
{
boost::hawick_circuits(g, v);
boost::hawick_circuits(g, v, max_length);
}
};
struct call_hawick_unique_circuits
{
unsigned int max_length;
call_hawick_unique_circuits(unsigned int ml = 0) : max_length(ml) {}
template < typename Graph, typename Visitor >
void operator()(Graph const& g, Visitor const& v) const
{
boost::hawick_unique_circuits(g, v);
boost::hawick_unique_circuits(g, v, max_length);
}
};
int main()
{
// The last two arguments to cycle_test() are the expected (correct)
// number of circuits in the undirected and directed test graphs.
std::cout << "---------hawick_circuits---------\n";
cycle_test(call_hawick_circuits());
cycle_test(call_hawick_circuits(), 30, 31);
std::cout << "\n\n---------hawick_unique_circuits---------\n";
cycle_test(call_hawick_unique_circuits());
cycle_test(call_hawick_unique_circuits(), 27, 24);
// Correct values for max_length = 0 to 10
// undirected
std::size_t nc1[] = { 30, 0, 22, 26, 28, 30, 30, 30, 30, 30, 30 };
// directed
std::size_t nc2[] = { 31, 0, 3, 7, 13, 17, 22, 24, 27, 30, 31 };
// undirected, unique
std::size_t nc3[] = { 27, 0, 19, 23, 25, 27, 27, 27, 27, 27, 27 };
// directed, unique
std::size_t nc4[] = { 24, 0, 3, 6, 10, 13, 17, 19, 21, 23, 24 };
for (unsigned int ml = 0; ml <= 10; ++ml) {
std::cout << "\n\n---------hawick_circuits(max_length = " << ml;
std::cout << ")---------\n";
cycle_test(call_hawick_circuits(ml), nc1[ml], nc2[ml]);
std::cout << "\n\n---------hawick_unique_circuits(max_length = " << ml;
std::cout << ")---------\n";
cycle_test(call_hawick_unique_circuits(ml), nc3[ml], nc4[ml]);
}
std::cout << "\n\n";
return boost::report_errors();
}
+163 -1
View File
@@ -57,7 +57,11 @@ template < typename Generator > struct random_functor
#endif
template < typename Graph1, typename Graph2 >
void randomly_permute_graph(const Graph1& g1, Graph2& g2)
std::map<
typename graph_traits< Graph1 >::vertex_descriptor,
typename graph_traits< Graph2 >::vertex_descriptor
>
randomly_permute_graph(const Graph1& g1, Graph2& g2)
{
// Need a clean graph to start with
BOOST_TEST(num_vertices(g2) == 0);
@@ -93,6 +97,8 @@ void randomly_permute_graph(const Graph1& g1, Graph2& g2)
{
add_edge(vertex_map[source(*e, g1)], vertex_map[target(*e, g1)], g2);
}
return vertex_map;
}
template < typename Graph >
@@ -243,11 +249,167 @@ void test_isomorphism(int n, double edge_probability)
}
}
template<typename Graph>
struct ColorFunctor {
typedef typename graph_traits< Graph >::vertex_descriptor argument_type;
typedef int result_type;
ColorFunctor(const Graph& g) : graph(g) {}
inline result_type operator() (argument_type v) const {
return get(vertex_color_t(), graph)(v);
}
inline result_type max() const {
result_type max_result = std::numeric_limits<result_type>::min();
typedef typename graph_traits< Graph >::vertex_iterator vertex_iter;
for(vertex_iter iter = vertices(graph).first; iter != vertices(graph).second; ++iter) {
max_result = std::max(max_result, this->operator()(*iter));
}
return max_result + 1;
}
const Graph& graph;
};
void test_colored_isomorphism(int n, double edge_probability)
{
using namespace boost::graph::keywords;
typedef adjacency_list< vecS, vecS, bidirectionalS, property< vertex_color_t, int > > graph1;
typedef adjacency_list< listS, listS, bidirectionalS,
property< vertex_index_t, int, property< vertex_color_t, int >
>
> graph2;
typedef graph_traits< graph1 >::vertex_descriptor vertex1_t;
typedef graph_traits< graph2 >::vertex_descriptor vertex2_t;
typedef std::map< vertex1_t, vertex2_t > vertex_map_t;
graph1 g1(n);
generate_random_digraph(g1, edge_probability);
graph2 g2;
vertex_map_t vertex_map = randomly_permute_graph(g1, g2);
std::vector< int > colors(n);
typedef std::vector< int >::iterator colors_iter;
colors_iter midpoint = colors.begin() + n / 2;
std::fill(colors.begin(), midpoint, 0);
std::fill(midpoint, colors.end(), 1);
random_generator_type gen;
#ifndef BOOST_NO_CXX98_RANDOM_SHUFFLE
random_functor< random_generator_type > rand_fun(gen);
std::random_shuffle(colors.begin(), colors.end(), rand_fun);
#else
std::shuffle(colors.begin(), colors.end(), gen);
#endif
int v_idx = 0;
for (graph1::vertex_iterator v = vertices(g1).first;
v != vertices(g1).second; ++v)
{
put(get(vertex_color_t(), g1), *v, colors[v_idx]);
put(get(vertex_color_t(), g2), vertex_map[*v], colors[v_idx]);
v_idx += 1;
}
v_idx = 0;
for (graph2::vertex_iterator v = vertices(g2).first;
v != vertices(g2).second; ++v)
{
put(get(vertex_index_t(), g2), *v, v_idx);
v_idx += 1;
}
typedef std::map< graph1::vertex_descriptor, graph2::vertex_descriptor > iso_map;
iso_map mapping;
bool isomorphism_correct;
clock_t start = clock();
BOOST_TEST(
isomorphism_correct = isomorphism(
g1,
g2,
isomorphism_map(make_assoc_property_map(mapping))
.vertex_invariant1(ColorFunctor<graph1>(g1))
.vertex_invariant2(ColorFunctor<graph2>(g2))
)
);
clock_t end = clock();
std::cout << "Elapsed time (clock cycles): " << (end - start) << std::endl;
bool verify_correct;
BOOST_TEST(verify_correct
= verify_isomorphism(g1, g2, make_assoc_property_map(mapping)));
if (!isomorphism_correct || !verify_correct)
{
// Output graph 1
{
std::ofstream out("colored_isomorphism_failure.bg1");
out << num_vertices(g1) << std::endl;
for (graph1::edge_iterator e = edges(g1).first;
e != edges(g1).second; ++e)
{
out << get(vertex_index_t(), g1, source(*e, g1)) << ' '
<< get(vertex_index_t(), g1, target(*e, g1)) << std::endl;
}
}
// Output graph 2
{
std::ofstream out("colored_isomorphism_failure.bg2");
out << num_vertices(g2) << std::endl;
for (graph2::edge_iterator e = edges(g2).first;
e != edges(g2).second; ++e)
{
out << get(vertex_index_t(), g2, source(*e, g2)) << ' '
<< get(vertex_index_t(), g2, target(*e, g2)) << std::endl;
}
}
}
bool map_contains_null_vertices = false;
{
typedef graph_traits< graph2 >::vertex_descriptor vertex2_t;
const vertex2_t g2_null_vertex = graph2::null_vertex();
typedef iso_map::iterator map_iter;
const map_iter end = mapping.end();
for(map_iter iter = mapping.begin(); iter != end; ++iter) {
if(iter->second == g2_null_vertex) {
map_contains_null_vertices = true;
break;
}
}
}
BOOST_TEST(!map_contains_null_vertices);
// Map is bijective if each vertex of the second graph occurs only once
{
typedef graph_traits< graph2 >::vertex_descriptor vertex2_t;
std::set< vertex2_t > vertex_set;
typedef iso_map::iterator map_iter;
const map_iter end = mapping.end();
for(map_iter iter = mapping.begin(); iter != end; ++iter) {
vertex_set.insert(iter->second);
}
BOOST_TEST(vertex_set.size() == mapping.size());
}
}
int main(int argc, char* argv[])
{
int n = argc < 3 ? 30 : boost::lexical_cast< int >(argv[1]);
double edge_prob = argc < 3 ? 0.45 : boost::lexical_cast< double >(argv[2]);
test_isomorphism(n, edge_prob);
test_colored_isomorphism(n, edge_prob);
return boost::report_errors();
}
+64 -3
View File
@@ -4,32 +4,60 @@
// Boost Software License, Version 1.0 (See accompanying file
// LICENSE_1_0.txt or http://www.boost.org/LICENSE_1_0.txt)
#include <iostream>
#include <string>
#include <set>
#include <boost/assert.hpp>
#include <boost/concept/assert.hpp>
#include <boost/range.hpp>
#include <boost/graph/graph_concepts.hpp>
#include <boost/graph/undirected_graph.hpp>
#include <boost/graph/directed_graph.hpp>
#include <boost/graph/labeled_graph.hpp>
#include "typestr.hpp"
using std::cout;
using std::string;
using namespace boost;
void test_concepts();
void test_norm();
void test_temp();
void test_bacon();
void test_remove_labeled_vertex();
void test_multiple_associative_container();
int main()
{
test_concepts();
test_norm();
test_temp();
test_bacon();
test_remove_labeled_vertex();
test_multiple_associative_container();
}
//////////////////////////////////////
// Graph Concepts
//////////////////////////////////////
void test_concepts()
{
// The labeled mutable graph hides the add_ and remove_ vertex functions
// from the mutable graph concept, so VertexMutableGraphConcept will not be
// tested here.
{
typedef labeled_graph< directed_graph<>, unsigned > Graph;
BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >));
BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< Graph >));
}
{
typedef labeled_graph< undirected_graph<>, unsigned > Graph;
BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
BOOST_CONCEPT_ASSERT((AdjacencyGraphConcept< Graph >));
BOOST_CONCEPT_ASSERT((EdgeMutableGraphConcept< Graph >));
}
}
//////////////////////////////////////
@@ -147,3 +175,36 @@ void test_bacon()
add_edge_by_label(bacon, slater, murder, g);
}
}
void test_remove_labeled_vertex()
{
typedef labeled_graph< directed_graph<>, string > Graph;
Graph g;
g.add_vertex("foo");
auto v = g.vertex("foo");
BOOST_ASSERT(v != nullptr);
g.remove_vertex("foo");
auto v2 = g.vertex("foo");
BOOST_ASSERT(v2 == nullptr);
}
void test_multiple_associative_container()
{
typedef labeled_graph<adjacency_list<listS, multisetS, directedS>, string, multimapS> Graph;
Graph g;
g.add_vertex("test");
g.add_vertex("test");
BOOST_ASSERT(num_vertices(g) == 2);
g.remove_vertex("test");
BOOST_ASSERT(num_vertices(g) == 1);
g.remove_vertex("test");
BOOST_ASSERT(num_vertices(g) == 0);
}
+380 -60
View File
@@ -9,6 +9,7 @@
#include <map>
#include <vector>
#include <string>
#include <boost/array.hpp>
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/connected_components.hpp>
#include <boost/graph/exception.hpp>
@@ -17,6 +18,7 @@
#include <boost/graph/maximum_adjacency_search.hpp>
#include <boost/graph/visitors.hpp>
#include <boost/graph/property_maps/constant_property_map.hpp>
#include <boost/make_shared.hpp>
#include <boost/property_map/property_map.hpp>
#include <boost/core/lightweight_test.hpp>
#include <boost/tuple/tuple.hpp>
@@ -44,54 +46,45 @@ struct edge_t
};
template < typename Graph, typename KeyedUpdatablePriorityQueue >
class mas_edge_connectivity_visitor : public boost::default_mas_visitor
class mas_test_visitor : public boost::default_mas_visitor
{
public:
typedef typename boost::graph_traits< Graph >::vertex_descriptor
vertex_descriptor;
typedef typename KeyedUpdatablePriorityQueue::key_type weight_type;
#if 0
mas_edge_connectivity_visitor(const mas_edge_connectivity_visitor<Graph, KeyedUpdatablePriorityQueue>& r)
: m_pq(r.m_pq), m_curr(r.m_curr), m_prev(r.m_prev),
m_reach_weight(r.m_reach_weight) {
BOOST_TEST_MESSAGE( "COPY CTOR" );
}
#endif
explicit mas_edge_connectivity_visitor(KeyedUpdatablePriorityQueue& pq)
: m_pq(pq)
, m_curr(new vertex_descriptor(0))
, m_prev(new vertex_descriptor(0))
, m_reach_weight(new weight_type(0))
{
// BOOST_TEST_MESSAGE( "CTOR" );
}
explicit mas_test_visitor(KeyedUpdatablePriorityQueue& pq)
: m_pq_(pq),
vertex_visit_order_(boost::make_shared< std::vector< vertex_descriptor > >()),
vertex_weights_when_visited_(boost::make_shared< std::vector< weight_type > >())
{}
void clear()
{
*m_curr = 0;
*m_prev = 0;
*m_reach_weight = 0;
vertex_visit_order_->clear();
vertex_weights_when_visited_->clear();
}
// template <typename Vertex> //, typename Graph>
// void start_vertex(Vertex u, const Graph& g) {
void start_vertex(vertex_descriptor u, const Graph& g)
{
*m_prev = *m_curr;
*m_curr = u;
// BOOST_TEST_MESSAGE( "Initializing Vertex(weight): " << u << "(" <<
// *m_reach_weight << ")" );
*m_reach_weight = get(m_pq.keys(), u);
vertex_visit_order_->push_back(u);
const weight_type u_weight = get(m_pq_.keys(), u);
vertex_weights_when_visited_->push_back(u_weight);
}
vertex_descriptor curr() const { return *m_curr; }
vertex_descriptor prev() const { return *m_prev; }
weight_type reach_weight() const { return *m_reach_weight; }
const std::vector<vertex_descriptor>& vertex_visit_order() const {
return *vertex_visit_order_;
}
const std::vector<weight_type>& vertex_weights_when_visited() const {
return *vertex_weights_when_visited_;
}
private:
const KeyedUpdatablePriorityQueue& m_pq;
boost::shared_ptr< vertex_descriptor > m_curr, m_prev;
boost::shared_ptr< weight_type > m_reach_weight;
const KeyedUpdatablePriorityQueue& m_pq_;
boost::shared_ptr< std::vector< vertex_descriptor > > vertex_visit_order_;
boost::shared_ptr< std::vector< weight_type > > vertex_weights_when_visited_;
};
// the example from Stoer & Wagner (1997)
@@ -105,10 +98,12 @@ void test0()
typedef boost::graph_traits< undirected_graph >::edge_descriptor
edge_descriptor;
edge_t edges[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 0, 4 }, { 1, 4 },
{ 1, 5 }, { 2, 6 }, { 3, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 } };
weight_type ws[] = { 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3 };
undirected_graph g(edges, edges + 12, ws, 8, 12);
boost::array< edge_t, 12 > edge_list = { { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 0, 4 }, { 1, 4 }, { 1, 5 },
{ 2, 6 }, { 3, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 } } };
const boost::array<weight_type, 12> ws = { 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3 };
const std::size_t vertices_count = 8;
undirected_graph g(edge_list.cbegin(), edge_list.cend(), ws.cbegin(), vertices_count, ws.size());
weight_map_type weights = get(boost::edge_weight, g);
@@ -134,7 +129,7 @@ void test0()
distances_type, std::greater< weight_type > >
pq(distances, indicesInHeap);
mas_edge_connectivity_visitor< undirected_graph,
mas_test_visitor< undirected_graph,
boost::d_ary_heap_indirect< vertex_descriptor, 22, indicesInHeap_type,
distances_type, std::greater< weight_type > > >
test_vis(pq);
@@ -146,28 +141,65 @@ void test0()
.vertex_assignment_map(assignments)
.max_priority_queue(pq));
BOOST_TEST_EQ(test_vis.curr(), vertex_descriptor(7));
BOOST_TEST_EQ(test_vis.prev(), vertex_descriptor(6));
BOOST_TEST_EQ(test_vis.reach_weight(), 5);
const boost::array< vertex_descriptor, vertices_count > expected_vertex_order1 = { 0, 4, 1, 5, 2, 3, 6, 7 };
const boost::array< weight_type, vertices_count > expected_weights_when_visited1 = { 9, 3, 4, 5, 3, 4, 5, 5 };
BOOST_TEST_ALL_EQ(
test_vis.vertex_visit_order().begin(),
test_vis.vertex_visit_order().end(),
expected_vertex_order1.cbegin(),
expected_vertex_order1.cend()
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_weights_when_visited().begin(),
test_vis.vertex_weights_when_visited().end(),
expected_weights_when_visited1.cbegin(),
expected_weights_when_visited1.cend()
);
test_vis.clear();
boost::maximum_adjacency_search(g,
boost::weight_map(weights)
.visitor(test_vis)
.root_vertex(*vertices(g).first)
.max_priority_queue(pq));
BOOST_TEST_EQ(test_vis.curr(), vertex_descriptor(7));
BOOST_TEST_EQ(test_vis.prev(), vertex_descriptor(6));
BOOST_TEST_EQ(test_vis.reach_weight(), 5);
BOOST_TEST_ALL_EQ(
test_vis.vertex_visit_order().begin(),
test_vis.vertex_visit_order().end(),
expected_vertex_order1.cbegin(),
expected_vertex_order1.cend()
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_weights_when_visited().begin(),
test_vis.vertex_weights_when_visited().end(),
expected_weights_when_visited1.cbegin(),
expected_weights_when_visited1.cend()
);
test_vis.clear();
boost::maximum_adjacency_search(
g, boost::weight_map(weights).visitor(test_vis).max_priority_queue(pq));
BOOST_TEST_EQ(test_vis.curr(), vertex_descriptor(7));
BOOST_TEST_EQ(test_vis.prev(), vertex_descriptor(6));
BOOST_TEST_EQ(test_vis.reach_weight(), 5);
BOOST_TEST_ALL_EQ(
test_vis.vertex_visit_order().begin(),
test_vis.vertex_visit_order().end(),
expected_vertex_order1.cbegin(),
expected_vertex_order1.cend()
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_weights_when_visited().begin(),
test_vis.vertex_weights_when_visited().end(),
expected_weights_when_visited1.cbegin(),
expected_weights_when_visited1.cend()
);
test_vis.clear();
boost::maximum_adjacency_search(g,
boost::weight_map(weights).visitor(
@@ -183,9 +215,23 @@ void test0()
boost::make_constant_property< edge_descriptor >(weight_type(1)))
.visitor(test_vis)
.max_priority_queue(pq));
BOOST_TEST_EQ(test_vis.curr(), vertex_descriptor(7));
BOOST_TEST_EQ(test_vis.prev(), vertex_descriptor(3));
BOOST_TEST_EQ(test_vis.reach_weight(), 2);
const boost::array< vertex_descriptor, vertices_count > expected_vertex_order2 = { 0, 1, 4, 5, 2, 6, 3, 7 };
const boost::array< weight_type, vertices_count > expected_weights_when_visited2 = { 9, 1, 2, 2, 1, 2, 2, 2 };
BOOST_TEST_ALL_EQ(
test_vis.vertex_visit_order().begin(),
test_vis.vertex_visit_order().end(),
expected_vertex_order2.cbegin(),
expected_vertex_order2.cend()
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_weights_when_visited().begin(),
test_vis.vertex_weights_when_visited().end(),
expected_weights_when_visited2.cbegin(),
expected_weights_when_visited2.cend()
);
}
// Check the unweighted case
@@ -197,9 +243,11 @@ void test1()
typedef boost::graph_traits< undirected_unweighted_graph >::edge_descriptor
edge_descriptor;
edge_t edge_list[] = { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 0, 4 }, { 1, 4 },
{ 1, 5 }, { 2, 6 }, { 3, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 } };
undirected_unweighted_graph g(edge_list, edge_list + 12, 8);
boost::array< edge_t, 12 > edge_list = { { { 0, 1 }, { 1, 2 }, { 2, 3 }, { 0, 4 }, { 1, 4 }, { 1, 5 },
{ 2, 6 }, { 3, 6 }, { 3, 7 }, { 4, 5 }, { 5, 6 }, { 6, 7 } } };
const std::size_t vertices_count = 8;
undirected_unweighted_graph g(edge_list.cbegin(), edge_list.cend(), vertices_count);
std::map< vertex_descriptor, vertex_descriptor > assignment;
boost::associative_property_map<
@@ -224,7 +272,7 @@ void test1()
distances_type, std::greater< weight_type > >
pq(distances, indicesInHeap);
mas_edge_connectivity_visitor< undirected_unweighted_graph,
mas_test_visitor< undirected_unweighted_graph,
boost::d_ary_heap_indirect< vertex_descriptor, 22, indicesInHeap_type,
distances_type, std::greater< weight_type > > >
test_vis(pq);
@@ -235,11 +283,26 @@ void test1()
.visitor(test_vis)
.max_priority_queue(pq));
BOOST_TEST_EQ(test_vis.curr(), vertex_descriptor(7));
BOOST_TEST_EQ(test_vis.prev(), vertex_descriptor(3));
BOOST_TEST_EQ(test_vis.reach_weight(), weight_type(2));
const boost::array< vertex_descriptor, vertices_count > expected_vertex_order1 = { 0, 1, 4, 5, 2, 6, 3, 7 };
const boost::array< weight_type, vertices_count > expected_weights_when_visited1 = { 9, 1, 2, 2, 1, 2, 2, 2 };
weight_type ws[] = { 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3 };
BOOST_TEST_ALL_EQ(
test_vis.vertex_visit_order().begin(),
test_vis.vertex_visit_order().end(),
expected_vertex_order1.cbegin(),
expected_vertex_order1.cend()
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_weights_when_visited().begin(),
test_vis.vertex_weights_when_visited().end(),
expected_weights_when_visited1.cbegin(),
expected_weights_when_visited1.cend()
);
test_vis.clear();
const boost::array<weight_type, 12> ws = { 2, 3, 4, 3, 2, 2, 2, 2, 2, 3, 1, 3 };
std::map< edge_descriptor, weight_type > wm;
weight_type i = 0;
@@ -253,9 +316,258 @@ void test1()
boost::maximum_adjacency_search(
g, boost::weight_map(ws_map).visitor(test_vis).max_priority_queue(pq));
BOOST_TEST_EQ(test_vis.curr(), vertex_descriptor(7));
BOOST_TEST_EQ(test_vis.prev(), vertex_descriptor(6));
BOOST_TEST_EQ(test_vis.reach_weight(), weight_type(5));
const boost::array< vertex_descriptor, vertices_count > expected_vertex_order2 = { 0, 4, 1, 5, 2, 3, 6, 7 };
const boost::array< weight_type, vertices_count > expected_weights_when_visited2 = { 9, 3, 4, 5, 3, 4, 5, 5 };
BOOST_TEST_ALL_EQ(
test_vis.vertex_visit_order().begin(),
test_vis.vertex_visit_order().end(),
expected_vertex_order2.cbegin(),
expected_vertex_order2.cend()
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_weights_when_visited().begin(),
test_vis.vertex_weights_when_visited().end(),
expected_weights_when_visited2.cbegin(),
expected_weights_when_visited2.cend()
);
}
typedef boost::graph_traits< undirected_unweighted_graph >::vertex_descriptor mas_test_vertex_descriptor;
typedef boost::graph_traits< undirected_unweighted_graph >::edge_descriptor mas_test_edge_descriptor;
typedef std::size_t mas_test_weight_type; // weight corresponds to the priority value in the priority queue.
typedef boost::shared_array_property_map< mas_test_weight_type, boost::property_map< undirected_graph, boost::vertex_index_t >::const_type > mas_test_distances_type;
typedef std::vector< mas_test_vertex_descriptor >::size_type mas_test_index_in_heap_type;
typedef boost::shared_array_property_map< mas_test_index_in_heap_type, boost::property_map< undirected_graph, boost::vertex_index_t >::const_type > mas_test_indicesInHeap_type;
const std::size_t mas_test_arity = 4;
typedef boost::d_ary_heap_indirect< mas_test_vertex_descriptor, mas_test_arity, mas_test_indicesInHeap_type, mas_test_distances_type, std::greater< mas_test_weight_type > > mas_test_maxheap_type;
typedef mas_test_visitor< undirected_unweighted_graph, mas_test_maxheap_type> mas_text_visitor_type;
template <typename Graph>
mas_test_maxheap_type create_mas_test_maxheap(const Graph& g) {
mas_test_distances_type distances = boost::make_shared_array_property_map(
num_vertices(g), mas_test_weight_type(0), get(boost::vertex_index, g));
mas_test_indicesInHeap_type indicesInHeap = boost::make_shared_array_property_map(
num_vertices(g), mas_test_index_in_heap_type(-1), get(boost::vertex_index, g));
return mas_test_maxheap_type(distances, indicesInHeap);
}
template <std::size_t edge_count, std::size_t vertices_count>
void test_weighted(
const boost::array<edge_t, edge_count>& edge_list,
const boost::array<mas_test_weight_type, edge_count> weights_list,
const boost::array<mas_test_vertex_descriptor, vertices_count>& expected_vertex_order,
const boost::array<mas_test_weight_type, vertices_count>& expected_weights_when_visited,
const mas_test_vertex_descriptor start_vertex = 0)
{
const undirected_unweighted_graph g(edge_list.cbegin(), edge_list.cend(), vertices_count);
mas_test_maxheap_type pq = create_mas_test_maxheap(g);
mas_text_visitor_type test_vis = mas_text_visitor_type(pq);
std::map< mas_test_edge_descriptor, mas_test_weight_type > weights_map;
std::size_t i = 0;
BGL_FORALL_EDGES(e, g, undirected_unweighted_graph)
{
weights_map[e] = weights_list[i];
++i;
}
boost::associative_property_map< std::map< mas_test_edge_descriptor, mas_test_weight_type > >
weights_boost_map(weights_map);
boost::maximum_adjacency_search(
g,
boost::weight_map(
weights_boost_map)
.visitor(test_vis)
.max_priority_queue(pq)
.root_vertex(start_vertex)
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_visit_order().begin(),
test_vis.vertex_visit_order().end(),
expected_vertex_order.cbegin(),
expected_vertex_order.cend()
);
BOOST_TEST_ALL_EQ(
test_vis.vertex_weights_when_visited().begin(),
test_vis.vertex_weights_when_visited().end(),
expected_weights_when_visited.cbegin(),
expected_weights_when_visited.cend()
);
}
template <std::size_t edge_count, std::size_t vertices_count>
void test_unweighted(
const boost::array<edge_t, edge_count>& edge_list,
const boost::array<mas_test_vertex_descriptor, vertices_count>& expected_vertex_order,
const boost::array<mas_test_weight_type, vertices_count>& expected_weights_when_visited,
const mas_test_vertex_descriptor start_vertex = 0)
{
boost::array<mas_test_weight_type, edge_count> weights_list;
for (std::size_t i = 0; i < edge_count; i++) {
weights_list[i] = 1;
}
test_weighted(
edge_list,
weights_list,
expected_vertex_order,
expected_weights_when_visited,
start_vertex);
}
void test2_noweights() {
const std::size_t edge_count = 1;
const std::size_t vertices_count = 2;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 } } };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 0, 1 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 1 };
test_unweighted(
edge_list,
expected_vertex_order,
expected_weights_when_visited
);
}
void test3_noweights() {
const std::size_t edge_count = 2;
const std::size_t vertices_count = 3;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 }, { 1, 2 } } };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 0, 1, 2 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 1, 1 };
test_unweighted(
edge_list,
expected_vertex_order,
expected_weights_when_visited
);
}
void test4_noweights() {
const std::size_t edge_count = 3;
const std::size_t vertices_count = 3;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 }, { 0, 2 }, { 1, 2 } } };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 0, 1, 2 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 1, 2 };
test_unweighted(
edge_list,
expected_vertex_order,
expected_weights_when_visited
);
}
// The example graph from Matula (1993)
void test5_Matula1993() {
const std::size_t edge_count = 24;
const std::size_t vertices_count = 12;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 }, { 0, 2 },
{ 0, 3 }, { 0, 9 }, { 1, 2 }, { 1, 4 }, { 1, 10 }, { 2, 5 }, { 2, 11 },
{ 3, 4 }, { 3, 5 }, { 3, 6 }, { 4, 5 }, { 4, 7 }, { 5, 8 }, { 6, 7 },
{ 6, 8 }, { 6, 9 }, { 7, 8 }, { 7, 10 }, { 8, 11 }, { 9, 10 },
{ 9, 11 }, { 10, 11 } } };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 0, 1, 2, 10, 9, 11, 6, 3, 7, 4, 8, 5 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 1, 2, 1, 2, 3, 1, 2, 2, 3, 3, 4 };
test_unweighted(
edge_list,
expected_vertex_order,
expected_weights_when_visited
);
}
// Testing with a different start vertex
void test6_noweights_start_vertex() {
const std::size_t edge_count = 2;
const std::size_t vertices_count = 3;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 }, { 1, 2 } } };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 1, 0, 2 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 1, 1 };
test_unweighted(
edge_list,
expected_vertex_order,
expected_weights_when_visited,
1
);
}
void test7_weights() {
const std::size_t edge_count = 2;
const std::size_t vertices_count = 3;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 }, { 1, 2 } } };
const boost::array< mas_test_weight_type, edge_count > weights_list = { 2, 6 };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 0, 1, 2 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 2, 6 };
test_weighted(
edge_list,
weights_list,
expected_vertex_order,
expected_weights_when_visited
);
}
void test8_weights() {
const std::size_t edge_count = 3;
const std::size_t vertices_count = 3;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 }, { 0, 2 }, { 1, 2 } } };
const boost::array< mas_test_weight_type, edge_count > weights_list = { 2, 6, 7 };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 0, 2, 1 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 6, 9 };
test_weighted(
edge_list,
weights_list,
expected_vertex_order,
expected_weights_when_visited
);
}
void test9_weights_start_vertex() {
const std::size_t edge_count = 3;
const std::size_t vertices_count = 3;
const boost::array< edge_t, edge_count > edge_list = { { { 0, 1 }, { 0, 2 }, { 1, 2 } } };
const boost::array< mas_test_weight_type, edge_count > weights_list = { 2, 6, 7 };
const boost::array< mas_test_vertex_descriptor, vertices_count > expected_vertex_order = { 1, 2, 0 };
const boost::array< mas_test_weight_type, vertices_count > expected_weights_when_visited = { vertices_count+1, 7, 8 };
test_weighted(
edge_list,
weights_list,
expected_vertex_order,
expected_weights_when_visited,
1
);
}
#include <boost/graph/iteration_macros_undef.hpp>
@@ -266,6 +578,14 @@ int main(int argc, char* argv[])
test_dir = argv[1];
test0();
test1();
test2_noweights();
test3_noweights();
test4_noweights();
test5_Matula1993();
test6_noweights_start_vertex();
test7_weights();
test8_weights();
test9_weights_start_vertex();
}
return boost::report_errors();
}
+1 -1
View File
@@ -302,7 +302,7 @@ int main(int argc, char* argv[])
if (dir_itr->path().extension() != dimacs_extension)
continue;
std::cerr << "Testing " << dir_itr->path().leaf() << "... ";
std::cerr << "Testing " << dir_itr->path().filename() << "... ";
BOOST_TEST(test_graph(dir_itr->path().string()) == 0);
std::cerr << std::endl;
+118
View File
@@ -0,0 +1,118 @@
//=======================================================================
// Copyright (c) 2024 Andrea Cassioli
// Author: Andrea Cassioli <cassioliandre@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)
//=======================================================================
#include <boost/graph/adjacency_list.hpp>
#include <boost/graph/r_c_shortest_paths.hpp>
#include <boost/core/lightweight_test.hpp>
struct edge_prop {
edge_prop(int c, int t) : cost(c), time(t) {}
int cost;
int time;
};
using graph_type = boost::adjacency_list<boost::vecS, boost::vecS, boost::bidirectionalS, std::string, edge_prop>;
using vertex_type = graph_type::vertex_descriptor;
using edge_type = graph_type::edge_descriptor;
using path_type = std::vector<edge_type>;
class dominance
{
public:
template<class C>
inline bool operator()(const C& res_cont_1, const C& res_cont_2) const {
return res_cont_1.cost <= res_cont_2.cost && res_cont_1.time <= res_cont_2.time;
}
};
struct resource_container
{
resource_container(int c, int t) : cost(c), time(t) {}
int cost; // minimise cost
int time; // a fake time constraints
};
bool operator==(
const resource_container& res_cont_1, const resource_container& res_cont_2)
{
return (res_cont_1.cost == res_cont_2.cost
&& res_cont_1.time == res_cont_2.time);
}
bool operator<(
const resource_container& res_cont_1, const resource_container& res_cont_2)
{
if (res_cont_1.cost > res_cont_2.cost)
return false;
if (res_cont_1.cost == res_cont_2.cost)
return res_cont_1.time < res_cont_2.time;
return true;
}
struct extension_function {
template <typename GraphType>
bool operator()(const GraphType& graph,
resource_container& new_cont,
const resource_container& old_cont,
const typename GraphType::edge_descriptor& edge) const {
new_cont = old_cont;
new_cont.cost = old_cont.cost + graph[edge].cost;
// here I could check tme constraint, but for this example does not matter
new_cont.time = old_cont.time + graph[edge].time;
return true;
}
};
resource_container run_rcsp(const graph_type& graph, vertex_type source, vertex_type target) {
const auto vertex_index_map = boost::get(boost::vertex_index, graph);
const auto edge_index_map = boost::get(boost::edge_all, graph);
boost::default_r_c_shortest_paths_allocator label_allocator{};
path_type single_solution;
resource_container single_resource(0, 0);
const resource_container start_resource(0, 0);
boost::r_c_shortest_paths(graph, vertex_index_map, edge_index_map, source, target, single_solution, single_resource,
start_resource, extension_function{}, dominance{}, label_allocator,
boost::default_r_c_shortest_paths_visitor());
return single_resource;
}
int main() {
graph_type graph;
/*
(1,0) (10, 1)
/-----> [A] ------\
[s] [t]
\-----> [B] ------/
(2, 1) (3,1)
The shortest path is s->B->t with cost 5.
*/
const auto s = boost::add_vertex("s", graph);
const auto A = boost::add_vertex("A", graph);
const auto B = boost::add_vertex("B", graph);
const auto t = boost::add_vertex("t", graph);
boost::add_edge(s, A, edge_prop(1, 0), graph);
boost::add_edge(s, B, edge_prop(2, 1), graph);
boost::add_edge(A, t, edge_prop(10, 0), graph);
boost::add_edge(B, t, edge_prop(3, 1), graph);
const auto solution_resource_container = run_rcsp(graph, s, t);
BOOST_TEST(solution_resource_container.cost == 5);
return boost::report_errors();
}
+1 -1
View File
@@ -45,7 +45,7 @@ template < typename Graph > void test()
{
typedef erdos_renyi_iterator< boost::minstd_rand, Graph > er;
// Generate random graphs with 15 vertices and 15% probability
// Generate random graph with N vertices and probability P
// of edge connection.
static const size_t N = 20;
static const double P = 0.1;