mirror of
https://github.com/boostorg/graph.git
synced 2026-07-21 13:23:42 +00:00
Compare commits
163 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 198616d896 | |||
| 5557ccf921 | |||
| 17acf25da7 | |||
| 64a3bae4f2 | |||
| 05aa9fd816 | |||
| c71ceb8486 | |||
| 9c0ceda4c8 | |||
| 5007b01ad5 | |||
| 8126d97989 | |||
| 2154398906 | |||
| b8150fac82 | |||
| 06339d6f44 | |||
| e7d0adb472 | |||
| a3fffa9c2b | |||
| 6caa0baaec | |||
| 044c7d65a5 | |||
| 2e7d74b1a0 | |||
| 71cea99db3 | |||
| b9fbc47bbb | |||
| 2c36c0f819 | |||
| 2f5a3c2ccc | |||
| db7b3736d6 | |||
| 8f3139bed4 | |||
| 0be4c876bd | |||
| 5ec4327816 | |||
| 4375631fa6 | |||
| 81ead6e595 | |||
| 158eebd082 | |||
| fa8caeeffa | |||
| 33a2510c54 | |||
| 57fdbf4093 | |||
| 3fd626fa71 | |||
| 46a2823a94 | |||
| 46ddc517a2 | |||
| 9c9f9f4b49 | |||
| a052dcdd06 | |||
| 72cad02a0b | |||
| a7c3845f28 | |||
| e522561485 | |||
| 1f6bb4adfa | |||
| a63690ac60 | |||
| 3d6b1d4c9b | |||
| 5235d7dd49 | |||
| 372355b045 | |||
| fa2636d69d | |||
| e94408cf41 | |||
| 8dc51f8bdc | |||
| 52c216c0aa | |||
| f3158683b5 | |||
| 77c07d131e | |||
| 2e63766abb | |||
| f2d0ae7827 | |||
| d09128fc7b | |||
| 0fd61671ae | |||
| c3574b1f2d | |||
| e5ccf7977e | |||
| 3e2b86ab81 | |||
| 2cff7c5207 | |||
| 7a469ec47a | |||
| 1a3dab98cd | |||
| b48bf93057 | |||
| 942829ee68 | |||
| 4fc6b0b65e | |||
| 9f36ca3a1d | |||
| 047fff647f | |||
| 2097d8ffed | |||
| 98e7bfa10a | |||
| ec28611026 | |||
| b14f16b472 | |||
| 41aa91891d | |||
| 38efd9dc1d | |||
| 8c9f2dcaf5 | |||
| ee2cdcc805 | |||
| e56883f789 | |||
| 0182f7490e | |||
| 05e099335a | |||
| 5ef6a074e7 | |||
| 2573812229 | |||
| b5fa4d9758 | |||
| 12a57f9c01 | |||
| 985bfbd765 | |||
| 634f5fb1dd | |||
| a981db8b1f | |||
| a3001ec2e6 | |||
| 5308f29b6a | |||
| eb0ab8bd4b | |||
| 0714892239 | |||
| 0fb5562d43 | |||
| 088714f052 | |||
| 4d968a2972 | |||
| 1cf87d5558 | |||
| b460995095 | |||
| 2eea120320 | |||
| 21a9c6588f | |||
| aa0a4d3c93 | |||
| e8e47eacbb | |||
| 68ee7972df | |||
| 04a213038c | |||
| d95b3d477d | |||
| 5a9e2aa794 | |||
| a07f3532ad | |||
| e17d6f9ff8 | |||
| b9509fd9a8 | |||
| 00028767d8 | |||
| 1cf05f2b3f | |||
| b33c1eb37d | |||
| 5ccd0852b7 | |||
| a3148837c2 | |||
| 231de4c573 | |||
| f58f3df2bf | |||
| 3f75ea7aa3 | |||
| c9f515347b | |||
| 6f1f605ac8 | |||
| dd77077747 | |||
| ed75fd3e03 | |||
| a487ba019d | |||
| e9852ef6a0 | |||
| a649be53bd | |||
| 2862644154 | |||
| f62a1839bd | |||
| 3600dbc226 | |||
| 01020b0265 | |||
| fcfc152f85 | |||
| ea24532da5 | |||
| 944d9fc836 | |||
| 446dc15cf8 | |||
| 44632af1a9 | |||
| 5f4ce096f8 | |||
| 393c31d148 | |||
| 73149e556b | |||
| 3b6d40011b | |||
| 797530d23a | |||
| 2e4b9c461a | |||
| 3b6825958a | |||
| fa6aa57529 | |||
| 430f61f696 | |||
| 51f7f20cb6 | |||
| 71fed2fda8 | |||
| 76aed24add | |||
| c583bfa197 | |||
| fa3bd05312 | |||
| 99d0414416 | |||
| 31026c4a5a | |||
| 5f6e128c16 | |||
| 1e200701f8 | |||
| 8543c8ad78 | |||
| f2e5ef1b40 | |||
| f6fc9c8157 | |||
| 0486e91d1b | |||
| 0defbbc323 | |||
| b657cf3901 | |||
| 5ff3645af6 | |||
| 84232b46c0 | |||
| b76ffc7f2a | |||
| 972bde3031 | |||
| 8c76c8aa01 | |||
| 4879e70593 | |||
| 27202068ea | |||
| 6e1f68ef22 | |||
| bb4fbd6494 | |||
| 64aa4a822a | |||
| e5f9471984 | |||
| 70d7fca2ce |
-83
@@ -14,150 +14,67 @@ 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),
|
||||
linux_cxx("g++-9 2a", "g++-9", packages="g++-9", buildtype="boost", image="cppalliance/droneubuntu1404:1", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-9', 'CXXSTD': '2a', }, globalenv=globalenv),
|
||||
|
||||
linux_cxx("g++-10 03", "g++-10", packages="g++-10", image="cppalliance/droneubuntu2004:1", buildtype="boost", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-10', 'CXXSTD': '03', }, globalenv=globalenv),
|
||||
linux_cxx("g++-10 11", "g++-10", packages="g++-10", image="cppalliance/droneubuntu2004:1", buildtype="boost", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-10', 'CXXSTD': '11', }, globalenv=globalenv),
|
||||
linux_cxx("g++-10 14", "g++-10", packages="g++-10", image="cppalliance/droneubuntu2004:1", buildtype="boost", environment={'TOOLSET': 'gcc', 'COMPILER': 'g++-10', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
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),
|
||||
|
||||
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),
|
||||
osx_cxx("XCode-7.3 14", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '14', }, globalenv=globalenv),
|
||||
osx_cxx("XCode-7.3 1z", "clang++", packages="", buildtype="boost", xcode_version="7.3", environment={'TOOLSET': 'clang', 'COMPILER': 'clang++', 'CXXSTD': '1z', }, globalenv=globalenv),
|
||||
]
|
||||
|
||||
# from https://github.com/boostorg/boost-ci
|
||||
|
||||
+50
-95
@@ -12,7 +12,9 @@ jobs:
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
compiler: [ g++-9, g++-10, clang++-10 ]
|
||||
# Removed g++-10 because of an ICE; meant to be fixed in 10.2?
|
||||
# https://gcc.gnu.org/bugzilla/show_bug.cgi?id=94938
|
||||
compiler: [ g++-9, clang++-10 ]
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
with:
|
||||
@@ -27,7 +29,7 @@ jobs:
|
||||
- name: Add repository
|
||||
run: sudo apt-add-repository -y "ppa:ubuntu-toolchain-r/test"
|
||||
- name: Install packages
|
||||
run: sudo apt install g++-9 g++-10 clang-10
|
||||
run: sudo apt install g++-9 clang-10
|
||||
- name: Checkout main boost
|
||||
run: git clone -b develop --depth 1 https://github.com/boostorg/boost.git ../boost-root
|
||||
- name: Update tools/boostdep
|
||||
@@ -49,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
|
||||
@@ -134,54 +89,13 @@ 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-latest
|
||||
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-latest
|
||||
runs-on: windows-2019
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
@@ -221,3 +135,44 @@ jobs:
|
||||
- name: Test
|
||||
run: ..\..\..\b2 --hash address-model=64 cxxstd=14,17,20 toolset=msvc-14.2
|
||||
working-directory: ../boost-root/libs/graph/test
|
||||
windows_msvc_14_3:
|
||||
runs-on: windows-2022
|
||||
defaults:
|
||||
run:
|
||||
shell: cmd
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
toolset: [ msvc-14.3 ]
|
||||
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,20 address-model=64 toolset=msvc-14.3
|
||||
working-directory: ../boost-root/libs/config/test
|
||||
- name: Test
|
||||
run: ..\..\..\b2 --hash address-model=64 cxxstd=14,17,20 toolset=msvc-14.3
|
||||
working-directory: ../boost-root/libs/graph/test
|
||||
|
||||
@@ -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/
|
||||
|
||||
@@ -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
|
||||
|
||||
+2
-1
@@ -87,7 +87,8 @@ This describes the ways in which the vertices and edges of the
|
||||
graph can be visited. The choices are <TT>incidence_graph_tag</TT>,
|
||||
<TT>adjacency_graph_tag</TT>, <TT>bidirectional_graph_tag</TT>,
|
||||
<TT>vertex_list_graph_tag</TT>, <TT>edge_list_graph_tag</TT>, and
|
||||
<TT>adjacency_matrix_tag</TT>.
|
||||
<TT>adjacency_matrix_tag</TT>. You can also create your own
|
||||
tag which should inherit from one or more of the above.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
+1
-1
@@ -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>
|
||||
|
||||
@@ -52,7 +52,7 @@ colors c<sub>1</sub>, c<sub>2</sub>, ..., c<sub>n</sub> in a way
|
||||
that no vertex connects with 2 edges of the same color. Furthermore
|
||||
at most m + 1 colors are used.
|
||||
|
||||
<!-- King, I.P. An automatic reordering scheme for simultaneous equations derived from network analysis. Int. J. Numer. Methods Engrg. 2 (1970), 523-533 -->
|
||||
<!-- Misra, J., & Gries, D. (1992). A constructive proof of Vizing's theorem. In Information Processing Letters. -->
|
||||
|
||||
<h3>Where defined</h3>
|
||||
<a href="../../../boost/graph/edge_coloring.hpp"><tt>boost/graph/edge_coloring.hpp</tt></a>
|
||||
@@ -80,7 +80,7 @@ OUT: <tt>ColorMap color</tt>
|
||||
<h3>Example</h3>
|
||||
|
||||
See <A
|
||||
href="../example/edge_coloring.cpp"><tt>example/king_ordering.cpp</tt></A>.
|
||||
href="../example/edge_coloring.cpp"><tt>example/edge_coloring.cpp</tt></A>.
|
||||
|
||||
<h3>See Also</h3>
|
||||
|
||||
|
||||
@@ -200,9 +200,9 @@ The ways in which the vertices in the graph can be traversed.
|
||||
The traversal category tags are:
|
||||
<tt>incidence_graph_tag, adjacency_graph_tag,
|
||||
bidirectional_graph_tag, vertex_list_graph_tag,
|
||||
edge_list_graph_tag, vertex_and_edge_list_graph_tag,
|
||||
edge_list_graph_tag,
|
||||
adjacency_matrix_tag</tt>. You can also create your own
|
||||
tag which should inherit from one of the above.
|
||||
tag which should inherit from one or more of the above.
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
|
||||
@@ -13,13 +13,13 @@
|
||||
<h1 id="hawick_circuits"><code>hawick_circuits</code></h1>
|
||||
|
||||
<pre><code>template <typename Graph, typename Visitor, typename VertexIndexMap>
|
||||
void hawick_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& vim = get(vertex_index, graph));
|
||||
void hawick_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& vim = get(vertex_index, graph), unsigned int max_length = 0);
|
||||
|
||||
template <typename Graph, typename Visitor, typename VertexIndexMap>
|
||||
void hawick_unique_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& vim = get(vertex_index, graph));
|
||||
void hawick_unique_circuits(Graph const& graph, Visitor visitor, VertexIndexMap const& 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 ≤ <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">
|
||||
|
||||
+1
-1
@@ -44,7 +44,7 @@
|
||||
incident(typename graph_traits<Graph>::edge_descriptor e, Graph& g)
|
||||
</pre>
|
||||
|
||||
This function takes and edge descriptor and returns the pair of
|
||||
This function takes an edge descriptor and returns the pair of
|
||||
vertices that are <i>incident</i> to the edge. For directed graphs,
|
||||
the <tt>first</tt> vertex is the source and the <tt>second</tt> vertex
|
||||
is the target. This function is equivalent to the expression
|
||||
|
||||
+8
-15
@@ -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>
|
||||
|
||||
@@ -57,7 +57,7 @@ void r_c_shortest_paths( const Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor t,
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor>& pareto_optimal_solution,
|
||||
Resource_Container>& pareto_optimal_resource_container,
|
||||
Resource_Container& pareto_optimal_resource_container,
|
||||
const Resource_Container& rc,
|
||||
const Resource_Extension_Function& ref,
|
||||
const Dominance_Function& dominance,
|
||||
@@ -93,7 +93,7 @@ void r_c_shortest_paths( const Graph& g,
|
||||
typename graph_traits<Graph>::vertex_descriptor s,
|
||||
typename graph_traits<Graph>::vertex_descriptor t,
|
||||
std::vector<typename graph_traits<Graph>::edge_descriptor>& pareto_optimal_solution,
|
||||
Resource_Container>& pareto_optimal_resource_container,
|
||||
Resource_Container& pareto_optimal_resource_container,
|
||||
const Resource_Container& rc,
|
||||
const Resource_Extension_Function& ref,
|
||||
const Dominance_Function& 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>
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ void random_spanning_tree(const Graph& g, Gen& gen, vertex_descriptor ro
|
||||
<p>
|
||||
The <tt>random_spanning_tree()</tt> function generates a random spanning tree
|
||||
on a directed or undirected graph. The algorithm used is Wilson's algorithm (<a
|
||||
href="bibliography.html#wilson96generating">73</a>, based on <!-- (FIXME: add
|
||||
href="bibliography.html#wilson96generating">73</a>), based on <!-- (FIXME: add
|
||||
documentation for loop_erased_random_walk()) <a
|
||||
href="loop_erased_random_walk.html"> -->loop-erased random walks<!-- </a> -->. There must
|
||||
be a path from every non-root vertex of the graph to the root;
|
||||
|
||||
@@ -181,8 +181,8 @@ bool status = read_graphviz(gvgraph,graph,dp,"node_id");
|
||||
<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 "boost_graph" and "boost_regex" 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 "boost_graph" 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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -40,6 +40,7 @@ or form.</p>
|
||||
<li><a href="http://www.vrjuggler.org/">VR Juggler: Virtual Reality Tools</a></li>
|
||||
<li><a href="http://hyperworx.org">Hyperworx Platform Project</a></li>
|
||||
<li><a href="http://www.opencog.org/">OpenCog, an open source Artificial General Intelligence framework</a></li>
|
||||
<li><a href="https://www.pgRouting.org/">pgRouting extends the PostGIS/PostgreSQL geospatial database to provide geospatial routing functionality.</a></li>
|
||||
</ul>
|
||||
|
||||
</body>
|
||||
|
||||
@@ -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[])
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -328,7 +328,6 @@ inline void astar_search_no_init_tree(const VertexListGraph& g,
|
||||
BOOST_THROW_EXCEPTION(negative_edge());
|
||||
bool decreased
|
||||
= relax(e, g, weight, predecessor, distance, combine, compare);
|
||||
combine(get(distance, v), e_weight);
|
||||
if (decreased)
|
||||
{
|
||||
vis.edge_relaxed(e, g);
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -977,7 +977,7 @@ boykov_kolmogorov_max_flow(Graph& g, CapacityEdgeMap cap,
|
||||
}
|
||||
|
||||
/**
|
||||
* non-named-parameter version, given capacity, residucal_capacity,
|
||||
* non-named-parameter version, given capacity, residual_capacity,
|
||||
* reverse_edges, and an index map.
|
||||
*/
|
||||
template < class Graph, class CapacityEdgeMap, class ResidualCapacityEdgeMap,
|
||||
@@ -1029,8 +1029,7 @@ boykov_kolmogorov_max_flow(Graph& g, CapacityEdgeMap cap,
|
||||
* named-parameter version, some given
|
||||
*/
|
||||
template < class Graph, class P, class T, class R >
|
||||
typename property_traits<
|
||||
typename property_map< Graph, edge_capacity_t >::const_type >::value_type
|
||||
typename detail::edge_capacity_value< Graph, P, T, R >::type
|
||||
boykov_kolmogorov_max_flow(Graph& g,
|
||||
typename graph_traits< Graph >::vertex_descriptor src,
|
||||
typename graph_traits< Graph >::vertex_descriptor sink,
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -2069,15 +2069,20 @@ namespace detail
|
||||
inline void reindex_edge_list(
|
||||
EdgeList& el, vertex_descriptor u, boost::disallow_parallel_edge_tag)
|
||||
{
|
||||
for (typename EdgeList::iterator ei = el.begin(); ei != el.end(); ++ei)
|
||||
typename EdgeList::iterator ei = el.begin(), e_end = el.end();
|
||||
while (ei != e_end)
|
||||
{
|
||||
if (ei->get_target() > u)
|
||||
{
|
||||
typename EdgeList::value_type ce = *ei;
|
||||
++ei;
|
||||
el.erase(ce);
|
||||
--ce.get_target();
|
||||
el.insert(ce);
|
||||
}
|
||||
else {
|
||||
++ei;
|
||||
}
|
||||
}
|
||||
}
|
||||
} // namespace detail
|
||||
@@ -2184,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;
|
||||
|
||||
@@ -204,10 +204,10 @@ private:
|
||||
// Get the parent of a given node in the heap
|
||||
static size_type parent(size_type index) { return (index - 1) / Arity; }
|
||||
|
||||
// Get the child_idx'th child of a given node; 0 <= child_idx < Arity
|
||||
static size_type child(size_type index, std::size_t child_idx)
|
||||
// Get the first child of a given node
|
||||
static size_type first_child(size_type index)
|
||||
{
|
||||
return index * Arity + child_idx + 1;
|
||||
return index * Arity + 1;
|
||||
}
|
||||
|
||||
// Swap two elements in the heap by index, updating index_in_heap
|
||||
@@ -304,7 +304,7 @@ private:
|
||||
Value* data_ptr = &data[0];
|
||||
for (;;)
|
||||
{
|
||||
size_type first_child_index = child(index, 0);
|
||||
size_type first_child_index = first_child(index);
|
||||
if (first_child_index >= heap_size)
|
||||
break; /* No children */
|
||||
Value* child_base_ptr = data_ptr + first_child_index;
|
||||
|
||||
@@ -55,8 +55,9 @@ namespace detail
|
||||
(ReadablePropertyMapConcept< DistanceMap, Vertex >));
|
||||
BOOST_CONCEPT_ASSERT((NumericValueConcept< Distance >));
|
||||
typedef numeric_values< Distance > DistanceNumbers;
|
||||
BOOST_CONCEPT_ASSERT((AdaptableBinaryFunction< Combinator, Distance,
|
||||
Distance, Distance >));
|
||||
// NOTE: Disabled until this concept assert is fixed in Boost.ConceptCheck.
|
||||
// BOOST_CONCEPT_ASSERT((AdaptableBinaryFunction< Combinator, Distance,
|
||||
// Distance, Distance >));
|
||||
|
||||
// If there's ever an infinite distance, then we simply return
|
||||
// infinity. Note that this /will/ include the a non-zero
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -27,8 +27,9 @@ struct mean_geodesic_measure
|
||||
BOOST_CONCEPT_ASSERT((VertexListGraphConcept< Graph >));
|
||||
BOOST_CONCEPT_ASSERT((NumericValueConcept< DistanceType >));
|
||||
BOOST_CONCEPT_ASSERT((NumericValueConcept< ResultType >));
|
||||
BOOST_CONCEPT_ASSERT((AdaptableBinaryFunctionConcept< Divides,
|
||||
ResultType, ResultType, ResultType >));
|
||||
// NOTE: Disabled until this concept assert is fixed in Boost.ConceptCheck.
|
||||
// BOOST_CONCEPT_ASSERT((AdaptableBinaryFunctionConcept< Divides,
|
||||
// ResultType, ResultType, ResultType >));
|
||||
|
||||
return (d == base_type::infinite_distance())
|
||||
? base_type::infinite_result()
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
};
|
||||
|
||||
@@ -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());
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -29,94 +29,130 @@ namespace boost
|
||||
|
||||
namespace detail
|
||||
{
|
||||
template < typename ParityMap, typename WeightMap, typename IndexMap >
|
||||
class mas_min_cut_visitor : public boost::default_mas_visitor
|
||||
/**
|
||||
* \brief Performs a phase of the Stoer-Wagner min-cut algorithm
|
||||
*
|
||||
* Performs a phase of the Stoer-Wagner min-cut algorithm.
|
||||
*
|
||||
* As described by Stoer & Wagner (1997), a phase is simply a maximum
|
||||
* adjacency search (also called a maximum cardinality search), which
|
||||
* results in the selection of two vertices \em s and \em t, and, as a side
|
||||
* product, a minimum <em>s</em>-<em>t</em> cut of the input graph. Here,
|
||||
* the input graph is basically \p g, but some vertices are virtually
|
||||
* assigned to others as a way of viewing \p g as a graph with some sets of
|
||||
* vertices merged together.
|
||||
*
|
||||
* This implementation is a translation of pseudocode by Professor Uri
|
||||
* Zwick, School of Computer Science, Tel Aviv University.
|
||||
*
|
||||
* \pre \p g is a connected, undirected graph
|
||||
* \param[in] g the input graph
|
||||
* \param[in] assignments a read/write property map from each vertex to the
|
||||
* vertex that it is assigned to
|
||||
* \param[in] assignedVertices a list of vertices that are assigned to
|
||||
* others
|
||||
* \param[in] weights a readable property map from each edge to its
|
||||
* weight (a non-negative value)
|
||||
* \param[out] pq a keyed, updatable max-priority queue
|
||||
* \returns a tuple (\em s, \em t, \em w) of the "<em>s</em>" and
|
||||
* "<em>t</em>" of the minimum <em>s</em>-<em>t</em> cut and the
|
||||
* cut weight \em w of the minimum <em>s</em>-<em>t</em> cut.
|
||||
* \see http://www.cs.tau.ac.il/~zwick/grad-algo-08/gmc.pdf
|
||||
*
|
||||
* \author Daniel Trebbien
|
||||
* \date 2010-09-11
|
||||
*/
|
||||
template < class UndirectedGraph, class VertexAssignmentMap,
|
||||
class WeightMap, class KeyedUpdatablePriorityQueue >
|
||||
boost::tuple<
|
||||
typename boost::graph_traits< UndirectedGraph >::vertex_descriptor,
|
||||
typename boost::graph_traits< UndirectedGraph >::vertex_descriptor,
|
||||
typename boost::property_traits< WeightMap >::value_type >
|
||||
stoer_wagner_phase(const UndirectedGraph& g,
|
||||
VertexAssignmentMap assignments,
|
||||
const std::set< typename boost::graph_traits<
|
||||
UndirectedGraph >::vertex_descriptor >& assignedVertices,
|
||||
WeightMap weights, KeyedUpdatablePriorityQueue& pq)
|
||||
{
|
||||
typedef one_bit_color_map< IndexMap > InternalParityMap;
|
||||
typedef
|
||||
typename boost::graph_traits< UndirectedGraph >::vertex_descriptor
|
||||
vertex_descriptor;
|
||||
typedef typename boost::property_traits< WeightMap >::value_type
|
||||
weight_type;
|
||||
|
||||
public:
|
||||
template < typename Graph >
|
||||
mas_min_cut_visitor(const Graph& g, ParityMap parity,
|
||||
weight_type& cutweight, const WeightMap& weight_map,
|
||||
IndexMap index_map)
|
||||
: m_bestParity(parity)
|
||||
, m_parity(make_one_bit_color_map(num_vertices(g), index_map))
|
||||
, m_bestWeight(cutweight)
|
||||
, m_cutweight(0)
|
||||
, m_visited(0)
|
||||
, m_weightMap(weight_map)
|
||||
BOOST_ASSERT(pq.empty());
|
||||
typename KeyedUpdatablePriorityQueue::key_map keys = pq.keys();
|
||||
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
// set here since the init list sets the reference
|
||||
m_bestWeight = (std::numeric_limits< weight_type >::max)();
|
||||
}
|
||||
if (v == get(assignments, v))
|
||||
{ // foreach u \in V do
|
||||
put(keys, v, weight_type(0));
|
||||
|
||||
template < typename Vertex, typename Graph >
|
||||
void initialize_vertex(Vertex u, const Graph& g)
|
||||
{
|
||||
typedef typename boost::property_traits< ParityMap >::value_type
|
||||
parity_type;
|
||||
typedef
|
||||
typename boost::property_traits< InternalParityMap >::value_type
|
||||
internal_parity_type;
|
||||
|
||||
put(m_parity, u, internal_parity_type(0));
|
||||
put(m_bestParity, u, parity_type(0));
|
||||
}
|
||||
|
||||
template < typename Edge, typename Graph >
|
||||
void examine_edge(Edge e, const Graph& g)
|
||||
{
|
||||
weight_type w = get(m_weightMap, e);
|
||||
|
||||
// if the target of e is already marked then decrease cutweight
|
||||
// otherwise, increase it
|
||||
if (get(m_parity, boost::target(e, g)))
|
||||
{
|
||||
m_cutweight -= w;
|
||||
}
|
||||
else
|
||||
{
|
||||
m_cutweight += w;
|
||||
pq.push(v);
|
||||
}
|
||||
}
|
||||
|
||||
template < typename Vertex, typename Graph >
|
||||
void finish_vertex(Vertex u, const Graph& g)
|
||||
{
|
||||
typedef
|
||||
typename boost::property_traits< InternalParityMap >::value_type
|
||||
internal_parity_type;
|
||||
BOOST_ASSERT(pq.size() >= 2);
|
||||
|
||||
++m_visited;
|
||||
put(m_parity, u, internal_parity_type(1));
|
||||
vertex_descriptor s
|
||||
= boost::graph_traits< UndirectedGraph >::null_vertex();
|
||||
vertex_descriptor t
|
||||
= boost::graph_traits< UndirectedGraph >::null_vertex();
|
||||
weight_type w;
|
||||
while (!pq.empty())
|
||||
{ // while PQ \neq {} do
|
||||
const vertex_descriptor u = pq.top(); // u = extractmax(PQ)
|
||||
w = get(keys, u);
|
||||
pq.pop();
|
||||
|
||||
if (m_cutweight < m_bestWeight && m_visited < num_vertices(g))
|
||||
s = t;
|
||||
t = u;
|
||||
|
||||
BGL_FORALL_OUTEDGES_T(u, e, g, UndirectedGraph)
|
||||
{ // foreach (u, v) \in E do
|
||||
const vertex_descriptor v = get(assignments, target(e, g));
|
||||
|
||||
if (pq.contains(v))
|
||||
{ // if v \in PQ then
|
||||
put(keys, v,
|
||||
get(keys, v)
|
||||
+ get(weights,
|
||||
e)); // increasekey(PQ, v, wA(v) + w(u, v))
|
||||
pq.update(v);
|
||||
}
|
||||
}
|
||||
|
||||
typename std::set< vertex_descriptor >::const_iterator
|
||||
assignedVertexIt,
|
||||
assignedVertexEnd = assignedVertices.end();
|
||||
for (assignedVertexIt = assignedVertices.begin();
|
||||
assignedVertexIt != assignedVertexEnd; ++assignedVertexIt)
|
||||
{
|
||||
m_bestWeight = m_cutweight;
|
||||
BGL_FORALL_VERTICES_T(i, g, Graph)
|
||||
const vertex_descriptor uPrime = *assignedVertexIt;
|
||||
|
||||
if (get(assignments, uPrime) == u)
|
||||
{
|
||||
put(m_bestParity, i, get(m_parity, i));
|
||||
BGL_FORALL_OUTEDGES_T(uPrime, e, g, UndirectedGraph)
|
||||
{ // foreach (u, v) \in E do
|
||||
const vertex_descriptor v
|
||||
= get(assignments, target(e, g));
|
||||
|
||||
if (pq.contains(v))
|
||||
{ // if v \in PQ then
|
||||
put(keys, v,
|
||||
get(keys, v)
|
||||
+ get(weights, e)); // increasekey(PQ, v,
|
||||
// wA(v) + w(u, v))
|
||||
pq.update(v);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline void clear()
|
||||
{
|
||||
m_bestWeight = (std::numeric_limits< weight_type >::max)();
|
||||
m_visited = 0;
|
||||
m_cutweight = 0;
|
||||
}
|
||||
|
||||
private:
|
||||
ParityMap m_bestParity;
|
||||
InternalParityMap m_parity;
|
||||
weight_type& m_bestWeight;
|
||||
weight_type m_cutweight;
|
||||
unsigned m_visited;
|
||||
const WeightMap& m_weightMap;
|
||||
};
|
||||
return boost::make_tuple(s, t, w);
|
||||
}
|
||||
|
||||
/**
|
||||
* \brief Computes a min-cut of the input graph
|
||||
@@ -156,44 +192,71 @@ namespace detail
|
||||
vertex_descriptor;
|
||||
typedef typename boost::property_traits< WeightMap >::value_type
|
||||
weight_type;
|
||||
typedef
|
||||
typename boost::graph_traits< UndirectedGraph >::vertices_size_type
|
||||
vertices_size_type;
|
||||
typedef typename boost::property_traits< ParityMap >::value_type
|
||||
parity_type;
|
||||
|
||||
typename graph_traits< UndirectedGraph >::vertex_iterator u_iter, u_end;
|
||||
vertices_size_type n = num_vertices(g);
|
||||
|
||||
weight_type bestW = (std::numeric_limits< weight_type >::max)();
|
||||
weight_type bestThisTime = (std::numeric_limits< weight_type >::max)();
|
||||
vertex_descriptor bestStart
|
||||
= boost::graph_traits< UndirectedGraph >::null_vertex();
|
||||
std::set< vertex_descriptor > assignedVertices;
|
||||
|
||||
detail::mas_min_cut_visitor< ParityMap, WeightMap, IndexMap > vis(
|
||||
g, parities, bestThisTime, weights, index_map);
|
||||
// initialize `assignments` (all vertices are initially assigned to
|
||||
// themselves)
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph) { put(assignments, v, v); }
|
||||
|
||||
// for each node in the graph,
|
||||
for (boost::tie(u_iter, u_end) = vertices(g); u_iter != u_end; ++u_iter)
|
||||
vertex_descriptor s, t;
|
||||
weight_type bestW;
|
||||
|
||||
boost::tie(s, t, bestW) = boost::detail::stoer_wagner_phase(
|
||||
g, assignments, assignedVertices, weights, pq);
|
||||
BOOST_ASSERT(s != t);
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
// run the MAS and find the min cut
|
||||
vis.clear();
|
||||
boost::maximum_adjacency_search(g,
|
||||
boost::weight_map(weights)
|
||||
.visitor(vis)
|
||||
.root_vertex(*u_iter)
|
||||
.vertex_assignment_map(assignments)
|
||||
.max_priority_queue(pq));
|
||||
if (bestThisTime < bestW)
|
||||
put(parities, v, parity_type(v == t ? 1 : 0));
|
||||
}
|
||||
put(assignments, t, s);
|
||||
assignedVertices.insert(t);
|
||||
--n;
|
||||
|
||||
for (; n >= 2; --n)
|
||||
{
|
||||
weight_type w;
|
||||
boost::tie(s, t, w) = boost::detail::stoer_wagner_phase(
|
||||
g, assignments, assignedVertices, weights, pq);
|
||||
BOOST_ASSERT(s != t);
|
||||
|
||||
if (w < bestW)
|
||||
{
|
||||
bestW = bestThisTime;
|
||||
bestStart = *u_iter;
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
put(parities, v,
|
||||
parity_type(get(assignments, v) == t ? 1 : 0));
|
||||
|
||||
if (get(assignments, v)
|
||||
== t) // all vertices that were assigned to t are now
|
||||
// assigned to s
|
||||
put(assignments, v, s);
|
||||
}
|
||||
|
||||
bestW = w;
|
||||
}
|
||||
else
|
||||
{
|
||||
BGL_FORALL_VERTICES_T(v, g, UndirectedGraph)
|
||||
{
|
||||
if (get(assignments, v)
|
||||
== t) // all vertices that were assigned to t are now
|
||||
// assigned to s
|
||||
put(assignments, v, s);
|
||||
}
|
||||
}
|
||||
put(assignments, t, s);
|
||||
assignedVertices.insert(t);
|
||||
}
|
||||
|
||||
// Run one more time, starting from the best start location, to
|
||||
// ensure the visitor has the best values.
|
||||
vis.clear();
|
||||
boost::maximum_adjacency_search(g,
|
||||
boost::vertex_assignment_map(assignments)
|
||||
.weight_map(weights)
|
||||
.visitor(vis)
|
||||
.root_vertex(bestStart)
|
||||
.max_priority_queue(pq));
|
||||
BOOST_ASSERT(pq.empty());
|
||||
|
||||
return bestW;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -82,7 +82,7 @@ void transitive_closure(const Graph& g, GraphTC& tc,
|
||||
iterator_property_map< cg_vertex*, VertexIndexMap, cg_vertex, cg_vertex& >
|
||||
component_number(&component_number_vec[0], index_map);
|
||||
|
||||
int num_scc
|
||||
const cg_vertex num_scc
|
||||
= strong_components(g, component_number, vertex_index_map(index_map));
|
||||
|
||||
std::vector< std::vector< vertex > > components;
|
||||
@@ -107,12 +107,11 @@ void transitive_closure(const Graph& g, GraphTC& tc,
|
||||
}
|
||||
}
|
||||
std::sort(adj.begin(), adj.end());
|
||||
typename std::vector< cg_vertex >::iterator di
|
||||
const typename std::vector< cg_vertex >::iterator di
|
||||
= std::unique(adj.begin(), adj.end());
|
||||
if (di != adj.end())
|
||||
adj.erase(di, adj.end());
|
||||
|
||||
for (typename std::vector< cg_vertex >::const_iterator i = adj.begin();
|
||||
i != adj.end(); ++i)
|
||||
i != di; ++i)
|
||||
{
|
||||
add_edge(s, *i, CG);
|
||||
}
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
{
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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 ]
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -72,7 +72,7 @@ fill_random_max_flow_graph(Graph& g, CapacityMap cap, ReverseEdgeMap rev,
|
||||
// cannot use this, as we have no idea how properties are stored, right?
|
||||
typename graph_traits< Graph >::edge_iterator ei, e_end;
|
||||
for (boost::tie(ei, e_end) = edges(g); ei != e_end; ++ei)
|
||||
cap[*ei] = int_gen();
|
||||
put(cap, *ei, int_gen());
|
||||
|
||||
// get source and sink node
|
||||
vertex_descriptor s = random_vertex(g, gen);
|
||||
@@ -96,9 +96,9 @@ fill_random_max_flow_graph(Graph& g, CapacityMap cap, ReverseEdgeMap rev,
|
||||
boost::tie(new_edge, inserted)
|
||||
= add_edge(source_vertex, target_vertex, g);
|
||||
assert(inserted);
|
||||
rev[old_edge] = new_edge;
|
||||
rev[new_edge] = old_edge;
|
||||
cap[new_edge] = 0;
|
||||
put(rev, old_edge, new_edge);
|
||||
put(rev, new_edge, old_edge);
|
||||
put(cap, new_edge, 0);
|
||||
}
|
||||
return std::make_pair(s, t);
|
||||
}
|
||||
@@ -174,34 +174,152 @@ 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;
|
||||
boost::tie(src, sink)
|
||||
= fill_random_max_flow_graph(g, get(&tEdge::edge_capacity, g),
|
||||
get(&tEdge::edge_reverse, g), n_verts, n_edges, seed);
|
||||
return 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), get(&tVertex::vertex_color, g),
|
||||
get(&tVertex::vertex_distance, g), get(vertex_index, g), src, sink);
|
||||
|
||||
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),
|
||||
get(&tVertex::vertex_color, g), get(&tVertex::vertex_distance, g),
|
||||
get(vertex_index, g), src, sink);
|
||||
|
||||
long flow_named_overload = boykov_kolmogorov_max_flow(g, src, sink,
|
||||
capacity_map(get(&tEdge::edge_capacity, g))
|
||||
.residual_capacity_map(get(&tEdge::edge_residual_capacity, g))
|
||||
.reverse_edge_map(get(&tEdge::edge_reverse, g))
|
||||
.predecessor_map(get(&tVertex::vertex_predecessor, g))
|
||||
.color_map(get(&tVertex::vertex_color, g))
|
||||
.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;
|
||||
}
|
||||
|
||||
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;
|
||||
@@ -226,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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -55,5 +55,23 @@ int main(int argc, char* argv[])
|
||||
|
||||
BOOST_TEST(m_graph[ed1] == EDGE_VAL);
|
||||
|
||||
// https://github.com/boostorg/graph/issues/268
|
||||
// 1. Undirected:
|
||||
{
|
||||
boost::adjacency_list<boost::setS, boost::vecS, boost::undirectedS> g;
|
||||
boost::add_edge(2, 0, g);
|
||||
boost::remove_vertex(1, g);
|
||||
BOOST_TEST(num_vertices(g) == 2);
|
||||
BOOST_TEST(num_edges(g) == 1);
|
||||
}
|
||||
// 2. Directed:
|
||||
{
|
||||
boost::adjacency_list<boost::setS, boost::vecS, boost::directedS> g;
|
||||
boost::add_edge(2, 0, g);
|
||||
boost::remove_vertex(1, g);
|
||||
BOOST_TEST(num_vertices(g) == 2);
|
||||
BOOST_TEST(num_edges(g) == 1);
|
||||
}
|
||||
|
||||
return boost::report_errors();
|
||||
}
|
||||
|
||||
+335
-266
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
@@ -184,6 +184,32 @@ void test4()
|
||||
BOOST_TEST_EQ(parity2, get(parities, 7));
|
||||
}
|
||||
|
||||
// Non regression test for github.com/boostorg/graph/issues/286
|
||||
void test5()
|
||||
{
|
||||
edge_t edges[] = { { 0, 1 }, { 0, 2 }, { 0, 3 }, { 1, 2 }, { 1, 3 },
|
||||
{ 2, 3 }, { 4, 5 }, { 4, 6 }, { 4, 7 }, { 5, 6 }, { 5, 7 }, { 6, 7 },
|
||||
{ 0, 4 } };
|
||||
weight_type ws[] = { 3, 3, 3, 2, 2, 2, 3, 3, 3, 2, 2, 2, 6 };
|
||||
undirected_graph g(edges, edges + 13, ws, 8, 13);
|
||||
|
||||
weight_map_type weights = get(boost::edge_weight, g);
|
||||
std::map< int, bool > parity;
|
||||
boost::associative_property_map< std::map< int, bool > > parities(parity);
|
||||
int w
|
||||
= boost::stoer_wagner_min_cut(g, weights, boost::parity_map(parities));
|
||||
BOOST_TEST_EQ(w, 6);
|
||||
const bool parity0 = get(parities, 0);
|
||||
BOOST_TEST_EQ(parity0, get(parities, 1));
|
||||
BOOST_TEST_EQ(parity0, get(parities, 2));
|
||||
BOOST_TEST_EQ(parity0, get(parities, 3));
|
||||
const bool parity4 = get(parities, 4);
|
||||
BOOST_TEST_NE(parity0, parity4);
|
||||
BOOST_TEST_EQ(parity4, get(parities, 5));
|
||||
BOOST_TEST_EQ(parity4, get(parities, 6));
|
||||
BOOST_TEST_EQ(parity4, get(parities, 7));
|
||||
}
|
||||
|
||||
// The input for the `test_prgen` family of tests comes from a program, named
|
||||
// `prgen`, that comes with a package of min-cut solvers by Chandra Chekuri,
|
||||
// Andrew Goldberg, David Karger, Matthew Levine, and Cliff Stein. `prgen` was
|
||||
@@ -285,13 +311,15 @@ void test_prgen_50_70_2()
|
||||
|
||||
int main(int argc, char* argv[])
|
||||
{
|
||||
if (BOOST_TEST(argc == 2)) {
|
||||
if (BOOST_TEST(argc == 2))
|
||||
{
|
||||
test_dir = argv[1];
|
||||
test0();
|
||||
test1();
|
||||
test2();
|
||||
test3();
|
||||
test4();
|
||||
test5();
|
||||
test_prgen_20_70_2();
|
||||
test_prgen_50_70_2();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user